ARTICLE DETAIL

资讯详情

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

基于LSTM的光伏功率预测毕业设计实战:从数据预处理到多步预测

基于LSTM的光伏功率预测毕业设计实战:从数据预处理到多步预测 简介这是一份面向计算机相关专业毕业设计学生与项目实战学习者的LSTM短期光伏预测完整项目包选题聚焦新能源发电功率预测这一热门方向难度适中适合作为毕设选题或深度学习入门练手。资源共28个文件压缩包约3.38MB包含1个Python主程序与1个Jupyter Notebook用于模型搭建与训练1份光伏小时级数据集供直接读取另有22张训练过程与预测结果图、README说明文档及依赖清单便于快速复现与理解实验流程。目前已有125人学习下载。项目源码经本地编译调试可直接运行读者能借此掌握LSTM时序建模、数据预处理、模型评估与结果可视化的完整链路并参考图表与笔记梳理实验思路为毕设答辩或后续研究提供可复用的代码框架与排错参考。1. 光伏功率预测的毕业设计一份能跑通的 LSTM 项目长什么样做光伏功率预测的毕业设计最怕的不是模型不会搭而是数据拿到手发现时间戳对不上、发电功率和气象特征量纲差了几个数量级、训练完 loss 曲线看着挺美但预测曲线整体平移。这套基于 LSTM 的短期光伏预测项目核心就是解决「从原始 CSV 到可复现预测曲线」这条链路。资源包里包含pvdaq_2012_2014_hourly.csv数据集、pv_power_forecasting.py脚本、pv_power_forecasting.ipynb交互式笔记本、requirements.txt依赖清单以及 20 多张训练过程与基线对比图。适合正在做计算机相关毕业设计、需要一份结构完整且本地编译通过的 LSTM 时间序列预测实战项目的同学也适合想拿真实光伏数据练手 LSTM 回归的从业者。2. 数据与模型选型为什么是 LSTM 而不是 XGBoost2.1 光伏功率预测的任务本质与 LSTM 的适配点光伏功率预测按时间尺度分超短期分钟到小时、短期1-3 天、中长期周月。这份项目用的是小时级数据属于短期预测范畴。输入是历史发电功率加气象变量输出是未来若干小时的功率值。这本质上是一个多变量时间序列回归问题。LSTM 在这里的优势不是「比树模型强」而是它天然处理序列依赖。光伏功率受太阳高度角、云层移动、温度累积效应影响当前时刻的功率和前几个小时的功率、辐照度存在滞后相关。XGBoost 做这类任务需要手工构造 lag 特征比如把 t-1、t-2、t-3 时刻的功率拼成一行特征工程做完再喂给模型。LSTM 的门控结构直接把时序信息编码进隐状态省掉了显式 lag 构造这一步。代价是训练更慢、调参更玄学、对数据量和归一化更敏感。项目里pv_power_forecasting.py和.ipynb两个版本并存脚本版适合直接跑通看结果笔记本版适合逐单元格调试理解每一步。常见做法是先用笔记本把数据探索和模型定义跑一遍确认 shape 和 loss 正常再把逻辑固化到脚本里做批量实验。2.2 数据集字段与预处理的关键参数pvdaq_2012_2014_hourly.csv是 PVDAQ 公开数据集的小时级聚合版本覆盖 2012 到 2014 年。典型字段包括时间戳、交流功率、直流功率、环境温度、模块温度、辐照度等。不同站点的列名可能有差异加载后第一件事是确认时间列能被pd.to_datetime正确解析以及功率列是否存在负值夜间逆变器待机功耗会导致微小负值。预处理的核心步骤和参数如下步骤操作关键参数说明时间解析pd.to_datetimeformat按实际格式解析失败会变成 NaT后续 dropna 会丢大量行缺失值处理线性插值或前向填充limit3连续缺失超过 3 小时建议置 NaN 再丢弃夜间过滤功率小于阈值置零阈值取额定功率 1%避免夜间噪声干扰训练归一化MinMaxScalerfeature_range(0,1)必须用训练集 fit再 transform 验证集滑动窗口构造监督学习样本look_back24用过去 24 小时预测未来 1 小时look_back24是一个需要根据数据粒度调整的参数。小时级数据用 24 意味着模型能看到过去一整天的功率变化模式对短期预测来说信息量足够。如果改成 48 或 72模型输入维度增加训练时间上升但未必带来明显收益反而容易过拟合。我一般会从 12、24、48 三档做对比实验看验证集 RMSE 的变化曲线再定。2.3 环境搭建与依赖安装的实操步骤拿到资源包后第一步不是急着跑模型而是把环境对齐。requirements.txt里通常包含 numpy、pandas、matplotlib、scikit-learn、tensorflow 或 pytorch。先确认本机 Python 版本建议 3.8 到 3.10 之间太新的版本可能遇到 TensorFlow 轮子不兼容。# 创建独立虚拟环境避免污染全局包 python -m venv pv_env # 激活环境Windows pv_env\Scripts\activate # 激活环境macOS/Linux source pv_env/bin/activate # 安装依赖建议加国内镜像加速 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后用pip list核对关键包版本。如果requirements.txt里写的是tensorflow2.x.x而本机装的是 2.y.y先别急着降级跑一遍脚本看是否报 API 不兼容错误。常见的不兼容点是model.fit的validation_split参数行为和EarlyStopping的patience默认值变化这些在训练日志里能直接看出来。提示如果用的是 Apple Silicon 芯片TensorFlow 需要装tensorflow-macos和tensorflow-metal直接pip install tensorflow会装成 CPU 版本训练速度慢很多。3. 从 CSV 到预测曲线脚本逐段拆解与参数调优3.1 数据加载与滑动窗口构造的代码逻辑pv_power_forecasting.py的主流程分四段加载数据、构造窗口样本、定义 LSTM 模型、训练与评估。先看数据加载和窗口构造部分。import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler # 加载数据parse_dates 直接解析时间列 df pd.read_csv(data/pvdaq_2012_2014_hourly.csv, parse_dates[timestamp]) df df.sort_values(timestamp).reset_index(dropTrue) # 选取建模用列功率列和气象列 feature_cols [ac_power, ambient_temp, module_temp, irradiance] data df[feature_cols].values # 归一化fit 只在训练段做 scaler MinMaxScaler(feature_range(0, 1)) train_size int(len(data) * 0.8) scaler.fit(data[:train_size]) data_scaled scaler.transform(data) # 滑动窗口构造监督学习样本 def create_dataset(data, look_back24): X, y [], [] for i in range(len(data) - look_back): X.append(data[i:i look_back, :]) # 过去 look_back 小时的所有特征 y.append(data[i look_back, 0]) # 预测下一小时的 ac_power return np.array(X), np.array(y) look_back 24 X, y create_dataset(data_scaled, look_back) # 按时间顺序切分不能 shuffle X_train, X_test X[:train_size - look_back], X[train_size - look_back:] y_train, y_test y[:train_size - look_back], y[train_size - look_back:]这段代码有三个容易翻车的点。第一scaler.fit只能用训练段数据如果用全量数据 fit验证集的归一化参数里混入了未来信息评估结果会偏乐观。第二create_dataset里y取的是data[i look_back, 0]索引 0 对应ac_power列如果特征列顺序调整了这里要同步改。第三切分时train_size - look_back这个偏移量不能省否则训练集和测试集会有look_back长度的重叠造成数据泄漏。3.2 LSTM 网络结构与训练超参数的设置模型定义部分通常用 Keras Sequential API结构不复杂但每个参数都影响收敛。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.callbacks import EarlyStopping model Sequential([ # 第一层 LSTMreturn_sequencesTrue 传给下一层 LSTM LSTM(64, return_sequencesTrue, input_shape(look_back, len(feature_cols))), Dropout(0.2), # 第二层 LSTM只输出最后时间步 LSTM(32, return_sequencesFalse), Dropout(0.2), # 全连接输出单值预测 Dense(1) ]) model.compile(optimizeradam, lossmse, metrics[mae]) # 早停验证集 loss 连续 10 轮不降就停 early_stop EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue) history model.fit( X_train, y_train, epochs100, batch_size32, validation_split0.1, callbacks[early_stop], verbose1 )LSTM(64)和LSTM(32)的单元数是经验值。单元数太少欠拟合预测曲线会过于平滑抓不住功率爬坡和跌落单元数太多训练慢且容易过拟合验证集 loss 震荡。Dropout(0.2)放在两层 LSTM 之间作用是随机丢弃部分隐状态输出降低对训练集噪声的敏感度。batch_size32对小时级数据来说比较稳数据量小的时候可以降到 16梯度更新更频繁。EarlyStopping的patience10意味着验证集 loss 连续 10 轮不下降就停止训练并回滚到最佳权重。这个参数设太小会提前终止设太大浪费训练时间。我一般会先跑一次不早停的版本看 loss 曲线大概多少轮趋于平稳再把 patience 设成平稳轮数的 1.5 倍左右。3.3 预测结果反归一化与评估指标计算训练完拿到预测值后必须做反归一化才能和真实功率对比。这里有个细节scaler是对所有特征列一起 fit 的反归一化时不能直接scaler.inverse_transform(pred)因为 pred 只有一列维度对不上。# 预测 y_pred model.predict(X_test) # 反归一化构造和原始特征同宽度的矩阵只填功率列 def inverse_power(scaled_values, scaler, power_col_index0, n_features4): dummy np.zeros((len(scaled_values), n_features)) dummy[:, power_col_index] scaled_values.flatten() return scaler.inverse_transform(dummy)[:, power_col_index] y_test_inv inverse_power(y_test, scaler) y_pred_inv inverse_power(y_pred, scaler) # 评估指标 from sklearn.metrics import mean_squared_error, mean_absolute_error rmse np.sqrt(mean_squared_error(y_test_inv, y_pred_inv)) mae mean_absolute_error(y_test_inv, y_pred_inv) print(fRMSE: {rmse:.4f}, MAE: {mae:.4f})inverse_power函数里n_features4要和feature_cols的长度一致power_col_index0对应ac_power在特征列中的位置。如果换了数据集或调整了特征列顺序这两个参数必须同步改否则反归一化出来的数值会完全错位。评估指标除了 RMSE 和 MAE还可以算 MAPE但光伏功率在夜间接近零MAPE 会爆炸所以项目里一般以 RMSE 为主。资源包里的figure_baseline.png和model_baseline.png是基线模型通常是 persistence 模型即用当前时刻功率直接作为下一时刻预测的对比图。LSTM 的 RMSE 应该明显低于基线如果两者接近说明模型没学到有效时序模式需要检查归一化、窗口长度或模型容量。4. 训练过程中的避坑与排查记录4.1 损失函数不下降或震荡剧烈现象训练开始后 loss 在前几轮下降之后长期在某个值附近震荡验证集 loss 甚至上升。原因最常见的是学习率偏大或 batch_size 太小导致梯度噪声大。另一个可能是输入特征没有归一化不同量纲的特征让梯度更新方向混乱。解决先把optimizeradam换成optimizerAdam(learning_rate0.001)显式指定学习率如果还震荡就降到 0.0005。同时确认MinMaxScaler是否对所有特征列都做了缩放特别是辐照度这种数值范围可能到 1000 以上的列。如果数据里存在极端离群值先做 3σ 截断再归一化。4.2 预测曲线整体偏高或偏低现象预测曲线形状和真实曲线相似但整体向上或向下平移了一个固定量。原因反归一化时power_col_index或n_features设错导致功率列的缩放参数用成了其他列的。另一个可能是训练集和测试集切分时没有按时间顺序shuffle 之后模型学到了未来信息评估时表现异常。解决打印scaler.data_min_和scaler.data_max_确认功率列的最小最大值和原始数据一致。检查切分代码里有没有train_test_split的shuffleTrue时间序列必须按时间顺序切。如果用的是 DataFrame 的sample或shuffle全部去掉。4.3 夜间功率预测出现负值现象模型在夜间时段输出了负的功率预测值。原因归一化后的功率范围是 [0,1]但模型输出层是Dense(1)没有激活函数线性输出可以小于 0。反归一化后负值被放大成负功率。解决在输出层加activationsigmoid把输出限制在 [0,1]或者在反归一化后做np.clip(y_pred_inv, 0, None)截断。更根本的做法是在预处理阶段把夜间功率置零让模型学到夜间输出趋近于零的模式。4.4 训练集 loss 很低但测试集 RMSE 很高现象训练集 MSE 降到 0.001 以下测试集 RMSE 却比基线还差。原因过拟合。模型记住了训练集的噪声模式泛化能力差。数据量小、模型容量大、训练轮数过多都会导致。解决增加 Dropout 比例到 0.3 或 0.4减少 LSTM 单元数加 L2 正则化kernel_regularizerl2(0.001)。如果数据量确实太少可以用数据增强比如对训练集加轻微高斯噪声再训练。早停的patience也可以调小到 5更早终止训练。4.5 环境依赖版本冲突导致脚本无法运行现象pip install -r requirements.txt报错或者脚本 import 时报ModuleNotFoundError或AttributeError。原因requirements.txt里的版本约束和本机 Python 版本不匹配或者 TensorFlow 和 numpy 版本不兼容。解决先看报错信息里是哪个包的问题单独装那个包的兼容版本。常见组合是 TensorFlow 2.10 配 numpy 1.23TensorFlow 2.15 配 numpy 1.26。如果requirements.txt没有锁死版本可以尝试pip install tensorflow2.10.0 numpy1.23.5这种明确指定。实在搞不定就新建一个 Python 3.9 的虚拟环境重来3.9 对大多数深度学习包的兼容性最好。5. 进阶技巧用多步预测和误差分析提升项目完整度5.1 从单步预测扩展到多步预测项目默认是单步预测即用过去 24 小时预测下一小时。毕业设计答辩时老师常问「能不能预测未来一天」这时候需要改成多步预测。有两种做法直接多输出和滚动预测。直接多输出是把Dense(1)改成Dense(24)一次输出未来 24 小时。标签构造时y取data[ilook_back:ilook_back24, 0]。这种做法的优点是推理快缺点是各步之间独立预测可能不满足时序连续性。滚动预测是训练一个单步模型预测出 t1 后把预测值拼回输入序列再预测 t2循环 24 次。优点是模型结构不变缺点是误差会累积预测步数越多偏差越大。# 滚动预测示例 def rolling_forecast(model, last_sequence, steps24): preds [] current_seq last_sequence.copy() # shape: (1, look_back, n_features) for _ in range(steps): next_val model.predict(current_seq, verbose0) # (1, 1) preds.append(next_val[0, 0]) # 把预测值拼到序列末尾去掉最早的时间步 new_step current_seq[0, -1, :].copy() new_step[0] next_val[0, 0] # 更新功率列 current_seq np.append(current_seq[:, 1:, :], [[new_step]], axis1) return np.array(preds)滚动预测里new_step[0] next_val[0, 0]只更新了功率列其他气象列用的是最后一个时间步的值。如果要做更严谨的多步预测气象列也需要有预测值或使用天气预报数据否则模型输入的气象信息在滚动过程中是停滞的。5.2 误差时段分布分析与答辩加分点答辩时老师大概率会问「你的模型在什么时段预测最准、什么时段最差」。提前做误差时段分布分析能直接回答这个问题。把测试集的预测误差按小时分组算每个小时的平均绝对误差画柱状图。通常会发现清晨和傍晚误差最大因为这两个时段功率爬坡快云层遮挡导致功率波动剧烈LSTM 对突变模式的捕捉能力有限。正午时段功率平稳误差最小。资源包里的history_*.png和figure_*.png已经包含了训练 loss 曲线和预测对比图但误差时段分布图需要自己补。补上这张图答辩时讲「模型在 6-8 点和 17-19 点误差偏高原因是功率爬坡阶段时序依赖复杂后续可以引入天气预报的云量数据改善」比只讲 RMSE 数值有说服力得多。5.3 模型保存与推理脚本的工程化收尾训练完的模型用model.save(lstm_pv.h5)保存推理时用load_model加载。注意保存时要把look_back、feature_cols、scaler的参数一起存下来否则推理时输入维度对不上。import joblib # 保存模型和预处理器 model.save(lstm_pv_model.h5) joblib.dump(scaler, scaler.pkl) joblib.dump({look_back: look_back, feature_cols: feature_cols}, config.pkl) # 推理时加载 from tensorflow.keras.models import load_model model load_model(lstm_pv_model.h5) scaler joblib.load(scaler.pkl) config joblib.load(config.pkl)我一般会在项目根目录下建一个outputs/文件夹把模型文件、scaler、config、评估指标 JSON 全部丢进去README 里写清楚每个文件的用途。这样别人拿到资源包跑完训练脚本后能直接找到推理所需的全部文件不用翻代码找参数。从那以后我每次交付时序预测项目都会强制走一遍「训练脚本 → 保存产物 → 独立推理脚本验证」的流程确保模型不是只能在训练 notebook 里跑通。希望帮到你。本文还有配套的精品资源点击获取
返回列表