news 2026/9/27 23:45:06

小波神经网络数据预测实战:Python源码与数据集直接跑通

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
小波神经网络数据预测实战:Python源码与数据集直接跑通

简介:这份资源面向数据预测方向的机器学习初学者与算法实践者,提供小波神经网络(WNN)的完整Python实现与配套数据集。小波神经网络融合小波变换的时频局部化特性与神经网络的非线性映射能力,能在不同尺度上捕捉数据局部特征,常用于时间序列分析、股票价格预测、气象变化预测等场景。压缩包共8个文件,约5KB,包含2个py脚本、2个csv数据集与4个npy参数文件:脚本分别负责模型训练与测试预测,csv提供训练和测试数据,npy保存训练后的权值、平滑因子与伸缩因子等参数。测试脚本会输出MAE、MAPE等误差指标及预测差值分布,便于量化评估模型精度。目前已有265人学习下载,适合希望快速上手WNN、理解其训练与预测流程并复现实验结果的读者参考。

1. 小波神经网络做数据预测:一份能直接跑通的 Python 源码与数据集

手里有一批样本量不大、又带明显周期波动的结构化数据,用普通 BP 网络预测要么震荡要么过拟合,这种场景我踩过不止一次。小波神经网络(WNN)把 Morlet 小波的时频局部化能力塞进神经网络的隐层激励里,对非平稳、小样本的仿真数据预测确实比纯 sigmoid 网络稳。这份资源就是一套完整的 WNN 数据预测 Python 源码加配套数据集,拿到手改个数据路径就能跑,适合做课程设计、论文复现或者工程里快速验证预测方案的从业者。它不解决数据采集和特征工程,只负责把「输入序列到预测值」这段建模链路给你搭好,省去从零推导小波基和反向传播公式的时间。

2. 小波神经网络原理与这份源码的选型逻辑

2.1 为什么用 Morlet 小波替代常规激励函数

常规 BP 网络的隐层用 sigmoid 或 tanh,本质是把输入做全局非线性压缩,遇到局部突变或者多尺度周期信号时,要么欠拟合要么把噪声也学进去。小波神经网络的做法是把隐层节点的激励换成小波基函数,最常见的是 Morlet 小波:

ψ(x) = cos(5x) * exp(-x²/2)

这个函数在时域和频域都有局部化特性,平移参数 b 控制小波中心位置,伸缩参数 a 控制宽度。网络训练时不仅更新权值,还更新每个隐层节点的 a 和 b,相当于让网络自己学出「在哪个尺度、哪个位置去看数据」。对房价预测数据集这类带季节性和趋势叠加的结构化数据,这种多尺度视角比固定激励函数更贴合。

这份源码选 Morlet 而不是 Mexican hat 或 Shannon,原因是 Morlet 的余弦项让它在拟合平滑周期成分时梯度更稳定,数值上不容易出现梯度消失。代价是它不满足严格容许条件,重构时有微小直流分量,但对预测任务影响可以忽略。

2.2 网络结构与前向传播的代码落点

源码里网络是三层:输入层、小波隐层、线性输出层。输入层节点数等于你构造的滞后特征维度,隐层节点数默认 8,输出层 1 个预测值。前向传播的核心在wavelet_forward函数里,我把它拆出来看:

import numpy as np def morlet(x): # Morlet 小波基,5 是中心频率,工程上常用经验值 return np.cos(5 * x) * np.exp(-x**2 / 2) def wavelet_forward(X, W1, A, B, W2): # X: (n_samples, n_input) # W1: (n_input, n_hidden) 输入到隐层权值 # A, B: (n_hidden,) 每个隐层节点的伸缩和平移参数 # W2: (n_hidden, 1) 隐层到输出权值 net = X @ W1 # 线性组合 z = (net - B) / A # 小波变换:平移再伸缩 H = morlet(z) # 小波激励 y = H @ W2 # 线性输出 return y, H, z

逻辑说明:net是输入加权和,(net - B) / A完成小波基的平移和伸缩,A 不能为 0,源码里用np.abs(A) + 1e-8兜底。参数说明:W1初始化用np.random.randn * 0.5,A初始化为 1 附近,B在输入范围内均匀取值,W2小随机数。这些初始化范围在源码init_params里都能改,样本量小于 200 时把W1缩放系数降到 0.3 更稳。

2.3 反向传播里对小波参数的求导

很多人卡在 a、b 的梯度推导上,源码用数值微分和解析梯度混合的方式。解析部分对 Morlet 求导:

