资讯动态

QRLSTM区间预测:LSTM结合分位数回归的MATLAB实现

发布时间:2026/10/25 6:53:46 来源:尧图企业网站定制
简介MATLAB实现QRLSTM长短期记忆神经网络分位数回归时间序列区间预测资源面向需要进行风速、负荷、功率等单变量时序区间预测的研究者与工程师基于LSTM捕获长期依赖结合分位数回归输出不同置信水平下的预测区间适用于非线性时间序列的不确定性建模。压缩包共5个文件含4个.m脚本和1个xlsx示例数据整体仅20KB轻量易读主程序可直接运行分位数回归层脚本用于定义QRLSTM输出层评价脚本用于计算区间覆盖率与平均宽度等指标数据文件采用Excel格式方便替换成业务数据在MATLAB2018及以上环境即可复现。当前已有496人学习下载。通过这份资源可掌握QRLSTM完整建模流程理解分位数损失函数、区间预测评价方法并快速迁移到风速、负荷、功率等实际预测场景中是入门与进阶神经网络区间预测的实用参考。1. 当 LSTM 不直接给预测值时QRLSTM 与 MATLAB 区间预测思路做风速、负荷、功率预测的人最怕被问“你这个 LSTM 预测准不准”。因为点预测只有一个数调度员拿到 850MW 这个数字并不知道误差带是 ±10 还是 ±80。QRLSTM 解决的就是这件事在 MATLAB 里用长短期记忆神经网络LSTM做时序特征提取再用分位数回归输出上界和下界最终给出带置信水平的时间序列区间预测。相比传统点预测它多回答了一个关键问题这个预测值有多可信。这份资源的核心价值是把 LSTM 原来输出单个数值的末端替换成基于分位数损失回归的输出层让同一个网络结构同时给出上限和下限。适合两类人一类是刚接触区间预测、想在 MATLAB 里快速跑通完整流程的从业者另一类是已经在用 LSTM 做点预测、想给结果补上不确定性边界的工程师。2. 分位数回归为什么能配 LSTM从 pinball loss 到条件分位数2.1 点预测的局限与区间预测的实际收益时间序列预测里点预测的损失函数通常是最小化均方误差MSE网络学习的是条件期望 E(y|x)。但调度、交易、检修这类决策场景真正需要的往往不是一个均值而是一个覆盖范围。比如风功率预测并网考核里除了预测精度还有置信区间要求负荷预测里备用容量安排要看最坏情况而不是最好情况。区间预测输出的是一对上下边界同时附带一个置信水平比如“90% 的区间覆盖”。这个信息量远大于孤零零的一个数字。区间预测还有一个隐性收益它能暴露模型的自信程度。当模型对某个时段的预测把握不足时区间会自动变宽把握足时区间变窄。这一点对工程决策特别有价值因为你可以把区间宽度当成一种动态的风险指示器。QRLSTM 的思路就是让 LSTM 在编码时序依赖之后不去逼近期望值而是去逼近条件分位数。2.2 LSTM 如何记忆序列门控机制与长期依赖LSTM 之所以适合时间序列核心在于它引入了门控机制用输入门、遗忘门、输出门控制信息在记忆单元里的写入、保留和读取。相比普通循环神经网络RNNLSTM 能有效缓解梯度消失把几百步之前的有效信息带到当前预测中。这个特性对于风速、负荷这类强自相关、带周期性的序列非常关键。你可以把 LSTM 理解成一个带“过滤系统”的时序编码器每一时刻它决定哪些历史信息该记住哪些该丢掉。在 QRLSTM 组合里LSTM 部分负责的是序列特征提取任务输出的是编码后的时序特征而不是直接输出预测值。分位数回归部分则负责把时序特征映射到多个分位数输出上。这种分工很清晰LSTM 管记忆分位数层管不确定性建模两者通过全连接层衔接。2.3 pinball loss为什么损失函数决定了输出的“位置”分位数回归的损失函数叫分位数损失也叫 pinball loss。对于分位数 τ定义ρ_τ(u) u·(τ − 1{u 0})其中 u 是真实值与预测值的差。当预测低于真实值时u 为负损失为 (τ−1)·u当预测高于真实值时u 为正损失为 τ·u。这个损失函数的最小值点恰好就是条件分位数 Q_y(τ|x)。换句话说你用这个损失去训练网络网络输出逼近的就不是均值而是给定分位数 τ 的条件分位数。这解释了 QRLSTM 的核心机制同一个 LSTM 骨干网络如果把最后的损失从均方误差换成 pinball loss那么输出值的含义就变了。当 τ0.5 时你得到的是条件中位数当 τ0.05 和 τ0.95 时你得到的是 90% 置信区间上下界。网络结构几乎没变变的只是损失函数和输出层维度这是 QRLSTM 在工程上落地成本低的重要原因。提示很多人第一次接触分位数回归会误以为它跟“分箱”或“分位数变换”有关。其实它只是在优化一个非对称的损失函数让模型在不同分位点上的预测产生系统性偏移。3. quanRegressionLayer.m 拆解自定义分位数损失层与 LSTM 网络结构3.1 自定义回归层forwardLoss 怎么算quanRegressionLayer.m 是这个资源里最关键的自定义层。它在 MATLAB 深度学习框架里以自定义 RegressionLayer 的形式存在核心要覆盖的是 forwardLoss 方法。下面给出一个与资源功能等价的简化实现便于你理解内部逻辑classdef quanRegressionLayer nnet.layer.RegressionLayer properties q % 分位数向量例如 [0.05 0.95] end methods function layer quanRegressionLayer(q, name) layer.q q; layer.Name name; layer.Description Quantile regression layer, q mat2str(q); end function loss forwardLoss(layer, Y, T) % Y: 网络输出, 尺寸为 [numQuantiles, batchSize] % T: 真实值, 尺寸为 [1, batchSize] T repmat(T, size(Y,1), 1); diff T - Y; loss 0; for k 1:size(Y,1) q layer.q(k); e diff(k,:); loss loss mean(max(q*e, (q-1)*e)); end loss loss / size(Y,1); end end end这段代码里max(q*e, (q-1)e) 就是 pinball loss 的紧凑写法当 e ≥ 0 时取 qe当 e 0 时取 (q-1)*e。mean 表示对当前 batch 内所有样本求平均多个分位数之间再取均值保证每个分位数都被公平优化。repmat 的作用是把真实值 T 复制成与 Y 相同的行数因为每个分位数都要跟同一个真实值做比较。这个层虽然小但它是 QRLSTM 从“点预测”变成“区间预测”的开关深入理解这一层比跑通代码更有价值。3.2 网络整体结构与参数选型资源里 QRLSTM 的网络结构可以概括为sequenceInputLayer(1) → lstmLayer(隐藏单元) → fullyConnectedLayer(2) → quanRegressionLayer([0.05 0.95])。sequenceInputLayer(1) 表示每个时间步输入一个标量特征因为 data.xlsx 里是单变量序列。lstmLayer 负责提取时序特征输出模式设置为 last只取最后一个时间步的输出避免把每个时间步的结果都送进全连接层。fullyConnectedLayer(2) 的输出维度与分位数个数一致两个输出分别对应 τ0.05 和 τ0.95。训练参数方面常见配置可以参考下面的表格。需要注意这些参数不是死的要按数据量级和序列特性调整参数常见取值调整依据隐藏单元数 lstmLayer32~128序列越长、非线性越强取偏大值分位数向量[0.05 0.95] 或 [0.1 0.5 0.9]需要几个边界就设几个初始学习率0.001~0.01数据噪声大时调小MiniBatchSize32~128数据量小时调小序列长度 seqLen10~100根据数据的周期性和自相关性来定一个容易踩的细节全连接层输出个数必须跟 quanRegressionLayer 里分位数的数量严格一致。如果你把分位数定义为 [0.05 0.5 0.95]那全连接层就得是 fullyConnectedLayer(3)否则训练时会直接报维度不匹配错误。另外LSTM 层的 OutputMode 必须设成 last因为区间预测只需要序列末尾的隐含状态不需要每个时间步都输出。3.3 数据格式与替换方法data.xlsx 的默认格式是单变量时间序列一列数值从上到下按时间顺序排列。替换成自己的数据时最省事的做法是把风速或负荷数据粘贴到 Excel 的同一列保持纵向排列。需要注意数据中不能有文本表头混入数值区MATLAB 的 xlsread 读取时会按数值矩阵处理混入字符会导致读取失败或数据错位。输入输出单变量这一点决定了这个资源适用的是“单序列区间预测”。如果你的场景是多元输入比如同时考虑温度、湿度、风速来预测负荷那需要把 sequenceInputLayer 的输入特征维数改掉并把数据组织成多维数组。资源原版按单变量设计做多元扩展时要额外处理特征拼接不能直接套用。提示读取数据时建议用 xlsread(data.xlsx)返回的默认是数值矩阵。如果你的 Excel 里第一行是列名先删掉或用 xlsread 的 sheet 参数跳过表头区域。4. 跑通 MainQRLSTMTS.m数据切分、训练与 PICP/PIMWP 评估4.1 从原始序列构造监督学习样本QRLSTM 的本质是有监督回归所以第一步是把原始时间序列转换成“过去 seqLen 步 → 下一步”的样本对。常见做法是滑动窗口切分。下面这段代码展示了我习惯用的数据预处理逻辑function [X, Y] createSequences(data, seqLen) numObservations length(data) - seqLen; X cell(numObservations, 1); Y zeros(numObservations, 1); for i 1:numObservations X{i} data(i : i seqLen - 1); Y(i) data(i seqLen); end end这里 X 用 cell 数组存储每个元素是一个 1×seqLen 的行向量行数对应特征维度列数对应时间步数正好匹配 sequenceInputLayer(1) 对输入格式的要求numFeatures×numTimeSteps。Y 是单列向量存放每个窗口的下一时刻真实值。滑动窗口的好处是样本量大一个 1000 步的序列seqLen20 时能产出 980 个样本训练数据利用率高。实际运行时建议把数据先做归一化再切窗。归一化用 mapminmax 或 zscore 都行我一般用 zscore因为风速、功率这类数据经常有偏态分布标准化后训练更稳定。预测得到的结果再反归一化回原始量纲用于绘图和计算评估指标。4.2 训练搭网络、定选项、trainNetwork训练阶段把上一章的层结构直接组装成 layers 数组再交给 trainNetwork 跑。下面是主体代码seqLen 20; data xlsread(data.xlsx); data zscore(data); [X, Y] createSequences(data, seqLen); numSamples length(Y); splitIdx round(numSamples * 0.8); XTrain X(1:splitIdx); YTrain Y(1:splitIdx); XTest X(splitIdx1:end); YTest Y(splitIdx1:end); layers [ sequenceInputLayer(1) lstmLayer(64, OutputMode, last) fullyConnectedLayer(2) quanRegressionLayer([0.05 0.95], qrlstm)]; options trainingOptions(adam, ... MaxEpochs, 300, ... InitialLearnRate, 0.001, ... MiniBatchSize, 64, ... Shuffle, every-epoch, ... Verbose, true); net trainNetwork(XTrain, YTrain, layers, options);训练选项里Shuffle 设成 every-epoch 每个 epoch 都重新打乱样本顺序能有效避免模型学习到样本顺序带来的伪规律。InitialLearnRate 是 0.001对大部分风速、负荷数据足够如果训练损失下降很慢可以改成 0.005但要注意是否出现震荡。MiniBatchSize 64 是兼顾内存和梯度稳定性的折中数据量小于几千条时可以降到 32。4.3 预测与评估PICP 和 PIMWP 怎么算训练完成后predict 输出的是一个 2×N 的矩阵第一行是 τ0.05 的下分位数第二行是 τ0.95 的上分位数。评估区间预测质量主要看两个指标PICP 和 PIMWP这两个指标分别对应 PICP.m 和 PIMWP.m 两个文件。Ypred predict(net, XTest); L Ypred(1, :); U Ypred(2, :); picp PICP(L, U, YTest); pimwp PIMWP(L, U, YTest, range(YTest)); fprintf(PICP %.2f%%, PIMWP %.2f%%\n, picp, pimwp);PICPPrediction Interval Coverage Probability衡量真实值落在预测区间内的比例理想情况下应接近置信水平。如果你设置的是 [0.05 0.95]那么期望覆盖概率就是 90%。PIMWPPrediction Interval Mean Width Percentage衡量区间平均宽度占真实值范围的百分比这个值越小说明预测区间越“紧凑”越有实用价值。这两个指标存在天然的权衡关系区间拉宽PICP 会上升但 PIMWP 变差区间收窄PIMWP 好看但 PICP 可能掉到置信水平以下。做工程判断时一般先确保 PICP 达到或接近目标置信水平再观察 PIMWP 是否可控。如果 PICP 远高于置信水平同时 PIMWP 也高说明模型输出了一个“万金油”式的宽区间没有太多决策价值。注意PIMWP 的归一化基数有的实现用训练集范围有的用整个数据范围。资源里的 PIMWP.m 用的是真实值范围这个口径下结果更直观但跟其他文献对比时要确认口径一致。5. 避坑QRLSTM 训练与预测的 5 个常见故障5.1 训练 Loss 变成 NaN前几个 epoch 就崩了现象训练开始时输出显示 Loss 为 NaN或者迭代几步之后 Loss 突然变成 NaN 且不再恢复。原因最常见的是数据没做归一化风速、功率数据量级动辄几百上千LSTM 内部激活函数的梯度在反向传播时容易溢出。另一个原因是学习率设太大Adam 优化器在初始阶段也会因为梯度过大导致数值不稳定。解决先对原始数据做 zscore 标准化再做窗口切分。把 InitialLearnRate 降到 0.001 或更低同时检查训练数据里有没有 Inf 或缺失值。MATLAB 里读入 Excel 后建议顺手执行 sum(isnan(data)) 检查一遍。5.2 PICP 很高但区间宽得离谱预测等于没预测现象PICP 达到 95% 甚至 100%但 PIMWP 也大到 50% 以上画出来的区间几乎覆盖了整个数据波动范围预测结果没有决策价值。原因分位数损失在个别异常值或极端样本上会被拉得很开模型学到的是“给一个足够宽的区间总能覆盖住真实值”的捷径而不是捕捉条件分位数的形状。解决检查训练损失和验证损失确认模型没有过拟合尝试把隐藏单元数调小或者增加训练数据的规模。另一个更直接的办法是缩短分位数跨度比如用 [0.1 0.9] 代替 [0.05 0.95]区间收敛压力更大宽度会明显收紧。5.3 预测区间出现“翻转”上边界低于下边界现象画图时发现某一段预测区间 U 比 L 还小区间上下界交叉逻辑上明显不合理。原因多数情况下是因为两个分位数输出的初始化状态不同训练不充分时网络还没有学会分位数之间的排序关系。此外全连接层输出两个值的顺序和 quanRegressionLayer 里分位数的定义顺序必须一一对应如果对应错了上下边界会颠倒。解决训练完之后先检查 Ypred(1,:) 和 Ypred(2,:) 的大小关系如果大量出现翻转说明训练还没收敛增加 MaxEpochs 或把学习率适当调低。如果训练充分仍然翻转检查全连接层的输出顺序确保第一个输出对应小分位数。5.4 自定义层在 MATLAB 版本上报错方法名对不上现象把量化的代码放到较新版本的 MATLAB 里运行提示 forwardLoss 或 predict 方法有问题。原因MATLAB 自定义层的接口在不同版本里有演进。早期版本要求实现 forwardLoss 和 backwardLossR2019a 之后部分接口改为 predict。资源要求 MATLAB 2018 及以上如果你的版本恰好卡在接口过渡期就会出现这类问题。解决先在命令行执行 doc nnet.layer.Layer 查看当前版本的方法签名。如果当前版本要求 predict就把 forwardLoss 的近义词改成对应方法名或者直接以量化包里自带的层定义文件为准不要手动在旧版本上另写自定义层。5.5 预测结果整体比真实值滞后一个时间步现象把预测区间画出来看到区间曲线的走势明显比真实值晚一拍类似于“上一时刻的真实值被当成了这一时刻的预测”。原因这其实是自回归预测里常见的问题。训练时的监督信号是“用过去 seqLen 步预测下一步”但推理阶段如果采用了滚动预测把上一步的预测值再喂回输入误差会被逐步放大形成滞后。另一个原因是 seqLen 太短模型只学到了“输出约等于最近时刻输入”这个捷径。解决先确认测试阶段用的是持出窗口的真实值前缀而不是模型自己的预测结果。在此基础上再增大 seqLen比如从 10 增加到 20 或 30让模型必须依赖更长的历史信息才能做预测滞后现象通常会缓解。如果仍然滞后考虑在数据预处理阶段去掉趋势项。6. 进阶验证分位数单调性与区间质量的固定流程区间预测模型跑通之后我习惯加一个额外的验证步骤能显著降低把模型“交付”给业务方之后翻车的概率。具体做法是把分位数从两个扩展到三个即用 [0.05 0.5 0.95] 作为 quanRegressionLayer 的分位数向量同时把全连接层改成 fullyConnectedLayer(3)。这样一个模型同时输出下边界、中位数、上边界其中 0.5 分位数可以当作稳健的点预测中心线。训练完成后检查三条曲线是否满足 0.05 分位数曲线始终在 0.5 分位数下方、0.95 分位数曲线始终在上方。这个单调性验证看起来简单实际上能同时捕捉训练不收敛、分位数顺序颠倒、数据分布异常三类问题。另一个我固定执行的检查是用验证集而不是训练集来计算 PICP 和 PIMWP。训练集上的覆盖率天然会偏乐观因为模型见过这些样本只有验证集上的覆盖率接近置信水平才能说明模型的区间预测能力真的泛化到了未知数据。建议在数据切分时留下 10%~20% 的样本完全不参与训练单独作验证而不是直接在训练集末尾切一小段当作测试。最后一步是画区间图。把下分位数、上分位数和真实值画在同一张图上用填充方式展示区间肉眼看一眼区间是否跟随数据波动。区间宽窄如果与数据局部波动高度相关说明模型学到的是有意义的条件分位数如果区间宽度变化突兀、跟数据走势无关大概率是训练过程出了问题。我每次换新数据集都会强制自己先跑 5 个 epoch打印三个分位数的最大值、最小值和顺序确认没有翻转和 NaN 再跑全量。这个习惯帮我省掉了至少三次从头排查的时间希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