ARTICLE DETAIL

资讯详情

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

PyTorch LSTM电力负荷预测实战:从时序数据到可复现源码

PyTorch LSTM电力负荷预测实战:从时序数据到可复现源码 简介这份资源面向深度学习初学者与电力系统数据分析人员提供一套基于PyTorch实现LSTM电力负荷预测的完整源码与项目说明帮助读者掌握序列数据建模、模型训练与评估的实践流程。压缩包共14个文件约2.1MB以5个py脚本、5个csv数据集、1个pt模型权重、1个md说明文档及缓存文件为主分别对应数据预处理、模型搭建、训练测试与结果可视化等模块。已有156人学习下载。读者可借助项目说明文档理解LSTM门控机制与PyTorch动态图用法结合csv负荷数据完成清洗、归一化与序列构造并通过MSE、MAE、R²等指标对比预测值与真实负荷进而调整隐藏层单元数、学习率与批次大小等超参数优化效果。目录结构清晰适合作为课程设计、毕业设计或电力系统深度学习入门的参考范例。1. 电力负荷预测的 LSTM 实战从时序数据到可复现的 PyTorch 源码电力负荷预测是能源行业最典型的时序回归任务之一调度端需要提前知道未来 24 小时甚至 7 天的负荷曲线才能安排机组启停和备用容量。传统做法用 ARIMA 或线性回归遇到周末、节假日、极端气温这类非线性拐点就明显吃力。这份资源给的是一个基于 PyTorch 的 LSTM 最小可运行实现包含完整源码和项目说明适合两类人一是刚学完 PyTorch 基础、想找一个真实时序项目练手的同学二是手上有一份历史负荷 CSV、想快速搭个基线模型验证特征有效性的工程师。它不追求 SOTA 精度胜在结构清晰、依赖干净、改起来快你能在一两个小时内跑通训练并看到预测曲线。2. LSTM 做负荷预测的原理与这份源码的选型逻辑2.1 为什么是 LSTM 而不是全连接或普通 RNN电力负荷序列有两个绕不开的特性周期性和长程依赖。日周期早高峰、午间回落、晚高峰和週周期工作日与周末差异叠加在一起意味着当前时刻的负荷和 24 小时前、168 小时前的值强相关。普通全连接网络把输入当成独立样本必须手工构造大量滞后特征才能捕捉这种关系普通 RNN 在反向传播时梯度容易消失超过 20 个时间步就学不动了。LSTM 通过输入门、遗忘门、输出门三个门控结构维护一条细胞状态让信息可以在几十上百个时间步上稳定传递。对负荷预测来说遗忘门会自动学会「丢掉上周同期的噪声、保留趋势项」这是它比手工特征工程更省心的地方。这份源码选择单层 LSTM 加一层全连接输出而不是堆叠多层或上 Transformer理由很实际负荷数据量通常只有几万条模型太深直接过拟合而且单层 LSTM 在 CPU 上就能训练不需要 GPU 也能验证流程。2.2 源码的整体结构与数据流拿到压缩包解压后目录结构大致是数据文件、模型定义、训练脚本、预测脚本和一份说明文档。核心数据流是原始负荷序列 → 滑动窗口切分成 (输入序列, 目标值) 样本 → 归一化 → 按时间顺序划分训练/测试集 → 送入 LSTM → 全连接映射到单值输出 → 反归一化得到真实负荷。这里有个容易被忽略的设计点划分数据集必须按时间顺序切不能随机打乱。负荷序列前后有时序依赖随机划分会让模型在训练时「偷看」到未来的统计分布测试指标虚高上线就翻车。源码里如果用了train_test_split且没设shuffleFalse这是第一个要改的地方。2.3 环境搭建与依赖确认PyTorch 的安装是新手第一道坎CPU 版和 CUDA 版命令完全不同。如果你只是跑这份负荷预测源码数据量小CPU 版足够装起来也省事。常见做法是用 conda 建一个独立环境避免和系统里的其他包冲突。# 创建独立环境python 版本建议 3.9 到 3.11 conda create -n load_lstm python3.10 conda activate load_lstm # CPU 版 PyTorch最省事跑这份源码够用 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 数据处理和画图依赖 pip install pandas numpy matplotlib scikit-learn如果你有 NVIDIA 显卡并想用 GPU 加速去 PyTorch 官网按你的 CUDA 版本选对应命令不要直接pip install torch那样装到的可能是 CPU 版。装完后用下面这段验证import torch print(torch.__version__) print(CUDA 可用:, torch.cuda.is_available()) # 如果输出 False 但你确实有显卡多半是装成了 CPU 版参数说明torch.__version__确认版本号torch.cuda.is_available()返回布尔值决定后续代码里device怎么设。源码里通常有一行device torch.device(cuda if torch.cuda.is_available() else cpu)这行是自适应的不用手改。2.4 数据准备与滑动窗口构造负荷数据一般是一列时间戳加一列负荷值采样间隔 15 分钟或 1 小时。LSTM 需要的是定长序列样本所以要用滑动窗口把长序列切成一条条训练样本。假设用过去 24 个点预测下一个点import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 读取负荷数据假设列名为 load df pd.read_csv(load.csv, parse_dates[timestamp]) values df[load].values.reshape(-1, 1) # 归一化LSTM 对输入尺度敏感这步不能省 scaler MinMaxScaler(feature_range(0, 1)) scaled scaler.fit_transform(values) # 滑动窗口seq_len 是回看步数这里取 24 def make_sequences(data, seq_len): xs, ys [], [] for i in range(len(data) - seq_len): xs.append(data[i:i seq_len]) ys.append(data[i seq_len]) return np.array(xs), np.array(ys) seq_len 24 X, y make_sequences(scaled, seq_len) # 按时间顺序切分前 80% 训练后 20% 测试绝不能 shuffle split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] # 转成 tensor import torch X_train torch.tensor(X_train, dtypetorch.float32) y_train torch.tensor(y_train, dtypetorch.float32) X_test torch.tensor(X_test, dtypetorch.float32) y_test torch.tensor(y_test, dtypetorch.float32) print(X_train.shape) # 期望 (样本数, 24, 1)逻辑说明MinMaxScaler把负荷压到 0 到 1是因为 LSTM 的激活函数对大幅值输入不友好不归一化损失会震荡不收敛。make_sequences里seq_len决定模型能看多远的历史24 对应一天 24 小时小时采样或 6 小时15 分钟采样这个值要结合你的采样频率和预测目标调。切分用切片而不是随机函数是保证测试集严格在训练集之后模拟真实预测场景。参数怎么改seq_len调大能捕捉更长周期但样本数会减少且训练变慢一般从 24 起步试 48、168 对比验证集误差。feature_range如果数据有极端尖峰可以改成(0.1, 0.9)留出余量。3. 模型定义、训练循环与预测反归一化3.1 LSTM 网络结构逐层拆解源码里的模型类通常长这样我把它拆开讲清楚每个参数import torch.nn as nn class LoadLSTM(nn.Module): def __init__(self, input_size1, hidden_size64, num_layers1, output_size1): super().__init__() self.hidden_size hidden_size self.num_layers num_layers # batch_firstTrue 让输入维度是 (batch, seq, feature) self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue) self.fc nn.Linear(hidden_size, output_size) def forward(self, x): # h0, c0 初始化为全零 h0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device) c0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device) out, _ self.lstm(x, (h0, c0)) # 只取最后一个时间步的输出做预测 out self.fc(out[:, -1, :]) return out逻辑说明input_size1是因为单变量负荷预测如果你加了温度、星期几等外生变量这里要改成对应维度。hidden_size64是隐状态维度太小欠拟合太大过拟合且慢64 到 128 是常见区间。batch_firstTrue很关键PyTorch 的 LSTM 默认输入是 (seq, batch, feature)设成 True 后变成 (batch, seq, feature)和 DataLoader 的输出对齐忘了设会导致维度报错。out[:, -1, :]取序列最后一步的隐状态因为预测的是「看完过去 24 步之后的下一个值」。3.2 训练循环与损失函数选择负荷预测是回归任务损失用 MSE 或 MAE。MSE 对大误差惩罚重适合关注峰值预测准确度MAE 对异常值更鲁棒。源码一般用 MSE配合 Adam 优化器。import torch.optim as optim from torch.utils.data import TensorDataset, DataLoader device torch.device(cuda if torch.cuda.is_available() else cpu) model LoadLSTM().to(device) criterion nn.MSELoss() optimizer optim.Adam(model.parameters(), lr1e-3) train_loader DataLoader(TensorDataset(X_train, y_train), batch_size32, shuffleTrue) epochs 50 for epoch in range(epochs): model.train() total_loss 0 for xb, yb in train_loader: xb, yb xb.to(device), yb.to(device) optimizer.zero_grad() pred model(xb) loss criterion(pred, yb) loss.backward() optimizer.step() total_loss loss.item() if (epoch 1) % 10 0: print(fEpoch {epoch1}, Loss: {total_loss/len(train_loader):.6f})逻辑说明optimizer.zero_grad()必须在反向传播前调用否则梯度会累加这是 PyTorch 新手最常见的错误之一。batch_size32是折中值数据量小可以降到 16训练更稳但慢。lr1e-3是 Adam 的常用起点如果 loss 震荡就降到 1e-4如果下降太慢就升到 5e-3 试。训练集这里可以 shuffle因为样本之间已经通过滑动窗口构造好了打乱不破坏时序逻辑但测试集和验证集绝不能 shuffle。3.3 预测与反归一化最容易出错的一步模型输出的是 0 到 1 之间的归一化值必须用训练时的 scaler 反变换回真实负荷量纲。这里有个血泪经验反归一化必须用训练集的 scaler不能用测试集重新 fit 一个否则量纲对不上预测曲线整体偏移。model.eval() with torch.no_grad(): X_test_dev X_test.to(device) pred_scaled model(X_test_dev).cpu().numpy() # 反归一化scaler 是训练时 fit 的那个 pred scaler.inverse_transform(pred_scaled) true scaler.inverse_transform(y_test.numpy()) # 计算误差指标 from sklearn.metrics import mean_absolute_error, mean_squared_error mae mean_absolute_error(true, pred) rmse np.sqrt(mean_squared_error(true, pred)) print(fMAE: {mae:.2f}, RMSE: {rmse:.2f}) # 画图对比 import matplotlib.pyplot as plt plt.plot(true, label真实值) plt.plot(pred, label预测值) plt.legend() plt.savefig(prediction.png)逻辑说明model.eval()切换推理模式关掉 dropout 和 batchnorm 的训练行为虽然这份源码可能没用到这些层但养成习惯没坏处。torch.no_grad()关闭梯度计算省显存也加速。反归一化时scaler.inverse_transform接收的是二维数组所以pred_scaled要保持 (N, 1) 形状如果中间被 squeeze 成一维会报错。MAE 和 RMSE 一起看MAE 反映平均偏差RMSE 对大误差敏感如果 RMSE 远大于 MAE说明存在个别预测严重偏离的点通常是节假日或极端天气需要检查特征里有没有日期信息。4. 避坑与排查跑不通这份源码的五个高频问题4.1 现象Loss 一直是 nan 或者不下降原因最常见是学习率太大或者输入没归一化。负荷原始值可能是几千上万千瓦直接喂进 LSTM梯度爆炸loss 直接变 nan。另一个可能是数据里有空值pandas 读进来是 NaN参与计算后污染整个 batch。解决先确认scaler.fit_transform那步做了打印scaled.min()和scaled.max()应该在 0 到 1 之间。再检查df.isnull().sum()有空值就df.dropna()或前向填充。学习率从 1e-3 降到 1e-4 再试。4.2 现象报维度错误提示 expected input size 不匹配原因input_size和实际特征数对不上。比如你给数据加了温度、湿度两列特征变成 3 维但模型里input_size还是默认的 1。或者batch_first没设输入维度顺序错了。解决打印X_train.shape确认最后一维是特征数把它传给LoadLSTM(input_size特征数)。确认 LSTM 初始化时batch_firstTrue。4.3 现象测试集预测曲线整体平移形状对但数值差一截原因反归一化用错了 scaler或者训练集和测试集分别 fit 了不同的 scaler。也有可能是数据本身有趋势项MinMaxScaler 对趋势不敏感训练集最大值和测试集最大值差很多时反变换会系统性偏移。解决全局只 fit 一次 scaler训练测试共用。如果数据有明显增长趋势改用 StandardScaler 或先做差分去掉趋势再归一化。4.4 现象训练 loss 很低但测试 loss 很高原因过拟合。模型记住了训练集的噪声泛化差。负荷数据量小的时候尤其明显。解决减小hidden_size从 64 降到 32加 dropout在 LSTM 后加nn.Dropout(0.2)或者加 L2 正则在 optimizer 里设weight_decay1e-4。另外检查是不是随机打乱划分了数据集那会造成信息泄漏测试指标虚低。4.5 现象预测结果永远是一条平线原因模型没学到东西输出收敛到均值附近。可能是seq_len太短模型看不到周期也可能是训练轮数不够loss 还没降下来就停了还可能是学习率太小参数几乎没更新。解决把seq_len从 24 加到 48 或 168让它能看到完整周期。训练轮数加到 100 以上观察 loss 曲线是否还在下降。学习率调到 1e-3 或 5e-3。5. 进阶技巧多变量输入与预测步长扩展跑通单变量单步预测之后真正能提升精度的是引入外生变量。负荷不只和历史负荷有关还和温度、星期几、是否节假日强相关。把温度列和 one-hot 编码的星期列拼到输入特征里input_size从 1 变成 1179模型能学到「高温天负荷高」「周末负荷低」这类规律。我一般会先做特征相关性分析把和负荷相关系数低于 0.1 的变量剔掉避免噪声。# 假设 df 已有 load, temperature, weekday 列 df[weekday] pd.to_datetime(df[timestamp]).dt.weekday weekday_dummies pd.get_dummies(df[weekday], prefixwd) features pd.concat([df[[load, temperature]], weekday_dummies], axis1) # 对 load 和 temperature 分别归一化dummy 列保持 0/1另一个方向是多步预测。上面代码只预测下一个点实际调度要未来 24 个点。两种做法一是直接多输出把output_size改成 24一次吐出整条曲线二是滚动预测把预测值喂回输入窗口一步步推。直接多输出训练更稳但每个步长共享同一个隐状态远期精度会衰减滚动预测灵活但误差会累积。我一般先用直接多输出做基线误差不达标再换滚动。验证模型有没有真的学到东西别只看 loss 数字。把预测曲线和真实曲线叠在一起看三个位置早高峰的峰值有没有预测准、午间回落有没有跟上、周末的低谷有没有识别出来。如果峰值总是被削平说明模型偏向保守可以给峰值样本加权或者在损失里对高峰时段加大惩罚。从那以后我每次跑完负荷预测都会强制把预测图和真实图叠出来肉眼过一遍数字指标会骗人曲线不会。希望帮到你。本文还有配套的精品资源点击获取
返回列表