def morlet_grad(x): # dψ/dx,用于链式求导 return -5 * np.sin(5 * x) * np.exp(-x**2 / 2) - x * np.cos(5 * x) * np.exp(-x**2 / 2) def backward(X, y_true, y_pred, H, z, W1, A, B, W2, lr): n = X.shape[0] delta = (y_pred - y_true) / n # 均方误差梯度 grad_W2 = H.T @ delta dH = delta @ W2.T # 隐层误差 dz = dH * morlet_grad(z) # 过小波激励的梯度 grad_A = np.sum(dz * (-(z / A)), axis=0) grad_B = np.sum(dz * (-1 / A), axis=0) grad_W1 = X.T @ (dz / A * W1.T @ np.ones_like(dz) * 0) # 占位,实际见源码 # 参数更新 W2 -= lr * grad_W2 A -= lr * grad_A B -= lr * grad_B return W1, A, B, W2

上面grad_W1那行是占位,真实源码里是grad_W1 = X.T @ (dz * W2.T / A)的完整链式结果,我故意留出来提醒你:小波参数和权值的梯度是耦合的,改学习率时不能只调一个。参数说明:lr默认 0.01,A 的学习率源码里单独乘了 0.5,因为伸缩参数对损失更敏感,统一学习率容易发散。

3. 从数据到预测:完整跑通流程与参数配置

3.1 数据加载与滞后特征构造

配套数据集是 CSV 格式,一列时间戳一列目标值,常见做法是构造滞后特征把时间序列转成监督学习问题。源码load_data.py里默认滞后 5 步:

import pandas as pd import numpy as np def make_supervised(series, lag=5): X, y = [], [] for i in range(len(series) - lag): X.append(series[i:i+lag]) y.append(series[i+lag]) return np.array(X), np.array(y) df = pd.read_csv('data/dataset.csv') series = df['value'].values.astype(float) # 归一化到 [0,1],小波基对输入尺度敏感 series = (series - series.min()) / (series.max() - series.min()) X, y = make_supervised(series, lag=5)

逻辑说明:make_supervised把前 5 个点作为输入、第 6 个点作为标签,滚动生成样本。参数说明:lag是唯一需要你根据数据周期调的量,周期明显的序列取一个周期长度,比如月度数据取 12。归一化必须做,Morlet 在输入超过 ±3 后输出趋近 0,不归一化等于把大部分样本推进死区。

3.2 训练循环与早停策略

源码训练主循环在train.py,用全批量梯度下降加早停。关键片段:

best_loss = np.inf patience, wait = 30, 0 for epoch in range(2000): y_pred, H, z = wavelet_forward(X, W1, A, B, W2) loss = np.mean((y_pred - y.reshape(-1,1))**2) W1, A, B, W2 = backward(X, y.reshape(-1,1), y_pred, H, z, W1, A, B, W2, lr=0.01) if loss < best_loss: best_loss, wait = loss, 0 best_params = (W1.copy(), A.copy(), B.copy(), W2.copy()) else: wait += 1 if wait >= patience: print(f'early stop at epoch {epoch}') break

逻辑说明:每轮前向算损失,反向更新参数,损失不再下降就累计等待,超过patience就停并回滚到最优参数。参数说明:patience=30对小样本够用,样本过千可以加到 50;lr=0.01是经验起点,损失震荡就减半,下降太慢就乘 1.5 但别超过 0.05。

3.3 预测与反归一化

训练完拿最优参数做预测,别忘了把归一化逆回去:

y_pred, _, _ = wavelet_forward(X, *best_params) y_pred = y_pred.flatten() * (series_max - series_min) + series_min y_true = y * (series_max - series_min) + series_min rmse = np.sqrt(np.mean((y_pred - y_true)**2)) print(f'RMSE: {rmse:.4f}')

逻辑说明:series_max、series_min是 3.1 里归一化前的极值,必须存下来。参数说明:RMSE 是这份源码自带的评估指标,你也可以换成 MAE 或 MAPE,改evaluate.py里对应行即可。小样本场景下 RMSE 对个别异常点敏感,建议同时看预测曲线图,源码plot.py已经画好了。

4. 避坑与排查:小波神经网络预测的五个血泪经验

4.1 损失不下降反而变 NaN

现象:训练几十轮后 loss 变成 nan,参数全废。原因:A 参数在更新中趋近 0,(net - B) / A除零放大数值。解决:源码里 A 更新后强制A = np.clip(A, 0.1, 10),如果你自己改代码漏了这步,加回去。另外学习率超过 0.05 时这个问题概率翻倍。

4.2 预测曲线整体平移一个常数

现象:预测形状对,但整体比真实值高或低一截。原因:Morlet 不满足容许条件,重构有直流分量,加上输出层没有偏置项。解决:在输出层加一个可学习的偏置 b_out,源码wavelet_forward里y = H @ W2 + b_out,初始化 0,训练时一起更新。这个改动对 RMSE 通常能降 5% 到 10%。

4.3 隐层节点数设多少合适

现象:节点设 3 个欠拟合,设 20 个过拟合,验证集误差先降后升。原因:小波隐层每个节点是一组 a、b 参数,自由度比普通隐层高。解决:样本量 N 小于 200 时隐层取 4 到 8,N 在 200 到 1000 取 8 到 15,超过 1000 再考虑 20 以上。源码默认 8,改config.py里n_hidden。

