ARTICLE DETAIL

资讯详情

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

基于LSTM的短期光伏预测Python源码与数据集实战指南

基于LSTM的短期光伏预测Python源码与数据集实战指南 简介本资源为基于LSTM的短期光伏预测算法Python实现包面向计算机、人工智能、通信工程、自动化等专业的在校学生、教师及企业技术人员可用于毕业设计、课程设计、项目立项演示或算法进阶学习。包内共11个文件以6个ipynb交互式笔记本为核心配合1个py脚本、1个xlsx数据表、1个txt使用说明及png、jpg图示压缩包约3.89MB结构轻量便于快速上手。内容围绕园区光伏与负荷数据展开涵盖单变量与多变量预测流程、规则集与储能框架探索、模拟程序及数据清洗脚本可帮助读者理解LSTM在时间序列预测中的建模思路、特征构造与结果评估方法。已有248人学习下载适合希望掌握短期光伏功率预测完整实现路径、并在此基础上修改扩展功能的读者参考。1. 从一份 LSTM 光伏预测源码包说起它到底能解决什么问题光伏电站最头疼的不是发电而是「发多少」说不准。云层飘过来三分钟功率能从满载掉到三成调度侧要备用容量交易侧要报次日曲线偏差一大就是真金白银的罚款。短期光伏预测要干的事就是拿历史功率、辐照度、温度、风速这些时序数据把未来 1 到 24 小时的出力曲线提前算出来。这份「基于 LSTM 的短期光伏预测算法 python 源码 数据集」压缩包本质是一套能跑通的最小闭环数据读取、归一化、滑窗构造、LSTM 建模、训练、评估、画图一条龙。它适合两类人——刚入门时间序列预测、想找一个能跑通全流程的 python 项目练手的新手以及手上真有电站数据、想快速验证 LSTM 到底比持久化模型强多少的运维或算法工程师。别指望它直接上线但拿它当基线、当脚手架性价比很高。2. LSTM 做光伏预测的原理与选型为什么不是 ARIMA 也不是 XGBoost2.1 光伏功率序列的三个特性决定了模型选型光伏功率序列有三个绕不开的特性。第一是强日周期性晴天曲线几乎是标准正弦早上爬坡、正午封顶、傍晚回落。第二是天气突变带来的非平稳性一片云就能让功率在分钟级抖出 40% 的波动这种突变没有明显的前兆规律。第三是多变量耦合功率不只跟自身历史有关还跟辐照度、组件温度、环境温度强相关。传统 ARIMA 类模型假设序列线性、平稳遇到云遮这种非线性突变基本抓瞎差分阶数调半天也压不住误差。树模型如 XGBoost 对特征工程依赖极重你得手工构造滞后项、滑动均值、辐照度交互项特征没做好效果就上不去而且它天然不擅长处理长序列的时序依赖。LSTM 的门控结构遗忘门、输入门、输出门恰好能选择性地记住「昨天同一时刻的功率水平」这种长周期信息又能对短时突变做出响应输入多变量也天然支持。这就是为什么短期光伏预测里 LSTM 及其变体BiLSTM、CNN-LSTM、Attention-LSTM是主流基线。提示LSTM 不是万能的。如果只有功率单变量、且预测步长只有 15 分钟持久化模型拿上一时刻值当预测往往就很难打败先跑通持久化基线再上 LSTM才知道模型到底有没有价值。2.2 从零把环境搭起来python 与 pytorch 的版本选择拿到源码包第一件事不是急着跑而是把环境对齐。LSTM 实现主流用 PyTorch 或 TensorFlow/Keras这份源码包大概率是 PyTorch 路线pytorch lstm 源码是热搜高频词。python 安装建议 3.9 到 3.11太新的版本某些科学计算库轮子还没跟上太老的又缺特性。用 conda 建独立环境避免污染系统 python。# 创建独立环境python 版本锁在 3.10 conda create -n pv_lstm python3.10 -y conda activate pv_lstm # 安装核心依赖pytorch 按自己显卡的 CUDA 版本去官网选对应命令 # 这里给的是 CPU 版示例有 GPU 的换成 cu118 对应命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install numpy pandas matplotlib scikit-learn openpyxl这段命令的逻辑是先隔离环境再装框架和数据处理三件套。参数上python3.10是稳妥选择--index-url指定 pytorch 官方源避免装到不匹配的版本openpyxl是为了读 Excel 格式的数据集很多电站导出就是 xlsx。装完用python -c import torch; print(torch.__version__)验证能打印版本号就说明环境通了。vscode python 环境配置的话记得在右下角把解释器切到刚建的pv_lstm否则跑起来还是系统 python报「找不到 torch」的玄学错误多半出在这。2.3 数据集长什么样字段、粒度与清洗要点光伏数据集通常包含时间戳、有功功率、辐照度、组件温度、环境温度、风速、风向这几列。粒度常见 15 分钟或 1 小时一条一天 96 点或 24 点。拿到数据先做三件事时间戳解析、缺失值处理、异常值剔除。import pandas as pd import numpy as np # 读取数据parse_dates 直接把时间列解析成 datetime df pd.read_excel(pv_data.xlsx, parse_dates[timestamp]) df df.sort_values(timestamp).reset_index(dropTrue) # 缺失值功率列用线性插值气象列用前向填充 df[power] df[power].interpolate(methodlinear, limit4) df[irradiance] df[irradiance].ffill() # 异常值夜间功率应为 0出现负值或白天超装机容量的直接置 NaN 再插值 df.loc[df[power] 0, power] np.nan df.loc[df[power] df[capacity], power] np.nan df[power] df[power].interpolate(methodlinear) # 加时间特征小时和分钟能帮模型捕捉日周期 df[hour] df[timestamp].dt.hour df[minute] df[timestamp].dt.minute逻辑说明interpolate的limit4表示连续缺失超过 4 个点就不插了避免用假数据填出一大段异常值先置 NaN 再插值比直接删行保留更多样本。参数上capacity是电站装机容量得从数据说明里拿没有就问现场。清洗完打印df.isna().sum()确认没有残留空值否则后面归一化会报错。3. 把 LSTM 模型跑起来滑窗构造、网络定义与训练循环3.1 滑窗构造把时序问题变成监督学习问题LSTM 吃的是序列但训练时需要「输入序列 对应标签」的样本对。滑窗就是拿过去 N 个时刻的多变量特征预测未来 M 个时刻的功率。N 是回看窗口M 是预测步长。from sklearn.preprocessing import MinMaxScaler features [power, irradiance, temperature, hour] data df[features].values # 归一化LSTM 对量纲敏感不归一化收敛极慢 scaler MinMaxScaler() data_scaled scaler.fit_transform(data) def make_windows(data, lookback24, horizon4): X, y [], [] for i in range(len(data) - lookback - horizon 1): X.append(data[i:i lookback]) # 过去 24 个点 y.append(data[i lookback:i lookback horizon, 0]) # 未来 4 个点的功率 return np.array(X), np.array(y) X, y make_windows(data_scaled, lookback24, horizon4) print(X.shape, y.shape) # (样本数, 24, 4) (样本数, 4)逻辑说明lookback24对应 15 分钟粒度就是过去 6 小时horizon4是预测未来 1 小时。y只取第 0 列功率因为预测目标就是功率。参数怎么定回看窗口太短抓不到日周期太长引入噪声且训练慢24 到 96 是常见区间预测步长按业务需求日前调度要 96 步实时调度 4 步就够。注意归一化必须用训练集 fit再 transform 测试集否则数据泄漏评估结果虚高这是血泪经验。3.2 LSTM 网络定义层数、隐藏单元与 dropout 的取舍网络结构不用堆太深光伏预测这种任务两层 LSTM 足够堆到四五层反而过拟合。import torch import torch.nn as nn class PVLSTM(nn.Module): def __init__(self, input_size4, hidden_size64, num_layers2, output_size4): super().__init__() self.lstm nn.LSTM( input_sizeinput_size, hidden_sizehidden_size, num_layersnum_layers, batch_firstTrue, dropout0.2, # 两层以上才生效 ) self.fc nn.Linear(hidden_size, output_size) def forward(self, x): out, _ self.lstm(x) # out: (batch, seq, hidden) out out[:, -1, :] # 取最后一个时间步 return self.fc(out) model PVLSTM() print(sum(p.numel() for p in model.parameters()), 个参数)逻辑说明batch_firstTrue让输入维度是 (batch, seq, hidden)符合直觉out[:, -1, :]取最后一个时间步的隐藏状态因为它聚合了整段序列的信息dropout0.2是防过拟合的常规值注意单层 LSTM 时 dropout 不生效。参数上hidden_size64是起点数据量大可以加到 128数据少就降到 32num_layers2够用再深收益递减。参数量打印出来心里有数几万到几十万级别都正常。3.3 训练循环与早停损失曲线怎么看训练用 MSE 损失、Adam 优化器加早停防止过拟合。from torch.utils.data import TensorDataset, DataLoader X_t torch.tensor(X, dtypetorch.float32) y_t torch.tensor(y, dtypetorch.float32) loader DataLoader(TensorDataset(X_t, y_t), batch_size64, shuffleTrue) model PVLSTM() criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) best_loss, patience, wait float(inf), 10, 0 for epoch in range(200): model.train() for xb, yb in loader: optimizer.zero_grad() loss criterion(model(xb), yb) loss.backward() optimizer.step() # 简单起见用训练损失做早停正式项目应看验证集 if loss.item() best_loss: best_loss, wait loss.item(), 0 torch.save(model.state_dict(), best_lstm.pt) else: wait 1 if wait patience: print(f早停于 epoch {epoch}) break if epoch % 20 0: print(fepoch {epoch}, loss {loss.item():.6f})逻辑说明batch_size64是显存和收敛稳定性的折中lr1e-3是 Adam 的默认甜点值loss 震荡就降到 5e-4patience10表示连续 10 轮没进步就停。看损失曲线正常是快速下降后趋平如果训练 loss 一直不降检查归一化和学习率如果训练 loss 降但验证 loss 涨就是过拟合加 dropout 或减层数。正式项目一定要切验证集这里为了代码简洁用训练 loss 演示别照搬到生产。4. 评估与调参MAPE、RMSE 怎么算超参数怎么搜4.1 反归一化与评估指标别在归一化空间里算误差预测出来的值还在 0 到 1 之间必须反归一化回真实功率量纲再算误差否则 MAPE 毫无意义。from sklearn.metrics import mean_absolute_error, mean_squared_error model.eval() with torch.no_grad(): pred model(X_t).numpy() # 反归一化功率是第 0 列用 scaler 的 min/max 还原 p_min, p_max scaler.data_min_[0], scaler.data_max_[0] pred_real pred * (p_max - p_min) p_min y_real y * (p_max - p_min) p_min mae mean_absolute_error(y_real.flatten(), pred_real.flatten()) rmse np.sqrt(mean_squared_error(y_real.flatten(), pred_real.flatten())) # MAPE 要避开夜间 0 功率否则除零爆炸 mask y_real.flatten() 0.05 * p_max mape np.mean(np.abs((y_real.flatten()[mask] - pred_real.flatten()[mask]) / y_real.flatten()[mask])) * 100 print(fMAE {mae:.2f}, RMSE {rmse:.2f}, MAPE {mape:.2f}%)逻辑说明反归一化用data_min_和data_max_这是 MinMaxScaler 记录的训练集极值。MAPE 的坑在于夜间功率接近 0分母极小导致百分比爆炸所以用mask只统计功率大于装机 5% 的白天点。指标参考短期光伏预测 MAPE 做到 10% 以内算不错晴天能到 5%阴雨天 15% 到 20% 也正常别拿晴天指标去要求阴天。4.2 超参数搜索回看窗口、隐藏单元、学习率三件套调参优先动这三个其他先固定。超参数常用范围影响调整建议lookback16 / 24 / 48 / 96太短抓不到周期太长噪声大从 24 起按粒度换算成 6 到 24 小时hidden_size32 / 64 / 128太小欠拟合太大过拟合数据少于 1 万条用 32 到 64learning_rate1e-3 / 5e-4 / 1e-4太大震荡太小收敛慢从 1e-3 起loss 震荡就减半num_layers1 / 2 / 3深了易过拟合2 层起步数据少用 1 层dropout0.1 / 0.2 / 0.3防过拟合过拟合明显就加到 0.3搜索策略上网格搜索太慢用随机搜索或 Optuna 贝叶斯优化20 到 30 组就能找到不错的组合。别一上来就搜先把默认参数跑通看基线再针对性调。4.3 对比基线持久化模型和 LSTM 到底差多少不上基线就不知道 LSTM 值不值。持久化模型最简单拿当前时刻功率当未来所有时刻的预测。# 持久化基线用回看窗口最后一个点的功率重复 horizon 次 persist np.repeat(X[:, -1, 0:1], y.shape[1], axis1) persist_real persist * (p_max - p_min) p_min persist_mape np.mean(np.abs((y_real[mask] - persist_real.flatten()[mask]) / y_real.flatten()[mask])) * 100 print(f持久化 MAPE {persist_mape:.2f}% vs LSTM MAPE {mape:.2f}%)逻辑说明X[:, -1, 0]取每个样本回看窗口最后一刻的功率np.repeat复制成 horizon 长度。如果 LSTM 的 MAPE 只比持久化低一两个点说明模型没学到东西得回去查特征和结构低五个点以上才算有价值。这个对比是判断项目成败的硬标准别跳过。5. 避坑与排查光伏 LSTM 训练里最常见的五个翻车现场5.1 损失不下降一直卡在高位现象训练几十轮 loss 几乎不动或者只在小数点后第三位晃。原因通常是归一化没做或做错或者学习率太小。解决确认所有输入特征都归一化到 0 到 1检查scaler.fit是不是只在训练集上做的学习率从 1e-3 试到 1e-2还不行就换优化器。5.2 预测曲线整体平移形状对但数值偏现象预测曲线跟真实曲线形状很像但整体高了一截或低了一截。原因是反归一化用错了极值或者训练集和测试集分布差异大。解决反归一化必须用训练集的data_min_和data_max_不能用测试集的如果测试集是不同季节的数据考虑重新训练或加季节特征。5.3 夜间预测出非零功率现象明明太阳落山了模型还预测出几百瓦。原因是夜间样本在训练集里占比大且功率为 0模型没学好这个边界或者归一化后 0 值被映射到非零。解决在特征里显式加「是否白天」的 0/1 标志或者后处理时把夜间时段强制置 0。5.4 验证集 loss 上升但训练 loss 下降现象典型的过拟合。原因是模型太复杂或数据太少。解决减层数、减隐藏单元、加 dropout、加 L2 正则或者做数据增强对训练样本加小幅噪声。数据少于 5000 条时LSTM 很容易过拟合考虑先用简单模型。5.5 换了数据集就报维度错误现象RuntimeError: input size mismatch。原因是新数据集的列数和顺序跟源码里写死的input_size4不一致。解决把特征列名和顺序固定下来input_size改成len(features)别硬编码。每次换数据先打印X.shape确认维度。6. 让预测再准一点的三个进阶技巧第一个技巧是加注意力机制。标准 LSTM 把整段序列压成一个隐藏状态信息有损。在 LSTM 输出上加一层注意力让模型自己决定回看窗口里哪些时刻更重要——比如突变前那几个点权重更高。实现上就是在out上过一个线性层算权重再加权求和代码量不大MAPE 通常能再降一到两个点。第二个技巧是误差修正。LSTM 对晴天拟合很好阴雨天误差大。可以训练一个副模型专门预测残差或者按天气类型分模型训练。我一般会先按辐照度把样本分成晴、多云、阴三类分别训 LSTM推理时按预报天气选模型阴天场景提升明显。第三个技巧是滚动预测。别一次性预测未来 24 小时而是预测 1 步、把预测值喂回输入、再预测下一步。这样能利用最新信息但误差会累积适合短期几步。实现时注意每次喂回的值要归一化别把真实值混进去造成泄漏。验证方法上别只看一个测试集。用滚动窗口做交叉验证前 70% 训练、接下来 15% 验证调参、最后 15% 测试再整体前移重跑几次看指标稳定性。指标波动大说明模型不稳别急着上线。我自己踩过最深的坑是拿测试集调参调到最后指标漂亮得不像话一上真实数据就崩。后来养成习惯测试集只在最后碰一次调参全在验证集上做。这个习惯比任何调参技巧都值钱。希望帮到你。本文还有配套的精品资源点击获取
返回列表