资讯动态

风电功率预测实战:基于lightGBM的完整机器学习项目解析

发布时间:2026/10/1 12:29:52 来源:尧图企业网站定制
简介基于机器学习LightGBM模型实现的风电预测项目源码包面向毕业设计、课程设计及期末大作业场景适合计算机相关专业学生、高校教师和程序员快速上手与实际落地。项目集成完整训练与预测流程既可用于学术研究中的功率预测对比实验也便于二次开发拓展特征工程或调参优化。压缩包共30个文件约25.42MB包含22个csv格式的多风电场历史数据集、4个joblib序列化模型文件、2个Python源码文件训练与预测脚本、1个md格式说明文档及1张png结构示意图目录划分清晰数据集覆盖多个风电场站点模型文件可直接加载复现预测效果。目前已有161人学习下载。配套的项目文档说明提供从环境准备到运行的指引并给出常见问题排查思路源代码逻辑简洁支持独立调试或整合到更大系统中是风电功率预测方向入门与实践的实用参考。1. 风电功率预测项目lightGBM 源码包能直接落地到毕设吗风电功率预测是新能源方向的高频毕设选题也是典型的表格回归任务。这套基于机器学习 lightGBM 模型的 Python 源码包把「20 个风机 CSV 数据 4 个已训练 joblib 模型 train.py 训练脚本 predict.py 预测脚本 项目文档说明」打包成了一条完整链路。拿到手不是零碎代码而是能跑通「原始数据 → 特征工程 → 训练 → 保存模型 → 加载推理 → 输出预测功率」全流程的工程闭环。对做课程设计、期末大作业的同学来说它的价值在于能直接演示、能答辩、能二次开发对想从 sklearn 迁移到 lightGBM 的从业者这是一个现成的代码模板。资源里的四个 joblib 模型对应分组训练策略加上风电数据本身强自相关的特性整体方案在精度和速度之间取得了不错的平衡。下面我把数据构成、训练逻辑、推理链路和踩坑点逐层拆开讲清楚。2. 数据集构成与赛题理解20 个风机 CSV 和四个 joblib 模型的关系2.1 风机 CSV 里的特征列风电竞赛数据集的典型结构解压后根目录下能看到 01.csv 到 20.csv一共 20 个文件对应 20 个风机的历史运行记录。这类风电功率预测竞赛数据集的特征列有固定的套路我按常见字段整理了一张对照表字段名含义类型预测中的作用timestamp时间戳datetime提取小时、月份、星期等时间特征wind_speed轮毂高度风速float功率曲线的最主要驱动变量wind_direction风向角度float经 sin/cos 变换后作为周期特征temperature环境温度float影响空气密度进而影响功率humidity湿度float辅助特征部分时段影响显著pressure气压float空气密度的另一个代理变量power实际功率float训练标签预测目标读数据时要注意不同 CSV 里的列名大小写可能不统一比如 wind_speed 和 WindSpeed 同时出现。第一次跑 train.py 前先用df.columns打印一遍确认物理含义和列名的对应关系。另外原始 CSV 里可能混入功率为 0 但风速大于切入风速的异常行这类记录一般是风机停机或限电训练前建议做一次清洗。时间粒度方面这类竞赛数据通常是 15 分钟一条记录一天 96 个点单台风机一年数据量约 3.5 万行。20 台风机合起来大约 70 万行lightGBM 处理这个量级完全没有压力这也是选树模型而不是深度学习网络的一个重要原因——数据量还没到必须用 LSTM 的程度用梯度提升树反而训练更快、调参更可控。2.2 infile 目录和待预测数据训练集与测试集的分工资源里有个 infile 文件夹里面放着 00011.csv、0002.csv、19.csv 这几个文件。它们和根目录的 01-20.csv 角色不同不带功率标签的气象数据就是待预测的连续时段。赛题逻辑是这样的先用 01-20.csv 里包含历史功率标签的数据训练模型学习气象特征到功率输出的映射关系然后读取 infile 中只有气象列、没有功率列的 CSV用训练好的模型推算未来一段时间的功率曲线。实际处理时我一般会单独写一个load_data()函数用两个分支分别读训练集和预测集确保特征列顺序完全一致。一个容易被忽略的细节是infile 里的 CSV 时间范围可能不是连续的中间有缺口加载后先按时间排序并检查是否出现重复时间戳否则做滞后特征时错位一行结果会整体偏移。2.3 为什么打包了四个 joblib 模型分组训练的常见策略模型目录下是 LightGBMmodel_0.joblib 到 LightGBMmodel_3.joblib共四个。第一次看到会疑惑为什么不训一个大模型这其实是风电预测项目里非常实用的分组训练策略。常见的分组方式有两种。第一种是按风机编号分组20 个风机的地理微环境不同有的处于上风向有的尾流影响大功率曲线形态有差异把特征相似的风机聚成 4 组分别建模组内模式更一致。第二种是按时间窗口拆分把全天按时段切段比如凌晨、白天、傍晚、深夜因为不同时段的风速分布和功率响应特性差异明显。我倾向于先做相关性分析再分组对每个风机的历史功率序列算彼此间的皮尔逊相关系数相关系数高的放一组。四个模型保存时用 0-3 命名正好对应分组索引。分组训练的价值在于降低单模型拟合多风机时互相干扰带来的偏差代价是要维护多个模型文件推理时遍历加载。从模型文件大小看每个 joblib 都有几 MB 到十几 MB说明每棵树的深度和数量是可观的实际训练成果不是占位用的空壳。3. lightGBM 选型与核心参数风电预测为什么梯度提升是首选3.1 lightGBM 在风电场景的四个优势先从原理层面说清楚为什么是 lightGBM 而不是线性回归、SVR 或神经网络。风电功率预测本质上是学习一条功率曲线风速低于切入风速时功率为 0风速在额定区间内功率近似立方增长超过额定风速后功率被截断在额定值。这是一条明显的分段非线性曲线线性回归天然搞不定这种形态。lightGBM 这类梯度提升树模型的核心机制是不断拟合残差每一轮新增一棵决策树来修正上一轮的预测误差。这个机制让它可以自动逼近分段常数函数对功率曲线中的平台期和拐点都能刻画。另外特征之间可能存在的交互效应例如风速与风向的联合影响树模型也能通过分裂逻辑捕获不需要手动做交互项工程。第二个优势是它对待特征尺度不敏感。风速是 0-30 m/s功率是 0-1500 kW温度可能是 -10 到 40 度量纲差异极大。线性模型必须做标准化神经网络也很吃归一化但树模型按特征值排序后分裂阈值只取决于相对次序所以特征缩放不是必要步骤。第三个优势是训练效率。lightGBM 用基于直方图的算法把连续特征离散化成固定数量的箱大幅减少了寻找最优分裂点的计算量。配合单边梯度采样70 万行数据、十几列特征在一台普通笔记本上几十秒就能完成一轮完整训练这比 XGBoost 和深度网络都快得多。最后一个原因是工程生态。lightgbm 的 Python 包有原生的 sklearn API——LGBMRegressor在 train.py 里以类似RandomForestRegressor的方式直接调用学习成本低保存模型用 joblib 也无缝衔接。3.2 核心参数配置一份能直接抄的 lightGBM 参数表我基于这份资源的场景整理了一份参数基线它适合大多数中等规模的风电预测任务可以直接抄进自己的 train.pyimport lightgbm as lgb params { objective: regression, # 回归任务 metric: rmse, # 评估指标RMSE 对功率误差敏感 learning_rate: 0.05, # 学习率小一点防止过拟合 num_leaves: 63, # 单棵树叶子数控制模型复杂度 max_depth: 6, # 限制深度避免单棵树过长 feature_fraction: 0.8, # 每棵树随机采样 80% 特征 bagging_fraction: 0.8, # 每轮迭代采样 80% 样本 bagging_freq: 1, # 每轮都做 bagging min_data_in_leaf: 20, # 叶子节点最小样本数 n_estimators: 800, # 最大迭代轮数配合 early stopping verbose: -1, # 不打印大量训练日志 } model lgb.LGBMRegressor(**params)逐个说明关键参数learning_rate设为 0.05数值偏小意味着每棵树贡献有限需要更多轮数但泛化性更好不建议直接拉到 0.1 以上num_leaves是 lightGBM 里最重要的复杂度控制参数风电特征数量不大63 是合理起点如果验证集 RMSE 持续下降但训练集已经接近 0说明叶子数太多需要调小feature_fraction和bagging_fraction是两组随机化防过拟合手段前者按特征采样后者按样本采样两个同时开效果叠加但训练会略慢。min_data_in_leaf是防止树过度细分的小技巧风电数据在临界风速附近有大量噪声点叶子样本太少时学到的全是噪声。这里要特别提醒一个常见误区n_estimators不是越大越好配合early_stopping_rounds使用才是正确姿势。把训练集再切出验证集训练过程中监控验证集 RMSE连续 50 轮不下降就自动截断。4. train.py 训练流程拆解时间特征、滞后特征与模型保存全链路4.1 数据读取与特征工程风电预测的核心竞争力train.py 的第一步是读取 20 个风机的 CSV 并拼接成一个大 DataFrame。读取时统一用pd.read_csv并把 timestamp 列解析为 datetime 类型这一步在预测脚本里同样要做保证训练和推理的时间解析逻辑一致。特征工程是这份资源里最有技术含量的部分。我按风电预测的普遍做法把特征分为三类时间特征、气象特征、历史统计特征。import pandas as pd import numpy as np def build_features(df): # 时间特征风电功率昼夜差异明显小时特征优先级最高 df[timestamp] pd.to_datetime(df[timestamp]) df[hour] df[timestamp].dt.hour df[month] df[timestamp].dt.month df[weekday] df[timestamp].dt.weekday # 风向的周期编码角度 0/360 是相邻值直接喂数值会让树模型误以为差距巨大 df[wind_dir_sin] np.sin(np.deg2rad(df[wind_direction])) df[wind_dir_cos] np.cos(np.deg2rad(df[wind_direction])) # 滞后特征功率序列自相关性强前一时刻功率是下一时刻的强预测因子 df[power_lag1] df[power].shift(1) df[power_lag2] df[power].shift(2) df[power_lag3] df[power].shift(3) # 滑动统计最近 3 个点的均值平滑瞬时波动 df[power_rolling_mean_3] df[power].rolling(window3).mean() # 风力趋势当前风速与前 15 分钟风速的差值 df[wind_speed_diff] df[wind_speed].diff() # 删除构造滞后特征产生的 NaN 行 df df.dropna().reset_index(dropTrue) return df这段代码有几个设计逻辑需要说明。风向是 0-360 度的圆周变量10 度和 350 度在物理上只差 20 度但直接按数值算距离就是 340 度。把角度拆成 sin 和 cos 两个特征后树模型可以学到风向的周期性。滞后特征是风电预测中提升效果最明显的特征——风具有惯性前一刻的功率对下一刻有极强预测力。用 power_lag1 到 lag3 和滑动均值共同刻画时间序列的惯性本质上是让树模型学习到一阶自回归结构。shift()之后前三行必然产生 NaN这里直接丢弃。4.2 时间序列交叉验证不能用随机 KFold 的硬道理很多初学者在这里翻车用train_test_split随机切分数据集训练集和验证集混在一起切导致验证集里出现了未来时间的数据。风向变化是连续的相邻时间点的功率高度相关随机切分会产生严重的数据泄漏验证集 RMSE 虚低实际上线效果崩掉。正确做法是时间序列交叉验证始终保持「训练集时间全部早于验证集时间」from sklearn.model_selection import TimeSeriesSplit import numpy as np # 按风机分组后拼接好的特征矩阵 X 和标签 y X features.drop(columns[power, timestamp]) y features[power] tscv TimeSeriesSplit(n_splits5) best_model None best_score float(inf) for train_idx, val_idx in tscv.split(X): X_train, X_val X.iloc[train_idx], X.iloc[val_idx] y_train, y_val y.iloc[train_idx], y.iloc[val_idx] model lgb.LGBMRegressor(**params) model.fit( X_train, y_train, eval_set[(X_val, y_val)], eval_metricrmse, callbacks[lgb.early_stopping(stopping_rounds50, verboseTrue)] ) val_pred model.predict(X_val) score np.sqrt(((val_pred - y_val) ** 2).mean()) if score best_score: best_score score best_model modelTimeSeriesSplit会按时间先后顺序切出递增的训练窗口每一折的训练集都是验证集之前的全部历史数据。这模拟了真实预测场景只能用过去预测未来。early_stopping是这里的关键防过拟合机制——如果验证集 RMSE 超过 50 轮没有改善训练提前终止选历史最优迭代轮数的模型。训练完取best_model用于后续预测而不是随便拿最后一轮的模型。4.3 模型保存joblib 的保存与加载规范训练完成后模型用 joblib 序列化保存到 model 目录文件名带分组索引import joblib import os os.makedirs(model, exist_okTrue) for group_id, model in enumerate(grouped_models): joblib.dump(model, fmodel/LightGBMmodel_{group_id}.joblib)我一般用 joblib 而不是 pickle 保存模型文件原因是 joblib 对 numpy 数组的序列化做了专门的优化大模型保存和读取更快。另一个值得记录的习惯把训练时使用的特征列名也存成一个 json 文件后面预测脚本读取时按相同顺序加载这是防止特征错位最可靠的手段。保存模型后还要做一步验证重新用joblib.load读取一遍对训练集末尾一段数据做预测确认 R2 得分在正常范围。这个步骤能提前拦截序列化损坏或版本兼容问题比等到 predict.py 跑挂了再排查效率高得多。5. predict.py 推理链路与避坑特征对齐、路径乱码和版本兼容5.1 推理主流程加载模型并复现特征构造predict.py 做的事情是训练流程的逆过程读取 infile 下的预测数据构造和训练时完全相同的特征加载四个模型逐一预测最后把结果写成 CSV。核心代码如下import joblib import pandas as pd import numpy as np def load_models(model_dirmodel): models [] for i in range(4): model_path f{model_dir}/LightGBMmodel_{i}.joblib models.append(joblib.load(model_path)) return models def predict_forecast(input_csv, models): df pd.read_csv(input_csv, encodingutf-8) # 训练和预测必须走同一个特征工程函数保证列完全一致 df build_features(df) feature_cols [c for c in df.columns if c not in [timestamp, power]] X df[feature_cols].fillna(methodffill) # 多模型平均每个模型对同一批样本预测后取均值平滑单模型误差 preds np.mean([model.predict(X) for model in models], axis0) df[predicted_power] preds return df[[timestamp, predicted_power]]推理流程中最重要的原则是「训练和预测用同一个特征函数」。我在项目里会把build_features单独放进一个feature_utils.py训练脚本和预测脚本都从这里导入而不是各自复制一份。复制粘贴的坏处是两边稍有不一致比如训练时加了power_lag3而预测脚本只构造了power_lag2模型加载后特征数量不匹配直接报错。多模型预测时取平均是普遍做法。四个模型分别从不同的风机子集学到不同的功率曲线形态取平均能抵消部分过拟合震荡。注意这里传的是特征矩阵的引用而不是合并后的 DataFrame避免把无意义的 timestamp 列带进去。5.2 避坑一路径含中文导致模型加载失败现象按文档运行 predict.py报错信息是FileNotFoundError: [Errno 2] No such file or directory: model/LightGBMmodel_0.joblib但资源里明明有这个文件。原因项目文件路径中包含中文字符时不同操作系统对路径编码的处理方式不一致Windows 下 Python 在部分环境会因默认编码问题无法正确解析中文路径。另外一些压缩包解压工具生成中文目录名后lightgbm 的 C 底层在读取文件时也会因编码不一致而失败。解决把整个项目重命名为纯英文字母比如wind_power_lgbm并放到不含空格的目录下。解压后不要在中文路径下直接运行例如别放在「桌面\新建文件夹(2)」这种位置。5.3 避坑二训练和预测特征数量不一致现象predict.py 执行到model.predict(X)时抛出异常提示Number of features of the predictor (15) doesnt match number of features in data (13)。原因训练时构造了 15 列特征预测脚本只构造出 13 列。最常见的差异来源是预测数据里没有power列而特征构造函数还在执行rolling均值后dropna导致预测集在滞后特征轮数上不同行数和列数都对不上。解决把特征工程函数统一训练和预测走完全相同的代码路径。我通常会在训练结束后保存一份feature_columns.json预测时先对比特征列顺序一旦发现差异立刻打印出缺失的列名不让你在黑匣子里猜。5.4 避坑三滞后特征泄漏导致验证集虚高现象模型在验证集上 RMSE 只有训练集的 1/10效果好得反常但提交到正式测试集上成绩却很普通甚至不如简单线性回归。原因训练时用了前一时刻的真实功率作为特征。如果验证集和训练集切分不当比如没有按时间顺序切滞后一时刻的功率会携带测试期附近的信息。另一种泄漏是预测阶段把真实功率喂给了模型——但待预测的时段本身没有功率标签推理时特征里少了这一列模型表现自然崩掉。解决训练验证切分必须严格使用TimeSeriesSplit而且预测推理时要确认特征矩阵中没有真实功率标签列。构造特征时给所有滞后特征加统一前缀例如lag_便于推理时检查并剔除。5.5 避坑四joblib 版本兼容问题现象在别人机器上训练好的 joblib 模型换到自己的环境加载时报UnicodeDecodeError或AttributeError: LGBMRegressor object has no attribute ...。原因joblib 序列化格式在不同版本间有过调整lightgbm 模型内部包含对 sklearn API 的依赖样机环境 sklearn 版本差异较大时属性查找失败。解决项目文档里应该写明主要依赖版本。没有写明的话用pip freeze | grep -E lightgbm|scikit-learn|joblib查看当前环境版本然后安装对应版本。最稳妥的做法是为项目单独创建 conda 环境训练和预测都在同一环境内执行避免跨环境传递模型文件。6. 进阶滚动预测与多模型融合把 RMSE 再压一截的验证技巧基线模型能跑通之后想提升预测精度我推荐两个性价比最高的方向滚动预测和多模型融合。滚动预测解决的是「预测时段超过滞后特征窗口」的问题。如果用 lag1-lag3 特征训练模型那么预测只能覆盖有真实历史功率的前三个时间点。要预测整段未来 24 小时需要把模型输出的功率回填为滞后特征逐步前向推理。它的逻辑是预测 13:15 用 13:00 的真实值预测 13:30 时没有真实值就改用 13:15 的预测值回填。这套「预测即历史」的循环在代码里用几个循环就能实现def rolling_predict(models, df, forecast_steps): 滚动预测后续点的滞后特征用前序预测值回填 # 先把存在真实功率的滞后特征保留 df df.copy() for step in range(forecast_steps): feature_cols [c for c in df.columns if c not in [timestamp, power]] X df[feature_cols].fillna(methodffill) # 多模型融合四个模型预测值按权重 0.25 平均 pred np.mean([m.predict(X) for m in models], axis0) new_row df.iloc[-1].copy() new_row[power] pred[-1] df pd.concat([df, new_row.to_frame().T], ignore_indexTrue) # 下一轮循环时 lag1 会取到上一轮的预测值 return df验证是进阶里最重要的一环。我一般会把预测结果和实际功率画在同一张时序图里重点看曲线是否在爬坡段和额定功率平台段出现偏移。RMSE 是整体误差看不出局部形态偏差所以辅以分风速段的误差分析把预测误差按风速区间分组统计能定位模型在哪个区间系统性低估。另一个验证技巧是计算归一化均方根误差。由于功率范围从 0 到 1500 kW直接用 RMSE 比较不同风机间的效果没有意义除以装机容量后才有可比性。同一份资源的 20 个风机模型不同风机间的误差差异可能接近一倍这不一定是模型问题而是风机自身功率曲线的陡峭程度不同。我在这类项目上栽过的跟头是训练时图方便把所有风机数据混在一起只训一个模型验证集 RMSE 看起来也稳定但实际查看单台风机的预测曲线时发现部分风机存在明显偏差。后来我强制自己把分组训练、多模型融合、按风机评估这三步写入代码流程从那以后每次拿到风电数据都按这套标准走一遍先按相关性分组训练预测时多模型平均最后按风机维度分列评估。这套流程把项目从「能跑通」推进到「能答辩、能解释」的程度希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