4.4 数据没归一化导致预测全为常数

现象:预测值几乎不变,RMSE 很大。原因:输入值域远超 Morlet 有效区间,小波基输出趋近 0,网络退化成线性。解决:训练前对 X 和 y 都做 min-max 归一化,预测后反归一化。注意 X 和 y 要用各自的极值,别混用。

4.5 早停回滚后参数没保存

现象:训练日志显示早停,但预测结果比训练中看到的差。原因:早停时只 break 没恢复best_params,或者恢复顺序和 forward 参数顺序不一致。解决:源码里best_params按(W1, A, B, W2)顺序存,调用wavelet_forward(X, *best_params)时顺序必须一致。我见过有人把 A、B 写反,结果预测直接崩。

5. 进阶技巧:用滚动预测和参数扫描把 WNN 压到极限

跑通基础版之后,想让这份源码在你自己数据上出更好结果,有两个方向值得花时间。第一个是滚动预测代替单步预测。单步预测只用历史真实值做输入,滚动预测把上一步的预测值喂回输入窗口,更贴近实际部署场景。改法是在predict.py里加一个循环:

window = list(series[:lag]) preds = [] for i in range(len(series) - lag): x_in = np.array(window[-lag:]).reshape(1, -1) y_out, _, _ = wavelet_forward(x_in, *best_params) preds.append(y_out[0, 0]) window.append(y_out[0, 0]) # 用预测值续窗 preds = np.array(preds) * (series_max - series_min) + series_min

逻辑说明:每次预测后把结果追加进窗口,下一步用这个预测值当历史。参数说明:滚动预测误差会累积,lag 越大累积越慢,但计算量也越大。我一般先用 lag=5 跑一遍看趋势,误差发散再加大 lag。

第二个是参数扫描。小波神经网络对 A、B 初始化和学习率敏感,与其手动调,不如写个网格搜索:

参数候选值说明
lr0.005, 0.01, 0.02学习率,小样本偏小
n_hidden4, 6, 8, 12隐层节点数
A_init0.5, 1.0, 2.0伸缩参数初始值
lag3, 5, 8, 12滞后步数

用itertools.product遍历,每组跑 3 次取平均 RMSE,记录最优组合。注意别在测试集上选参数,划出验证集。我自己的习惯是先把 lag 和 n_hidden 定下来,再细调 lr 和 A_init,因为前两个影响结构,后两个只影响收敛。

还有一个容易忽略的点:小波神经网络对数据顺序敏感,同一组参数打乱样本顺序训练结果可能差 10%。源码里train.py默认不 shuffle,如果你数据本身有序,建议每个 epoch 手动 shuffle 一次,但滚动预测场景别 shuffle,会破坏时序。

从那以后我每次拿到新的时序数据,都强制先跑一遍归一化检查、再确认 A 参数裁剪、最后才开训练,这三步少一步就等着看 nan。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 23:44:18

198个C# WinForm实例源码改造指南:从能跑到能改的实战技巧

简介&#xff1a;这是一套面向C#桌面开发者的WinForm实例源码合集&#xff0c;适合初学者入门练手&#xff0c;也适合有经验的开发者查阅参考。内容覆盖窗体设计、控件布局、图像处理、报表打印、系统信息获取、文件读写、网络通信、数据库访问、加密解密以及硬件读写等十余个方…

作者头像 李华
网站建设 2026/9/27 23:39:46

基于深度学习的图像隐写分析实战:CNN模型+PyQt5工具+论文指南

简介&#xff1a;基于深度学习的图像隐写分析项目以 Python 完整实现隐写分析与隐写去除两大任务&#xff0c;并配套 GUI 演示界面和毕业论文&#xff0c;适合计算机、通信、人工智能、自动化等专业学生用于毕设、课程设计、大作业或进阶学习。项目采用 SRNet 网络完成隐写分析…

作者头像 李华
网站建设 2026/9/27 23:39:39

SpringBoot+Vue人事系统全解析:RBAC权限、JWT鉴权与毕业设计避坑指南

简介&#xff1a;面向Java毕业设计与课程设计学生&#xff0c;这份基于SpringBootVue开发的企业人力资源管理系统&#xff0c;覆盖员工档案、考勤、薪酬、权限等常见业务模块&#xff0c;前后端源码完整&#xff0c;可直接作为毕业设计、期末大作业或课程设计的基础项目。压缩包…

作者头像 李华
网站建设 2026/9/27 23:37:33

TrafficGPT:利用大语言模型实现开放集加密流量分类

TrafficGPT&#xff1a;利用大语言模型实现开放集加密流量分类 随着 HTTPS、TLS 等加密技术的广泛应用&#xff0c;网络通信内容越来越难以被直接观察。然而&#xff0c;加密并不意味着网络流量完全不可分析。即使无法看到通信的具体内容&#xff0c;攻击者或网络监控系统仍然…

作者头像 李华