资讯详情

资讯详情

小波神经网络预测代码实战:从分解到重构的完整指南

简介小波神经网络预测代码包源自一个毕业设计项目面向具备信号处理与机器学习基础的研究者和学习者旨在演示小波变换多分辨率分析与神经网络自适应学习的融合方法。压缩包共六个文件包括五个脚本与一个数据文件整体仅约五千字节脚本涵盖模型主程序、自定义小波基及其导数计算、层析分析等模块数据文件提供实际交通流样本便于直接运行测试。通过研读代码可以梳理出从原始数据加载、小波变换、特征构造到神经网络训练与预测的完整流程理解各模块的分工与接口关系对于毕业设计、课程设计或科研入门而言这是一份轻量且可扩展的参考实现。目前已有九十八人学习浏览。使用时需注意遵循原始许可协议仅限交流学习禁止商业用途同时建议结合相关理论知识进行调试与优化。1. 小波神经网络预测代码不是把所有序列丢进一个黑匣子接过一个“小波神经网络预测代码.rar”里面躺着几个 Python 脚本和一份数据很多人第一反应是直接跑train.py然后对着 Loss 曲线发愣。这套资源真正做的事是把时间序列先做小波分解再用神经网络分别预测低频和高频分量最后重构出未来值小波也可以作为激活函数嵌进网络里这份代码包两种路线基本都覆盖了。适合正在做毕业设计、需要完成“预测类”模块的同学也适合想把小波 Elman 神经网络从论文搬进实际数据的从业者。先用默认配置跑通再换自己的数据、调分解层数和网络结构比从头写pywt和反向传播省太多时间。下面按我拆包后的实践顺序从原理到踩坑一条条讲清楚。2. 小波神经网络不是玄学从分解到重构的四个组件2.1 离散小波分解和小波包分解选几层、用哪个小波基小波分解做的事情是把一条非线性时间序列按照频率拆开。调用pywt.wavedec一次得到低频近似系数cA_n和多组高频细节系数cD_n...cD_1。低频系数保留趋势高频系数保留局部波动预测任务里趋势是主菜细节是调味料。这份代码里默认做 3 层分解用的是db4小波基分界模式用periodic。import pywt def dwt_decompose(data, level3, waveletdb4): coeffs pywt.wavedec(data, waveletwavelet, levellevel, modeperiodic) names [fcA_{level}] [fcD_{i} for i in range(level, 0, -1)] return dict(zip(names, coeffs))level3表示分解到第 3 层periodic是周期延拓模式边界处不会产生明显的人为跳变适合预测序列。如果换zero模式重构后的首尾会出现振荡这是预测里最常见的坑之一。分解层数不是越多越好我一般用int(log2(len(series) / input_len))作为上限超过 5 层后每个系数序列样本数太少网络根本学不够。小波基的选择与信号形态相关。常用的是db4计算快、紧支撑、正交性质好sym8对称性更好对相位失真更小morl是连续小波基通常不用在离散分解里而是用作小波神经网络的激活函数。具体对比在第四章参数部分给出表格。2.2 神经网络建模低频用 Elman 还是全连接尺度怎么进网络拆完后要给每个分量建预测模型。这里热词“小波 Elman 神经网络”指的就是把小波分解和 Elman 循环网络结合的方式。Elman 网络和普通全连接的区别是多了一个承接层把上一时刻隐藏层的输出反馈到当前输入因此对短时序依赖非常敏感非常适合预测小波系数这种强自相关序列。import numpy as np def elman_cell(x, h_prev, Wxh, Whh, bh): h np.tanh(np.dot(Wxh, x) np.dot(Whh, h_prev) bh) return h这份代码里常见做法是每个分量单独建模cA_n代表趋势用稍大一点的 Elman 网络cD代表高频扰动用更浅的网络防止高频分量过度拟合。另一种混合路线是把小波函数作为隐藏层激活这时网络变成了真正的小波神经网络需要额外设置尺度参数a和平移参数b。两种路线在资源里都有实现但先用分解加 Elman 的方式跑通效果往往比直接魔改激活函数稳定。2.3 逆小波重构预测值长度、延拓和系数对齐预测完成后要回到原始尺度才能看到真实数值。逆变换最烦的不是公式而是系数长度对齐。pywt.waverec要求cA和cD长度匹配否则要么抛异常要么重构出的序列尾部多一段毛刺。def reconstruct(pred_cA, pred_cD, level3, waveletdb4): coeffs [pred_cA] list(pred_cD) # 高频分量需要对齐到 cA 长度使用后向填充 coeffs [np.pad(c, (0, len(pred_cA) - len(c)), modeedge) for c in coeffs] series pywt.waverec(coeffs, waveletwavelet, modeperiodic) return seriesnp.pad的edge模式用最后一个有效值向外延拓比补零更自然。重构后返回的序列长度不是固定不变的它取决于分解层数和你给进去的系数长度所以后续要精确截取预测区段不要直接认为len(series)等于原始长度。2.4 标准化顺序先归一化还是先分解很多人拿到数据就直接MinMaxScaler.fit_transform全序列再分解、训练、预测测试集指标好看到离谱一换新数据就崩。这是典型的信息泄漏。正确顺序是先用训练集拟合 scaler再分别归一化训练集和测试集然后分解预测后先对每个分量的预测结果做逆变换再通过waverec重构。如果先分解再归一化则每个分量需要单独保存 scaler重构前要逐个逆变换。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler(feature_range(-1, 1)) train_scaled scaler.fit_transform(train.reshape(-1, 1)).ravel() test_scaled scaler.transform(test.reshape(-1, 1)).ravel()注意scaler只能fit在训练段上测试段只能用transform。这个习惯直接决定了你的结果是真预测还是自欺欺人。3. 把代码跑起来目录结构、依赖与第一次运行3.1 拿到 rar 之后先看这几个文件解压后别急着找main.py先看目录结构。我拆过的这套小波神经网络预测代码包常见结构是这样小波神经网络预测/ ├── data/ │ └── load_data.csv ├── model/ │ ├── dwt.py │ ├── elman.py │ └── activation.py ├── config.py ├── train.py ├── predict.py └── requirements.txtdwt.py负责分解和重构elman.py是网络主体activation.py里是小波激活函数实现config.py是所有参数集中地。我的习惯是先打开config.py看一眼默认的WAVELET、LEVEL、INPUT_LEN、HORIZON四个值这几个参数决定你后面需要动多少代码。3.2 配置环境Python 版本与依赖清单这份代码基于 Python依赖集中在数值计算、小波变换和机器学习三块。建议新建一个干净环境避免把老项目的包混进来。conda create -n wnn python3.9 -y conda activate wnn pip install numpy pandas matplotlib PyWavelets scikit-learnPyWavelets 就是pywt如果看到import pywt失败先查这个包。后续如果代码里有torch或tensorflow版本再按需补装先用 CPU 版把流程跑通不要一上来就配置 GPU会分散排查重点。3.3 运行示例修改数据路径、预测步长和输出数据文件要求至少两列第一列是时间第二列是数值。运行默认训练时会自动切分训练集和测试集并输出每个分量的 RMSE。命令加参数的方式比改代码方便python train.py --data ./data/load_data.csv --input_len 48 --horizon 6 python predict.py --model ./checkpoints/best.pkl --data ./data/test.csv--input_len 48表示用过去 48 个点预测未来--horizon 6表示预测未来 6 个点。这两个参数直接决定训练样本的张成范围--horizon设得越大模型误差越大第一次跑建议保持 1 到 6 之间。model加载后的输出是重构回原始量纲的预测序列不是归一化后的值。4. 核心参数怎么调层数、学习率、小波基和预测步长4.1 小波基函数选择db4、sym8、morl 的取舍小波基的选择对我这个项目影响很明显同一个数据集用db4和sym8跑出来的 RMSE 能差百分之十几。下面是我给毕设组学生常放的对比表小波基类型特点适用场景db1Haar离散正交最简单计算最快边界易有台阶噪声小的短序列db4离散正交紧支撑计算省默认首选大多数工程数据先用它sym8离散正交对称性更好相位失真小周期性明显的负荷、流量数据morlMorlet连续小波震荡衰减非正交做激活函数和时频分析不做离散分解切换小波基只改一处配置但注意这个选择同时影响分解层数和重构节奏。# config.py 中修改 WAVELET db4 # 离散分解用 db4 或 sym8 ACTIVATION morlet # 隐藏层激活函数用 morlet如果你把WAVELET改成morlpywt.wavedec会直接报错因为离散多分辨率分析需要正交或双正交基。这块的“玄学”不在选哪个基而在你改了之后有没有同步调整分解层数。4.2 网络结构与输入步长隐藏层神经元数和样本切窗序列预测里输入步长是最容易被忽略的参数。我用一个基本规则输入步长至少是预测长度的 4 到 8 倍。比如预测未来 6 个点输入步长取 24 到 48。给神经网络切片时用下面的函数生成监督学习的样本def make_samples(series, input_len48, horizon6): X, y [], [] for i in range(len(series) - input_len - horizon 1): X.append(series[i: i input_len]) y.append(series[i input_len: i input_len horizon]) return np.array(X), np.array(y)返回的X形状是(样本数, input_len)y形状是(样本数, horizon)。如果是多尺度合并输入就把多个分量的对应窗口纵向拼在一起但我不推荐一开始就这么干每个分量单独建模、单独调参更容易定位问题。隐藏层神经元数常见范围是int(sqrt(input_len horizon)) 5到 20先取 16看损失下降情况再增减。4.3 训练超参学习率、批量大小与早停时序数据切出来的样本不能像图像那样随机打乱我在代码里保留了原始顺序并按 batch 取连续段。训练时优先关注学习率和早停策略from torch.optim import Adam from torch.optim.lr_scheduler import ReduceLROnPlateau optimizer Adam(model.parameters(), lr0.001) scheduler ReduceLROnPlateau(optimizer, modemin, patience10, factor0.5)lr0.001是多数小波神经网络比较稳的起点如果 loss 前十几轮完全不动可以提高到 0.005如果出现 NaN 或剧烈震荡直接降到 0.0001。patience10表示验证集指标连续 10 轮不下降才把学习率减半这是防止过拟合的后悔药。批量大小常用 32 或 64样本少时用 16。4.4 预测效果评估RMSE、MAPE、R2 怎么打印毕设答辩里最常被问的是“你的模型到底好不好”不要只给一张预测曲线图。建议每次跑完都打印三个指标import numpy as np def metrics(y_true, y_pred): y_true np.asarray(y_true).ravel() y_pred np.asarray(y_pred).ravel() mse np.mean((y_true - y_pred) ** 2) rmse np.sqrt(mse) mae np.mean(np.abs(y_true - y_pred)) mape np.mean(np.abs((y_true - y_pred) / (y_true 1e-6))) * 100 ss_res np.sum((y_true - y_pred) ** 2) ss_tot np.sum((y_true - np.mean(y_true)) ** 2) r2 1 - ss_res / ss_tot return rmse, mae, mape, r2MAPE分母加上1e-6防止原始序列里有 0 导致除零。R2接近 1 不代表没有滞后遇到曲线错位的情况R2 照样很高这就是为什么要用下一章的滚动验证补充判断。5. 避坑五次典型翻车记录5.1 现象预测曲线整体滞后一个时间步第一次跑通看着测试集曲线和真实曲线几乎贴合但放大后发现每一条预测都慢了一拍。这个现象在小波 Elman 网络上特别常见原因是输入窗口里有大量历史值网络学到的捷径是“把最后一个观测值搬出来当预测”低频趋势很容易被这种捷径欺骗。解决办法是改成预测差分序列对原始系数做一阶差分模型预测的是变化量再累加回真实值滞后问题会明显缓解。diff np.diff(series) pred_diff model.predict(window) pred_value series[-1] pred_diff如果改动差分后 RMSE 反而更高说明原始序列本身噪声很小不需要差分可以只在高频cD分量上使用差分训练。5.2 现象小波系数输入网络后梯度爆炸loss 变成 NaN小波分解后cA_n低频系数量级通常很大而cD高频系数量级则很小两个分量未经处理直接喂进同一个网络大的主导梯度小的学不到最后优化器更新幅度过大直接溢出。解决方法是每个分量单独使用一个 scaler并且把压缩范围设成(-1, 1)而不是(0, 1)让神经元的输入更均匀。x_scaler MinMaxScaler(feature_range(-1, 1)) cA_norm x_scaler.fit_transform(cA.reshape(-1, 1)).ravel()每次训练前检查np.isnan(loss)的时机如果第一轮就出现 NaN大概率不是学习率问题而是某个系数序列没有归一化。5.3 现象测试集分数好得离谱换一段新数据直接崩这是信息泄漏的典型症状。常见原因有两个一是对全序列做了归一化才划分训练测试scaler 看到了全局统计量二是小波分解时使用了跨越训练/测试边界的延拓把未来的信息带到了训练段。解决方法是先切分出训练集和测试集再分别用同一个 scaler 转换滚动预测时每一轮只能使用当前时刻之前的数据做分解不能把未来段拼进系数序列再重构否则你的测试集成了开卷考试。5.4 现象pywt.waverec报错长度不匹配或重构结果多出几个点小波分解每个系数长度不同重构时如果直接waverec就会报错。更隐蔽的情况是重构不报错但输出长度不等于原序列造成预测点和时间轴对不上。我在给 n 层分解时重构前会强制把所有系数pad到和cA_n一致然后只截取预测对应区间。coeffs [np.pad(c, (0, len(cA) - len(c)), modeedge) for c in coeffs] reconstructed pywt.waverec(coeffs, waveletdb4, modeperiodic) forecast reconstructed[-horizon * (2 ** level - 1):]截取步长和分解层数有关别直接用[-horizon:]。这里每次改level都要同步检查截断长度是我血泪经验换来的地方。5.5 现象morlet 激活函数让网络输出全部接近 0loss 卡住不动小波函数作为隐藏层激活时Morlet 的表达式是cos(1.75x) * exp(-x^2/2)它只在x靠近 0 时有较强响应一旦线性加权和超出一段范围梯度会快速消失。解决方法是让权重初始化小一点并在网络外部包一层尺度缩放变量a和平移变量b。class WaveletLayer: def __init__(self, in_dim, out_dim): self.W np.random.randn(in_dim, out_dim) * 0.1 self.a np.ones((1, out_dim)) self.b np.zeros((1, out_dim)) def forward(self, x): z np.dot(x, self.W) self.b return np.cos(1.75 * z) * np.exp(-z * z / 2)初始化权重用0.1缩放置在[-1, 1]范围内等训练几轮之后再逐步放开a和b为可训练参数。如果一上来就放开模型基本学不进去。6. 验证你的模型不是过拟合滚动预测与残差检验训练测试集上的 RMSE 都很好不代表模型真能用。最有效的验证方式是滚动预测每次只预测下一个点然后把预测值当作已知输入继续往后滚。这样模拟的是真实部署时只能拿到历史数据的状态。def rolling_predict(model, data, input_len48, steps24): x data[-input_len:].copy() preds [] for _ in range(steps): p model.predict(x.reshape(1, -1))[0] preds.append(p) x np.append(x[1:], p) return np.array(preds)model.predict要确保网络处于验证模式如果用了 dropout请先切换到eval。滚动步数steps和时间步长越拉越长曲线大概率会漂移这是正常现象但如果 30 步后预测值直接变成常数说明模型已经退化成“复制最近值”。滚动预测之后再做一个残差自相关检查残差是预测值和真实值的差如果残差序列仍然有强自相关说明模型没有把序列中的规律学干净。res y_true - y_pred corr1 np.corrcoef(res[:-1], res[1:])[0, 1] if abs(corr1) 0.3: print(残差仍有自相关尝试增大输入步长或加入外部特征)第一阶自相关超过 0.3 时我一般会回头把input_len加大一倍或者把原始序列做一次差分后再小波分解。以前我交毕设前只盯着 RMSE 曲线后来被老师问了一句“如果一步一步滚动预测还能不能稳住”才发现看起来完美的模型在第 30 步之后已经变成复读机。从那以后我每次训练完都强制走一遍滚动预测和残差自相关检验这两步比任何花哨的网络结构都管用。这份小波神经网络预测代码包我已经整理好需要的直接去拿跑通默认参数后再改自己的数据坑都在第 5 章希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →