1) 小波神经网络 概念
对小波神经网络最常用、最好训练的形式是 小波基函数网络(Wavelet Basis Network):
y^(t)=P^(t)=∑k=1Kwk⋅ψ (zk−bkak)+w0\hat y(t)=\hat P(t)=\sum_{k=1}^{K} w_k\cdot \psi\!\left(\frac{z_k-b_k}{a_k}\right)+w_0y^(t)=P^(t)=k=1∑Kwk⋅ψ(akzk−bk)+w0
- (ψ(⋅)\psi(\cdot)ψ(⋅)):母小波(一般选 Morlet 最稳)
- (zkz_kzk):进入第 (kkk) 个小波节点的输入向量分量(通常就是某维特征,或线性组合)
- (ak>0a_k>0ak>0):尺度,(bkb_kbk):平移
- (wk,w0w_k,w_0wk,w0):线性输出权
直觉:它不是去"小波变换后再接 NN",而是把小波当成一种带尺度/平移的可学习基函数,网络通过学习 ((a_k,b_k,w_k)) 来拟合负荷的非线性周期性。
本文示例使用 一维输入版(每一维输入各自进自己的小波节点,结构简单、稳定),你要升级到"(z=W x) 线性组合版"我也可以补。
2) 电力负荷预测:怎么把问题做成监督学习
设负荷序列为 (P(1),P(2),...,P(N)P(1),P(2),\dots,P(N)P(1),P(2),...,P(N)),采样间隔=1h(或15min,同理)。
(1) 经典单步预测输入向量
x(t)=[P(t−1),P(t−2),...,P(t−L),D(t),H(t),1weekend(t))\mathbf{x}(t)= \big[P(t-1),P(t-2),\dots,P(t-L), D(t),H(t), \mathbb{1}_{\text{weekend}}(t) \big)x(t)=[P(t−1),P(t−2),...,P(t−L),D(t),H(t),1weekend(t))
- 历史负荷:(L=24L=24L=24)(小时)或 (96)(15min)
- 日历特征:日编号 (D)、小时编号 (H)、周末/节假日指示
- 温度/天气:能拿到就加(效果提升很大)
输出:(P^(t)=f(x(t))\hat P(t)=f(\mathbf{x}(t))P^(t)=f(x(t)))
(2) 归一化
建议用滑动窗口 z-score 或 min-max,这里先用简单 min-max:
matlab
Pn = (P - min(P))/(max(P)-min(P)+eps);
负荷预测里别把未来信息泄露进归一化(即不要用全局 future max/min 去归一化 test 段),工程上常见做法是:用 train 段统计做映射,test 段 clip。
3) 小波(Morlet)定义与网络前向
Morlet 母小波(复小波取实部即可):
ψ(u)=cos(5u) exp (−u2/2)\psi(u)= \cos(5u)\,\exp\!\big(-u^2/2\big)ψ(u)=cos(5u)exp(−u2/2)
前向计算(单样本 (x∈Rdx\in\mathbb{R}^dx∈Rd),这里让每个小波只吃一个维度 (x(j)x(j)x(j)),最稳):
- 假设有 (KKK) 个小波节点,且 (K=d×mK = d\times mK=d×m)(每层维度 (mmm) 个 ((a,b)(a,b)(a,b)))
- 对第 (j=1..dj=1..dj=1..d) 维输入,对应小波组 (k=(j−1)m+1..jmk=(j-1)m+1 .. jmk=(j−1)m+1..jm)
u=(x(j)−bk)/ak,hk=ψ(u)u = (x(j)-b_k)/a_k,\quad h_k=\psi(u)u=(x(j)−bk)/ak,hk=ψ(u)
- 输出
y^=w0+∑k=1Kwk hk\hat y = w_0 + \sum_{k=1}^{K} w_k\,h_ky^=w0+k=1∑Kwkhk
4) MATLAB:可运行的最小 Demo(单步预测 + MAPE/RMSE)
这是原理级可复现代码(不是调库),你可以直接贴进 MATLAB 跑通,再换成你的真实负荷 CSV。
matlab
%% ========= 1. 数据:造一条"有日周期+周末+噪声"的负荷 =========
Fs = 24; % 24点/天
N = 14*Fs; % 14天
t = (1:N)';
base = 100*ones(N,1);
daily = 30*(0.5+0.5*cos(2*pi*(t-7)/24)); % 日间高峰
week = 15*(mod((1:N)'-1,7)>=5); % 周末抬升
P = base + daily + week + 5*randn(N,1); % 负荷
P = max(P,50);
% 可视
figure; plot(t,P); grid on; title('Synthetic Load'); xlabel('hour index');
%% ========= 2. 构造监督样本(lag-24 单步预测)=========
L = 24; % 历史长度
D = L + 2; % 输入维:24负荷 + hour + weekend_flag
X = []; Y = [];
for i = (L+1):N
hist = P(i-L:i-1);
hr = mod(i-1,24)/24; % 小时归一化到 [0,1]
we = double(mod(i-1,7)==5 | mod(i-1,7)==6);
xi = [hist(:)./120 ; hr ; we]; % 简单归一化(你的真实数据再校准)
X = [X; xi'];
Y = [Y; P(i)];
end
% 输出也归一化(可选但更稳)
Ymean = mean(Y); Ystd = std(Y)+eps;
Y = (Y-Ymean)/Ystd;
%% ========= 3. 训练/测试切分(前70%训练)=========
n = size(X,1);
ntr = floor(0.7*n);
Xtr = X(1:ntr,:); Ytr = Y(1:ntr);
Xte = X(ntr+1:n,:); Yte = Y(ntr+1:n);
%% ========= 4. 初始化 WNN(Morlet 小波基)=========
d = size(X,2); % 输入维
m = 2; % 每个维的小波个数(可调)
K = d*m; % 总小波节点
% 参数打包:theta = [a(:); b(:); w(:); w0]
a0 = 0.5+0.3*rand(K,1);% 尺度
b0 = rand(K,1); % 平移(建议用输入统计量初始化更好)
w0 = randn(K,1)*0.1;
w00= 0;
theta0 = [a0;b0;w0;w00];
psi = @(u) cos(5*u).*exp(-u.^2/2); % Morlet(实部)
% ---------- 前向 ----------
function [y, H, Jac] = wnn_forward(X, theta, d, m)
K = d*m;
a = theta(1:K); b = theta(K+1:2*K); w = theta(2*K+1:3*K); w0 = theta(end);
Ns = size(X,1);
H = zeros(Ns,K);
for i=1:Ns
idx=0;
for j=1:d
for r=1:m
k=idx+r;
u=(X(i,j)-b(k))/a(k);
H(i,k)=psi(u);
end
idx=idx+m;
end
end
y = H*w + w0;
% Jacobian wrt theta(数值也行,但解析更稳定)
Jac = []; % 你把解析导放这里,或下面用数值Jacobian(见训练)
end
% ---------- 目标函数(带一点正则)==========
lambda = 1e-4;
fun = @(th) wnn_obj(th, Xtr, Ytr, d, m, lambda, psi);
%% ========= 5. 训练:Levenberg-Marquardt(推荐)=========
opts = optimoptions('lsqnonlin',...
'Algorithm','levenberg-marquardt',...
'Display','iter',...
'MaxIterations',120,...
'StepTolerance',1e-8);
[theta_hat,~,res] = lsqnonlin(fun, theta0,[],[],opts);
%% ========= 6. 推理 + 反归一化 + 指标 =========
pred_tr = wnn_pred(Xtr, theta_hat, d, m, psi)*Ystd + Ymean;
pred_te = wnn_pred(Xte, theta_hat, d, m, psi)*Ystd + Ymean;
Ytr_true = Ytr*Ystd + Ymean;
Yte_true = Yte*Ystd + Ymean;
fprintf('TRAIN MAPE=%.2f%% RMSE=%.3f\n',mape(Ytr_true,pred_tr),rmse(Ytr_true,pred_tr));
fprintf('TEST MAPE=%.2f%% RMSE=%.3f\n',mape(Yte_true,pred_te),rmse(Yte_true,pred_te));
figure; plot(Yte_true,'k'); hold on; plot(pred_te,'r--'); grid on;
legend('True','WNN Forecast'); title('WNN Load Forecast (Test)');
%% ========= 工具函数 =========
function F = wnn_obj(th, X, Y, d, m, lam, psi)
K = d*m;
a=th(1:K); b=th(K+1:2*K); w=th(2*K+1:3*K); w0=th(end);
Ns=size(X,1); E=zeros(Ns,1);
for i=1:Ns
s=w0;
idx=0;
for j=1:d
for r=1:m
k=idx+r;
u=(X(i,j)-b(k))/a(k);
s=s + w(k)*psi(u);
end
idx=idx+m;
end
E(i)=s-Y(i);
end
% 软正则(抑制权值爆炸)
F = [E; sqrt(lam)*w; sqrt(lam)*(a-0.5)];
end
function y = wnn_pred(X, th, d, m, psi)
K=d*m; a=th(1:K); b=th(K+1:2*K); w=th(2*K+1:3*K); w0=th(end);
Ns=size(X,1); y=zeros(Ns,1);
for i=1:Ns
s=w0; idx=0;
for j=1:d
for r=1:m
k=idx+r;
u=(X(i,j)-b(k))/a(k);
s=s+w(k)*psi(u);
end
idx=idx+m;
end
y(i)=s;
end
end
function v=mape(a,b), v=mean(abs(a-b)./max(abs(a),1e-6))*100; end
function v=rmse(a,b), v=sqrt(mean((a-b).^2)); end
参考代码 用于小波神经网络电力负荷预测 www.youwenfan.com/contentcsv/81439.html
5) 你把它用到"真实电力负荷 CSV"
- 读入 :
data = readtable('load.csv');拿到P = data.Load;与时间戳 - 做特征 :
hour = hour(timestamp),weekend = (weekday==6|7)- 有温度:
x_temp = (T-20)/15
- 归一化要"训练统计→测试"(更规范)
- 输入维改成:
[P(t-1)...P(t-L), hour_norm, weekend, temp_norm] - 小波节点数先从 每维 m=2~4 试(
K=d*m),过大会过拟合