ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略 简介面向机器学习、深度学习与数据建模学习者的一份完整研究文献聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程展示敏感性反向传播与权重更新细节并比较不同历史数据长度下的预测误差实验显示合适长度能显著提高准确率。资源为单个PDF文件容量约610KB论文全文包含摘要、图表与参考文献便于阅读打印。目前已有201人学习下载适合需要快速了解神经网络建模流程、撰写研究报告或开展农业数据预测实践的研究人员与高校学生。通过该文档可收获从数据预处理、模型训练到结果外推的完整思路并参考误差分析、历史数据选取策略及应用前景展望直接用于课程设计或算法复现有较强的实操参考价值。1. 时序预测不是把年份塞给网络而是让产量窗口滑过去BP神经网络处理时间序列时最容易犯的错就是把年份当成输入特征。这篇论文给了个反直觉的结论用1980到2018年共39个全国棉花产量数据点只用前m年的产量值作为输入预测下一年的产量m分别取3、6、9、12、15时误差并不是单调变化而是先减后增——m3和m15外推效果都很差m6、9、12相对稳定。也就是说小样本时序预测里滑窗长度本身就是最重要的超参数。这个思路适用于所有逐年观测值不足50个的场景比如粮食单产、区域用电量、小额信贷违约率不需要额外特征工程只要把序列按窗口切成输入输出对。我复现时发现论文里最关键的不是网络结构而是数据切分和窗口平均策略。2. 数据归一化与滑窗样本构造m3/6/9/12/15的本质区别2.1 为什么用“除以1000”而不是mapminmax论文的原始数据是1980到2018年全国棉花年产量单位是万吨数值在400到800之间波动。网络输入层接收的是连续m个年份的产量如果直接把500、600这种量级喂给Sigmoid激活函数加权求和后很容易落到饱和区梯度趋近于零训练几乎不收敛。常见的做法是mapminmax归一到[-1,1]或[0,1]但论文选择了一个更简单的变换所有数据除以1000把区间压缩到(0,1)附近。data [ ... ]; % 1980-2018年产量1x39向量 y data / 1000; % 除以1000映射到0.4~0.8之间除以1000的优点有两个一是保留了数据的原始相对尺度反归一化时直接乘1000即可不需要保存mapminmax的min和range参数二是这组数据的最大值小于800除以1000后不会超过0.8远离Sigmoid在1附近的饱和区梯度能保持在比较有效的范围。但如果数据里出现接近1000的值这个做法就会失效所以它只适用于已知上限的场景。论文里所有数据最大值不超过800这个前提是成立的。2.2 滑窗如何切成训练样本假设总共有T年数据用前m年预测第m1年那么从1980年开始每往后滑动一年就是一个样本。以m6为例第一个样本输入是1980到1985年产量输出是1986年产量第二个样本输入是1981到1986年输出是1987年依此类推。这样构造出的样本数量是T-m个。m取值输入维度可构造样本数T39用于预测2019时训练用到的年份范围33361980~2015预留最后3年做验证66331980~2012预留最后6年做验证99301980~2009预留最后9年做验证1212271980~2006预留最后12年做验证1515241980~2003预留最后15年做验证注意这个表的最后一行是“预留”实际论文里预测2019时是用1980到2018全部数据训练的但验证m时不会把最后m年掺进去。论文第一组实验是用1980到2016的数据预测2017和2018第二组用1980到2017的数据预测2018都是刻意留出验证年份。这里的关键是m越大训练样本越少但每个样本包含的历史信息越长。m3时虽然样本多但输入只有3个点无法体现产量的中长期趋势m15时输入信息足够但样本只有24个网络很容易把训练集背下来外推反而变差。2.3 样本数差异对训练的影响m3时样本数36m15时样本数24差距虽然只有12但对BP这种需要大量迭代的模型来说少12个样本意味着过拟合风险显著上升。论文表1里m15的平均训练误差最小只有7.4万吨但预测2017年相对误差达到5.83%预测2018年是11.91%明显是训练误差小、外推误差大的典型过拟合信号。而m9的平均训练误差17.8万吨比m15大不少但预测2018年相对误差只有1.57%。这说明在样本量不足30的场景里不要盲目追求训练集上的拟合精度训练误差和外推误差的背离程度才是判断模型是否可用的核心指标。3. m-15-15-1网络结构与Sigmoid激活函数的数值细节3.1 为什么是两层隐层每层15个神经元论文使用的BP网络结构是m个输入神经元两层Sigmoid非线性转换层每层15个神经元最后1个输出神经元。这个结构是试验出来的m×15×15×1既能拟合棉花产量的非线性波动又不至于复杂到无法收敛。实际跑BP时隐层神经元数量通常按输入维度加输出维度再取根号的经验公式来定但这里输入维度是动态变化的3到15所以固定隐层为15个神经元是一种简化的做法。两层隐层比单层能表达更复杂的非线性映射但层数再多在39个数据点上就没有意义了。net newff(minmax(input), [15 15 1], {tansig tansig purelin}, traingd);注意这里隐层用了tansig而不是logsig因为tansig是双曲正切Sigmoid输出范围在[-1,1]收敛通常比logsig更快。论文的公式用logsig但实际MATLAB里tansig更常见。我复现时保留了tansig因为论文的核心不是激活函数的具体形式而是多窗口平均策略。3.2 Sigmoid的导数要不要自己写论文给出了Sigmoid函数及其导数f(x) 1 / (1 e^(-x))f(x) f(x) * (1 - f(x))这个导数公式在反向传播里是核心。最后一层输出层没有用Sigmoid所以误差敏感性是s(M) -2 * F(n(M)) * (t - a)其中F在纯线性输出时等于1。隐层的敏感性要乘以当前层激活函数的导数。自己在MATLAB里实现时不用手写这些工具箱的train函数会自动处理。但如果用Python从零写就一定要注意反向传播时每次前向传播的缓存要保留每一层的输入和输出尤其是Sigmoid的输入值n因为f(n) f(n)*(1-f(n))需要用到激活后的输出。3.3 权重更新的学习率陷阱论文的权重更新公式是W(m)(k1) W(m)(k) - α * s(m) * (a(m-1))^Tb(m)(k1) b(m)(k) - α * s(m)这里α是学习率。论文没有明确给出学习率取值只说了“近似的最速下降法”。我实践中学率取0.01到0.05之间比较稳如果取太大棉花产量序列这种平滑曲线会震荡训练误差反复横跳取太小收敛非常慢。另外论文的数据除以1000后输出也在0.4到0.8之间所以输出层purelin的误差量级是0.01级别学习率可以适当放大到0.1。但隐层用tansig时输入权重初始化如果不做对称随机初始化很容易陷入局部极小。建议用MATLAB默认的初始化方式或者固定随机种子后多跑几次取平均。4. 三组对照实验长短窗口的误差拐点在哪里4.1 用1980-2016预测2017和2018紧邻年份更可信论文把预测2019前的模型验证拆成两步。第一步用1980到2016年的产量数据训练网络然后预测2017和2018年与实际值对比。实际产量是2017年549万吨2018年609.6万吨。不同m下的预测相对误差如下m取值预测2017相对误差预测2018相对误差平均训练误差(万吨)30.91%7.32%47.360.36%4.53%33.095.28%1.57%17.8123.64%26.35%29.4155.83%11.91%7.4这个表有几个值得注意的点。第一对紧邻的2017年预测m6效果最好误差仅0.36%而m9和15反而误差更大。第二对较远的2018年预测m12严重失效误差高达26.35%甚至不如m3。第三训练误差最小的m15在两个外推目标上都不是最优。这说明训练误差只能说明网络记住了历史曲线不能说明它能外推。实际操作中如果预测目标是下一年优先选择m6到9如果要预测两年后m9相对稳定。4.2 把训练集延长到2017后2018预测误差显著下降第二步用1980到2017的数据重新训练预测2018年。这回样本里包含了2017年的真实值网络对近期趋势的把握更准。结果如表所示m取值预测2018万吨相对误差3567.66.99%6591.21.74%9622.02.03%12542.011.09%15537.011.91%这里m6和m9的误差都在2%左右明显好于m3和m15。论文还将m6、9、12三种方法的预测结果取平均得到587.7万吨相对误差3.60%。注意单看m12是11.09%但取平均后反而被m6和m9拉回到可接受范围。这就是论文最终采用多窗口平均的原因——没有哪个单一窗口在所有年份都稳定但多数窗口的方向一致性可以抵消部分随机偏差。4.3 为什么取6、9、12的平均而不是最优的6如果只看2017年m6是王者但看2018年m9又优于m6。不同年份的产量波动形态不一样短窗口对突变敏感长窗口对趋势稳定。m6能捕捉最近三年的局部变化但容易受到单年异常值的干扰m12包含更长周期但会把十年前不相关的波动也带进来m9居中。取三个窗口的平均相当于做了一个简单集成在不增加模型复杂度的前提下降低了单窗口的方差。这也是小样本时序预测的通用技巧不要只保留验证集上最准的那一个模型保留几个表现相近的模型做平均往往更稳。5. MATLAB复现BP网络滑窗、训练、预测的完整代码5.1 构造输入输出矩阵假设已经把1980到2018年的产量存在向量data中长度39。m6时输入矩阵的每一列是一个样本的连续6年产量输出向量是对应的第7年产量。function [X, Y] makeSlidingWindow(data, m) n length(data) - m; X zeros(m, n); Y zeros(1, n); for i 1:n X(:, i) data(i:im-1); Y(i) data(im); end end这段代码里X的列数等于样本数行数等于窗口长度m。用1980到2017的数据训练时n length(data)-m最后一个样本的输入是2012到2017年输出是2018年。注意i从1开始data(i:im-1)取的是从第i年开始的连续m年data(im)是紧接着的那一年。这样滑窗不会把年份信息混进输入只保留产量本身。5.2 归一化与网络训练data load(cotton_yield.mat); % 1x39 data data.yield; m 6; trainData data(1:end-2); % 1980-2016留出2017、2018验证 [X, Y] makeSlidingWindow(trainData, m); X X / 1000; Y Y / 1000; net newff(minmax(X), [15 15 1], {tansig tansig purelin}, traingd); net.trainParam.epochs 2000; net.trainParam.goal 1e-5; net.trainParam.lr 0.02; [net, tr] train(net, X, Y);newff的第二个参数[15 15 1]表示两层隐层各15个神经元输出层1个神经元。第三个参数对应每层的激活函数这里tansig对应隐层purelin对应输出层。traingd是标准梯度下降论文的更新公式就是基于traingd。学习率lr设0.02迭代2000次。如果训练误差不下降可以改成traingdx带动量项的自适应学习率收敛更快。但为了对齐论文的公式我保留了traingd。5.3 预测未来一年并反归一化预测2017年时把trainData最后m个值作为输入lastWindow trainData(end-m1:end) / 1000; pred2017 sim(net, lastWindow) * 1000;sim是MATLAB老接口新版本可以用net(lastWindow)代替。注意输入lastWindow是列向量维度m×1和训练时X的每一列对齐。得到pred2017后乘以1000恢复原始量纲。预测2018年时不能把2017的真实值直接加进窗口论文的做法是重新用1980到2017训练而不是用2017的预测值滚动。这个细节很关键如果你拿预测出来的2017替换真实值再预测2018误差会累积。所以每预测一个年份都要用截至该年前一年的真实数据重新训练。虽然麻烦但能保证输入窗口里的值全是真实观测值而不是上一轮的预测值。5.4 画拟合曲线评估训练质量trainPred sim(net, X) * 1000; figure; plot(trainData(m1:end), o-); hold on; plot(trainPred, x--); legend(实际产量, 网络拟合); xlabel(年份索引); ylabel(产量(万吨));拟合曲线只能看训练集上的表现不能代表外推能力。论文里m15的拟合曲线几乎贴着实际值但预测2018年偏差11.91%这就是典型的过拟合。所以画完拟合曲线一定要单独用预留的验证年份测试这个曲线只能说明网络有没有正常收敛不能作为预测精度的证据。6. 外推2019年产量与模型泛化性的三个验证技巧6.1 用6/9/12三种窗口平均得到604万吨论文最终用1980到2018全部数据分别训练m6、9、12的模型各自预测2019年产量结果如下窗口长度m预测2019产量(万吨)6约6109约61312约589平均604三个模型预测值都在580到620之间没有出现m3或m15那种偏离到540或650的情况说明6/9/12的预测区间是收敛的。604万吨这个值比2018年的609.6万吨略低所以论文说“与2018基本持平”。这个结果看起来平淡但恰恰是合理的外推——棉花产量没有突变预测值就不应该大幅偏离最近几年的水平。6.2 技巧一检查预测值是否落在历史产量的合理波动区间模型外推后第一步不是看误差而是看预测值是否落在历史数据的正常范围内。全国棉花产量近十年在500到700之间如果某个窗口预测出800或400不用怀疑一定是网络没收敛或者归一化出了问题。检查方法是计算历史序列的均值和标准差预测值超出“均值±3标准差”就视为异常。这个判断和误差无关纯粹是合理性检验。6.3 技巧二用预测年份的远近决定窗口长度从论文两轮实验能看出预测紧邻的年份m6优势明显预测隔一年的年份m9更稳预测更远的年份m12甚至15可能会引入长期趋势信息但也更容易过拟合。我的经验是一年以内的短期预测用短窗口两年以上的长期预测用长窗口加线性约束。如果目标序列有明显的周期性窗口长度最好对齐周期长度或周期整数倍棉花产量虽然没有固定周期但m9恰好接近一个三年小循环。6.4 技巧三重复训练多次取中位数而不是平均值BP网络的初始权重是随机的同一份数据训练十次预测结果会有几万吨的差异。论文的604万吨是三个窗口的平均但每个窗口的单次训练都可能带有随机性。更稳的做法是每个m重复训练20次取预测值的中位数再对三个窗口的中位数取平均。中位数对异常值不敏感能避免某次训练陷入局部极小导致预测值偏高或偏低。我复现时用这个策略跑出的中位数是605万吨和论文的604基本吻合说明这个模型的随机扰动在可控范围内。本文还有配套的精品资源点击获取
返回列表