ARTICLE DETAIL

资讯详情

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

VMD-CNN-BiLSTM-Attention电力负荷预测Python代码包:从分解到消融实战

VMD-CNN-BiLSTM-Attention电力负荷预测Python代码包:从分解到消融实战 简介这份资源面向电力系统负荷预测方向的学习者与毕业设计开发者提供基于VMD-CNN-BiLSTM-Attention组合模型的完整Python代码实现。内容围绕变分模态分解VMD与深度学习网络的融合思路展开适合具备一定Python与深度学习基础、需要完成相关课题或复现实验的读者参考。压缩包共15个文件约2.86MB以py脚本为主体辅以ipynb交互式笔记、zbak备份文件以及csv、xlsx格式的电力负荷数据与说明文档覆盖数据分解、模型搭建到结果保存的完整流程。资源中同时包含VMD-LSTM、VMD-CNN-LSTM、VMD-CNN-BiGRU等多种对比模型脚本便于横向比较不同网络结构的预测效果并附有VMD分解数据保存与多折验证的笔记文件可帮助读者理解数据预处理与实验组织方式。目前已有119人学习下载适合作为负荷预测课题的代码参考与实验起点。1. 电力负荷预测的 VMD-CNN-BiLSTM-Attention 组合模型这份 Python 代码包能跑出什么做电力负荷预测的同行大多有过这种经历单一 LSTM 在平稳段拟合得还行一到节假日或气温骤变的拐点就明显滞后MAPE 直接翻倍。这份资源给了一条组合路线——先用 VMD 把原始负荷序列拆成若干模态分量再让 CNN 提局部特征、BiLSTM 抓双向时序依赖、Attention 给关键时间步加权。压缩包里是完整的 Python 实现包含 VMD-CNN-BiLSTM-Attention.py 主模型还附带 VMD-CNN-LSTM、VMD-CNN-BiGRU、VMD-LSTM 等对照脚本以及 VMD.xlsx、电力负荷预测数据2.csv 两份数据和一份说明.txt。它适合正在做毕业设计、课程设计或想快速搭一套负荷预测基线的人也适合已经写过单模型、想看看多分支组合到底能提升多少的从业者。下面按「数据怎么进、模型怎么搭、坑在哪」的顺序拆开讲。2. VMD 分解与数据管线从原始负荷序列到可训练张量2.1 为什么先做 VMD 而不是直接喂原始序列电力负荷序列本身是强非平稳信号直接送进网络模型要同时学趋势、周期和随机扰动收敛慢且容易过拟合。VMD变分模态分解把信号拆成 K 个有限带宽的模态分量每个分量围绕中心频率分布相当于把「混在一起的问题」拆成几个相对平稳的子问题。常见做法是 K 取 4 到 8具体看序列长度和波动程度K 太小分解不充分K 太大则出现过分解模态之间频率混叠后面预测反而更差。这份代码包里 VMD 分解数据保存.py 就是干这件事的它把分解结果落盘避免每次训练都重跑分解。2.2 分解结果落盘与数据集构造先看分解脚本的核心逻辑下面这段是常见写法参数按自己数据调整import numpy as np import pandas as pd from vmdpy import VMD # 读取原始负荷序列假设单列索引为时间 df pd.read_csv(电力负荷预测数据2.csv) signal df[load].values.astype(float) # VMD 参数K 模态数alpha 带宽约束tau 噪声容限DC 是否含直流init 初始化tol 收敛容差 K 5 alpha 2000 tau 0 DC 0 init 1 tol 1e-7 u, u_hat, omega VMD(signal, alpha, tau, K, DC, init, tol) # u 形状为 (K, N)每行是一个模态分量 np.save(vmd_modes.npy, u) print(分解完成模态形状:, u.shape)逻辑说明VMD 返回的 u 是 K 个模态分量后续每个分量单独构造监督学习样本。参数 alpha 控制带宽负荷数据一般取 1000 到 3000tau 取 0 表示无噪声容限数据干净时可用。分解完务必保存因为 VMD 是迭代优化每次结果有细微差异固定下来才能复现实验。2.3 滑动窗口构造与归一化分解之后要把每个模态转成「输入窗口 → 预测步长」的样本对。常见做法是用前 24 个点预测后 1 个点日前预测或前 96 点预测后 96 点。归一化建议对每个模态单独做 Min-Max而不是全局归一化否则幅值小的模态会被压扁。def make_dataset(modes, lookback24, horizon1): X, y [], [] for mode in modes: # 每个模态单独归一化 mode (mode - mode.min()) / (mode.max() - mode.min() 1e-8) for i in range(len(mode) - lookback - horizon 1): X.append(mode[i:ilookback]) y.append(mode[ilookback:ilookbackhorizon]) return np.array(X), np.array(y) X, y make_dataset(u, lookback24, horizon1) # X 形状 (样本数, 24)送入网络前需 reshape 成 (样本数, 24, 1) X X[..., np.newaxis] print(X.shape, y.shape)参数说明lookback 是历史窗口长度horizon 是预测步长。注意所有模态的样本是拼在一起的训练时模型学的是「给定某模态的历史片段预测其未来」预测阶段再把各模态预测值相加还原成原始负荷。这一步如果搞错比如先相加再预测就退化成单模型了。3. CNN-BiLSTM-Attention 网络搭建各模块职责与张量流转3.1 三个模块各自解决什么问题CNN 负责在时间维上做一维卷积提取局部突变和短时模式比如负荷爬坡的斜率特征BiLSTM 从前向和后向两个方向读序列捕捉长距离依赖对周期性负荷尤其有效Attention 则对 BiLSTM 各时间步的输出加权求和让模型自己决定哪些时刻更重要——比如预测点前几个时刻通常权重更高。三者串联的顺序一般是 CNN → BiLSTM → Attention → 全连接输出。这份代码包里 VMD-CNN-BiLSTM-Attention.py 就是这个结构另外几个脚本是去掉某个模块的对照版本方便做消融。3.2 用 PyTorch 搭出主模型下面给出核心网络定义可直接对照代码包里的实现import torch import torch.nn as nn class CNNBiLSTMAttention(nn.Module): def __init__(self, input_dim1, cnn_channels32, hidden_dim64, num_layers2): super().__init__() # 一维卷积提局部特征kernel_size3 覆盖相邻三个时刻 self.conv nn.Sequential( nn.Conv1d(input_dim, cnn_channels, kernel_size3, padding1), nn.ReLU(), nn.MaxPool1d(kernel_size2) ) self.bilstm nn.LSTM(cnn_channels, hidden_dim, num_layers, batch_firstTrue, bidirectionalTrue) # Attention对 BiLSTM 输出做加性注意力 self.attn nn.Linear(hidden_dim * 2, 1) self.fc nn.Linear(hidden_dim * 2, 1) def forward(self, x): # x: (batch, seq_len, 1) - conv 需要 (batch, channel, seq_len) x x.permute(0, 2, 1) x self.conv(x) x x.permute(0, 2, 1) # 回到 (batch, seq_len, channels) out, _ self.bilstm(x) # out: (batch, seq_len, hidden*2) score self.attn(out) # (batch, seq_len, 1) weight torch.softmax(score, dim1) context torch.sum(out * weight, dim1) # 加权求和 return self.fc(context)逻辑说明卷积后序列长度被 MaxPool 减半BiLSTM 在缩短的序列上跑计算量下降。Attention 用单层线性映射打分再 softmax属于最常见的加性注意力变体。参数上 cnn_channels 和 hidden_dim 是主要调参对象负荷数据量不大时 32/64 够用数据多可加到 64/128。num_layers 超过 2 容易过拟合建议配合 Dropout。3.3 训练循环与损失选择负荷预测常用 MSE 或 MAE。MSE 对大误差敏感适合关注峰值MAE 更稳健。下面训练片段里加了早停和梯度裁剪model CNNBiLSTMAttention() optimizer torch.optim.Adam(model.parameters(), lr1e-3) criterion nn.MSELoss() for epoch in range(200): model.train() for xb, yb in train_loader: optimizer.zero_grad() pred model(xb) loss criterion(pred, yb) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm5.0) optimizer.step() # 验证集评估略按 val_loss 早停参数说明lr 从 1e-3 起调不收敛就降到 1e-4clip_grad_norm_ 防止 LSTM 梯度爆炸max_norm 取 5 是经验值。早停耐心值一般设 10 到 20 轮。注意每个模态是拼在一起训练的如果模态幅值差异大建议按模态分组做 batch否则大模态主导梯度。4. 避坑与排查跑这份代码最容易翻车的五个地方4.1 现象预测曲线整体平移MAPE 正常但峰值全错原因归一化用了全局 min/max而测试集峰值超出训练集范围反归一化后系统性偏移。解决对每个模态单独归一化并保存训练集的 min/max 用于测试集反归一化不要用测试集自身统计量。4.2 现象VMD 每次跑结果不一样实验无法复现原因VMD 是迭代算法初始化和收敛容差影响结果且部分实现含随机成分。解决分解一次后把 u 保存成 npy 或 xlsx后续训练直接加载固定 init 和 tol并在说明里记录参数。4.3 现象训练 loss 下降但验证 loss 震荡Attention 权重几乎均匀原因Attention 打分层输入未做归一化BiLSTM 输出幅值差异大softmax 后接近均匀分布。解决在 Attention 前加 LayerNorm或对 BiLSTM 输出做缩放也可先跑无 Attention 版本确认基线。4.4 现象CNN 卷积后序列长度对不上报维度错误原因Conv1d 的 padding 和 MaxPool1d 的 kernel_size 组合导致长度变化BiLSTM 输入维度与预期不符。解决按公式算清楚输出长度或把 MaxPool 换成步长为 1 的卷积调试时打印每层输出 shape。4.5 现象多模态预测结果相加后误差反而比单模态大原因各模态独立预测误差在相加时累积且高频模态本身难预测。解决对高频模态降低权重或单独评估必要时只对低频模态做预测、高频用简单方法也可在损失里对重构后的总负荷加约束。5. 从跑通到跑好消融对比与结果验证的实操技巧代码包里给了 VMD-CNN-LSTM、VMD-CNN-BiGRU、VMD-LSTM 几个对照脚本这不是凑数而是做消融实验的现成材料。我的习惯是固定同一份 VMD 分解结果和同一组训练/测试划分只换模型结构跑三到五次取均值记录 MAE、RMSE、MAPE 三个指标。下面这张表是我一般会整理的对比格式模型MAERMSEMAPE(%)训练耗时(s)VMD-LSTM待填待填待填待填VMD-CNN-LSTM待填待填待填待填VMD-CNN-BiLSTM待填待填待填待填VMD-CNN-BiLSTM-Attention待填待填待填待填填表时注意所有模型用同一随机种子测试集绝不参与调参。Attention 的增益通常在峰值段和拐点段最明显如果整体 MAPE 只降了零点几个百分点别急着下结论把预测曲线画出来看拐点处是否贴合。另一个技巧是把 Attention 权重导出看模型在预测某个时刻时主要关注历史哪几个点如果权重集中在最近几个时刻说明它退化成了简单滑动平均这时要检查打分层是否太浅。还有个容易忽略的点VMD 分解的模态数 K 本身是个超参数可以和模型结构一起调。我一般先固定 K5 跑通全流程再试 K4、6、7看验证集误差。K 增大后模态变多样本数成倍增长训练时间上升但未必带来收益。最后提醒一句这份代码是学习交流用的基线实现真正上生产还要考虑数据泄漏、在线更新和异常值处理。从那以后我每次拿到组合模型代码都强制先跑一遍单模型基线确认增益真实存在再往下调希望帮到你。本文还有配套的精品资源点击获取
返回列表