资讯动态

基于Python的光伏发电功率预测:LSTM、CNN_LSTM与XGBoost多模型对比实战

发布时间:2026/10/3 6:58:24 来源:尧图企业网站定制
做光伏发电预测这个方向差不多算是时间序列回归里最能直接看到业务价值的题目之一了。数据公开、目标明确、评估标准透明而且对电力调度有实打实的帮助——电站可以做功率申报电网可以更从容地安排传统机组启停如果你在企业里做新能源相关算法这几乎是必踩的一环。这篇文章要聊的就是用 Python 同时实现 LSTM、CNN_LSTM 和 XGBoost 三个回归模型在同一个数据集上做光伏功率预测并且把每个模型的训练思路、参数取舍和踩过的坑都讲清楚。不管你是刚接触时间序列预测的新手还是已经在做深度学习、想补一补树模型对比思路的工程师这篇文章都值得看完。整套代码不依赖复杂框架PyTorch 加 XGBoost 就能跑重点是让你明白三件事光伏预测的数据该怎么处理LSTM 和 CNN_LSTM 这类深度学习模型到底怎么调以及 XGBoost 这样的传统机器学习模型在序列预测里为什么依然能打。1. 项目思路与模型选型解析1.1 光伏发电预测到底在预测什么先把这个任务定义清楚。光伏发电预测本质上是一个多变量时间序列回归问题给定过去一段时间比如过去 24 小时的气象观测数据和发电功率数据预测未来若干个时刻的光伏电站输出功率。这里有几个物理常识先讲明白因为它们直接影响特征工程。光伏组件的输出功率主要由组件表面的太阳辐照度决定这跟昼夜周期、季节、天气状况强相关温度过高反而会导致组件效率下降这就是功率温度系数带来的负面效应湿度、风速、云量则影响散热和光的散射。所以原始数据里如果只有功率序列模型会非常难学通常要引入辐照度、温度、湿度、风速这些气象变量一起作为输入。预测的时间尺度也分几种习惯分钟级到小时级的超短期预测主要服务有功控制和调度日内计划一般看提前 15 分钟到 4 小时小时到天级别的短期预测用于日前发电计划申报再长就是中期预测更多是结合数值天气预报做周度预估。我们项目里为了展示通用的建模框架一般做小时级或者 15 分钟级的数据预测未来 1 个时间步到未来若干个时间步。1.2 为什么同时用 LSTM、CNN_LSTM 和 XGBoost很多初学者会问做一个预测任务选一个模型不就够了吗为什么非要搭三个。说实话在工业实践里单一模型在某个数据集上表现好不代表换个电站、换个季节、换个地域还能继续赢。做多模型对比不是为了炫技而是为了让你真正掌握每个模型的性格也方便你后续在自己的数据上快速选型。先简单拆一下三种模型的核心差异模型核心机制优势短板LSTM门控循环单元通过输入门、遗忘门、输出门控制信息流动擅长捕捉长时间依赖天生适合序列预测训练慢对数据量要求高调参敏感CNN_LSTM一维卷积提取局部特征并降维LSTM 处理时间依赖能自动学习局部时序模式参数效率更高结构更复杂实现时需要处理维度顺序XGBoost梯度提升树逐轮拟合残差用二阶导数优化对特征缩放不敏感训练快表格数据上限很高不会隐式建模时间顺序必须手工构造序列样本从我实际跑过的项目来看LSTM 和 CNN_LSTM 适合处理长序列、强周期、多变量相互影响的场景比如连续多天的功率曲线和气象特征XGBoost 更像是“特征工程的天花板”只要你把滑窗特征构造得足够好它在中小规模数据上经常能跑出和深度学习模型不相上下的分数而且训练只要几分钟排查问题也方便得多。1.3 XGBoost 做时间序列的思路跟深度学习有什么本质区别这里要特别强调一个认知XGBoost 本身并没有“记忆”能力它不像 LSTM 那样内部维护一条时间线。你用 XGBoost 做序列预测核心思路是把“序列”拆成“特征”。具体来说你想预测时刻 t 的功率那就把 t 之前 n 个时刻的功率、气象变量、时间特征全部拼成一个特征向量作为一条训练样本。整个测试集也按同样的方式滑窗构造。这样的好处是模型可以用任意表格特征——包括 hour_sin、滞后 24 小时功率、过去 6 小时平均辐照度等而且训练速度极快坏处是长距离依赖要么靠手工构造滞后特征实现要么靠深度模型自动学习这一点直接决定了你在模型对比时能看到哪些差异。2. 数据处理与建模准备80% 的坑都出在这里2.1 输入数据长什么样字段与样例先定义一份标准数据表后面所有代码都基于这个结构。假设数据是按小时采样的最小需求字段如下字段含义说明datetime时间戳最好解析为 pandas 的 DatetimeIndexirradiance水平面总辐照度单位 W/m²temperature环境温度单位 ℃humidity相对湿度单位 %wind_speed风速单位 m/spower光伏电站实际出力单位 kW 或归一化后的数值如占装机容量的比例如果你的数据来自公开数据集或者自己的电站采集系统可能还有气压、降雨量、云量等字段优先作为附加特征保留即可。千万别只留功率一列纯靠功率历史去预测功率在强天气转折日基本必崩。2.2 数据清洗与异常值处理光伏数据最大的特点是“有规律性异常”。夜间功率应该接近 0但辐照度传感器偶尔会在夜晚输出一个很小的正值这正常真正的问题是设备故障带来的离群点。我做这个项目时遇到的典型情况有三种功率出现负值可能是传感器电流方向接反直接置 0 或剔除都是可接受的辐照度在夜间出现明显大于 50 W/m² 的数值基本是传感器故障或积灰挡住后又突然恢复需要按前后时刻做中值替换数据缺测例如某个小时整段没有上传最简单的做法是线性插值但在长段缺测超过 6 小时时更稳妥的是前向填充不要用均值填掉整段否则会破坏时序特征。下面这段代码是我的去异常值套路简洁有效import pandas as pd import numpy as np df df.sort_index() # 保证时间有序 # 1. 功率为负置 0 df.loc[df[power] 0, power] 0 # 2. 夜间辐照度异常用前后 3 小时中位数替换 mask (df.index.hour.isin([20, 21, 22, 23, 0, 1, 2, 3, 4, 5])) (df[irradiance] 50) df.loc[mask, irradiance] np.nan df[irradiance] df[irradiance].fillna( df[irradiance].rolling(6, centerTrue, min_periods1).median() ) # 3. 线性插值补缺测 df df.interpolate(methodlinear, limit_directionboth)这里给新手提个醒时间序列的清洗操作一定要保留原始的 datetime 顺序千万不要在清洗阶段就.sample(frac1)打乱。后面划分训练集测试集时也要按照时间来划分。2.3 特征工程决定预测上限的关键一步特征工程做得越精细三个模型的对比就越有意义。我在这个项目里固定了下面几类特征第一是时间特征。把小时、月、星期做周期性编码用 sin 和 cos 成对变换避免 23 点和 0 点之间出现数值跳跃df[hour_sin] np.sin(2 * np.pi * df.index.hour / 24) df[hour_cos] np.cos(2 * np.pi * df.index.hour / 24) df[month_sin] np.sin(2 * np.pi * df.index.month / 12) df[month_cos] np.cos(2 * np.pi * df.index.month / 12) df[weekday] df.index.weekday第二是滞后特征。滞后特征的意义在于让 XGBoost 这类没有循环结构的模型也能“看见”过去同时也能加固深度模型的短期记忆# 构造过去 1, 2, 3, 6, 12, 24 小时的功率滞后特征 for lag in [1, 2, 3, 6, 12, 24]: df[fpower_lag_{lag}] df[power].shift(lag)第三是滚动统计特征比如过去 6 小时和 24 小时的平均功率、平均辐照度。这类特征能帮模型感知“当前处于持续晴好还是正在被云遮挡”的中间状态我自己测试时发现对阴天转换时刻的预测提升尤其明显。需要注意的是滑窗相关特征会造成数据前 24 行有 NaN。处理方案有两种一是直接丢弃这些样本二是用前向填充补上。对光伏这种有季节周期的数据我更倾向于丢弃因为前向填充会把“前一天同一时刻”的信息当作“过去 24 小时信息”有一定误导性。2.4 归一化与数据划分两个极易出错的细节LSTM 和 CNN_LSTM 这类基于梯度的神经网络对输入特征的尺度很敏感。如果 power 的量纲是 kW辐照度的量纲是 W/m²数值范围差了几十倍训练时梯度更新会被大数值特征主导模型很难收敛。所以在训练深度学习模型之前所有连续特征都要归一化。关键细节是只能用训练集的数据去 fit 归一化器然后分别 transform 训练集和测试集。如果用全部数据去 fit测试集的信息就被泄漏进训练过程最终验证指标会虚高工业上没法用。from sklearn.preprocessing import MinMaxScaler feature_cols [irradiance, temperature, humidity, wind_speed, hour_sin, hour_cos, month_sin, month_cos, power_lag_1, power_lag_2, power_lag_3, power_lag_6, power_lag_12, power_lag_24] target_col power scaler_x MinMaxScaler() scaler_y MinMaxScaler() # 按时间顺序 8:2 划分 split_idx int(len(df) * 0.8) train_df df.iloc[:split_idx].copy() test_df df.iloc[split_idx:].copy() # 训练集上 fit再 transform 两边 train_x scaler_x.fit_transform(train_df[feature_cols]) train_y scaler_y.fit_transform(train_df[[target_col]]) test_x scaler_x.transform(test_df[feature_cols]) test_y scaler_y.transform(test_df[[target_col]])数据划分也按时间顺序来进行测试集必须是从训练集之后连续取值的时间段不能随机抽样。这样才能真实反映模型“预测未来”的能力。3. LSTM、CNN_LSTM 和 XGBoost 的完整实现3.1 用 PyTorch 写一个可复用的 LSTM 回归模型LSTM 的核心价值在于它解决了普通 RNN 在长序列上的梯度消失问题。它通过输入门、遗忘门和输出门控制信息的写入、丢弃和读取这刚好匹配光伏功率序列的特点——既有强周期规律昼夜、季节又有突发扰动云层遮挡带来的功率骤降。模型定义部分我习惯把 LSTM 的最后一个时间步输出接一个全连接回归头。之所以取最后时间步是因为在预测未来一个时刻的任务里最后时间步的隐状态浓缩了整个序列的历史信息够用了如果任务是逐点预测整个未来窗口再考虑 Sequence-to-Sequence 结构。import torch import torch.nn as nn class LSTMPowerPredictor(nn.Module): def __init__(self, input_size, hidden_size64, num_layers2, output_size1, dropout0.2): super().__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout) self.reg nn.Sequential( nn.Linear(hidden_size, 32), nn.ReLU(), nn.Dropout(0.1), nn.Linear(32, output_size) ) def forward(self, x): out, _ self.lstm(x) out out[:, -1, :] # [batch, hidden_size] return self.reg(out)这里有个新手必坑点nn.LSTM默认batch_firstFalse输入维度是 [seq_len, batch, feature]直接用二维表格数据喂进去很容易报维度错误。我上面已经设置了batch_firstTrue输入直接就是 [batch, seq_len, feature]。训练时需要把原始样本 reshape 成三维张量。训练循环也很直白优化器用 Adam、损失函数用 MSELoss50100 个 epoch 基本能看出效果from torch.utils.data import DataLoader, TensorDataset def make_sequences(x, y, seq_len24): xs, ys [], [] for i in range(len(x) - seq_len): xs.append(x[i:i seq_len]) ys.append(y[i seq_len]) return np.array(xs), np.array(ys) # train_x 是归一化后的特征矩阵 seq_x, seq_y make_sequences(train_x, train_y, seq_len24) tensor_x torch.tensor(seq_x, dtypetorch.float32) tensor_y torch.tensor(seq_y, dtypetorch.float32) dataset TensorDataset(tensor_x, tensor_y) loader DataLoader(dataset, batch_size64, shuffleFalse) # 时间序列不要 shuffle model LSTMPowerPredictor(input_sizetrain_x.shape[1]) optimizer torch.optim.Adam(model.parameters(), lr1e-3) criterion nn.MSELoss() for epoch in range(80): model.train() total_loss 0.0 for xb, yb in loader: 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:03d}, Loss: {total_loss / len(loader):.5f})关于shuffleFalse我在下面专门讲一下。很多人都习惯在数据装载时打开 shuffleOCR 分类任务这样做没问题但时间序列预测一旦打乱顺序就相当于让模型看到了未来信息训练出来的指标骗人部署后立刻失效。3.2 CNN_LSTM 混合模型先用卷积网络学习局部时序模式CNN_LSTM 这个结构在光伏预测里非常好用。它先通过一维卷积核对序列做局部特征提取例如连续 3 到 6 个小时的辐照度变化趋势、功率的短时波动形态然后经过池化降维再把压缩后的特征序列交给 LSTM 学习更长周期的依赖。为什么要在 LSTM 前面加 CNN一个现实原因是原始的多变量时间序列维度较高、序列较长LSTM 直接学容易过拟合也慢。CNN 相当于先做一层“特征提炼”把相邻时间步的局部模式抽取出来LSTM 只需要在更抽象的特征层级上继续建模参数效率更高训练也更快。class CNNLSTMPredictor(nn.Module): def __init__(self, input_size, hidden_size64, num_layers1, output_size1, cnn_filters32, kernel_size3, dropout0.2): super().__init__() self.conv nn.Sequential( nn.Conv1d(input_size, cnn_filters, kernel_size, paddingkernel_size // 2), nn.ReLU(), nn.MaxPool1d(2) # 序列长度减半 ) self.lstm nn.LSTM(cnn_filters, hidden_size, num_layers, batch_firstTrue, dropoutdropout) self.reg nn.Linear(hidden_size, output_size) def forward(self, x): # x: [batch, seq_len, input_size] x x.permute(0, 2, 1) # Conv1d 需要 [batch, input_size, seq_len] x self.conv(x) # [batch, cnn_filters, seq_len//2] x x.permute(0, 2, 1) # 再转回 [batch, seq_len//2, cnn_filters] out, _ self.lstm(x) out out[:, -1, :] return self.reg(out)写这个模型时最容易绕晕的就是维度顺序。Conv1d 处理的是 [batch, channels, length]而 LSTM 处理的是 [batch, length, features]所以前向传播中必须做两次permute。我第一次实现时忘了第二次 permute结果维度不一致直接报错排查了半天。时序窗口长度建议选 24 或 48。如果数据是小时级24 就是完整一天模型能够感知昼夜节律。如果数据是 15 分钟级窗口可以取 96正好覆盖一天 96 个点。窗口太短学不到日周期窗口太长模型参数负担重收益却不明显。3.3 XGBoost 回归模型如何用树模型处理时间序列XGBoost 做回归任务不需要归一化这跟神经网络完全不同。它内部用决策树做特征分裂对特征单调变换不敏感。所以从数据准备开始XGBoost 的思路就跟 LSTM 不太一样它需要你把一段时间窗口摊平成一条样本。import xgboost as xgb def build_supervised(df, feature_cols, target_col, lookback24): X, y [], [] for i in range(lookback, len(df)): # 取当前时刻前 lookback 行摊平成行向量 window df[feature_cols].iloc[i - lookback:i].values.flatten() X.append(window) y.append(df[target_col].iloc[i]) return np.array(X), np.array(y)这里特征矩阵会非常大。如果 lookback24、特征列有 14 个那么每个样本的特征维度就是 24×14336。树模型对高维特征处理得还可以但要注意别把所有滞后特征再重复加进去否则特征共线性会让模型变得更难解释。模型训练非常快核心参数可以先用一组稳健配置model_xgb xgb.XGBRegressor( n_estimators500, max_depth5, learning_rate0.05, subsample0.8, colsample_bytree0.8, reg_lambda1.0, random_state42, eval_metricrmse ) model_xgb.fit(X_train, y_train, verboseFalse)这里几个参数的取舍逻辑值得说。n_estimators是树的数量太小欠拟合太大容易过拟合配合learning_rate一起看学习率越低需要的树越多max_depth控制每棵树的复杂度光伏功率预测一般 4 到 6 就够太深会导致训练集拟合得很漂亮、测试集拉胯subsample和colsample_bytree是随机采样比例设置 0.8 左右能增加模型鲁棒性防止过拟合。还有一个细节XGBoost 官方文档里明确说明它会在训练阶段自动处理缺失值会学习缺失值的默认分裂方向。你在用前面构造的滑窗数据时如果还有少量 NaN 没处理干净XGBoost 能扛得住但 LSTM 不行它会直接给你报 NaN loss所以两边对缺失值的容忍度完全不同。3.4 统一的多模型评估框架三个模型跑完之后不能各算各的指标必须放到同一套评估代码里用同一个测试集来对比。这样才能保证公平。from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error def evaluate_model(y_true, y_pred, scaler_yNone): if scaler_y is not None: y_true scaler_y.inverse_transform(y_true.reshape(-1, 1)).ravel() y_pred scaler_y.inverse_transform(y_pred.reshape(-1, 1)).ravel() r2 r2_score(y_true, y_pred) mae mean_absolute_error(y_true, y_pred) rmse np.sqrt(mean_squared_error(y_true, y_pred)) return {R2: round(r2, 4), MAE: round(mae, 3), RMSE: round(rmse, 3)}需要提醒一个很重要的细节LSTM 返回的预测值是经过scaler_y归一化的评估时如果直接跟真实功率比较算出来的指标毫无意义。上面代码里专门加了inverse_transform这一步把预测值还原到原始功率量纲再计算误差。评估完之后一定要画一张“测试集真实值 vs 三个模型预测值”的对比图。只看指标容易忽略模型在局部时段的真实表现比如峰值时刻是不是普遍偏低、阴天转换时刻是不是整体滞后这些用折线图一眼就能看出来。我以前做复盘时经常发现某个模型虽然 RMSE 略好但它在晴天早晚突变段的曲线特别抖这种模型调度侧基本是不敢直接用的。4. 模型对比与指标解读4.1 回归指标怎么选R2、MAE 和 RMSE我对这三类模型做统一评估时最常看的指标是 R2、MAE 和 RMSE。它们侧重点完全不同指标含义适用场景R2模型对总方差的解释程度越接近 1 越好衡量整体拟合效果直观MAE预测误差的绝对平均值关注平均误差大小受异常点影响小RMSE误差平方后开方对大误差惩罚更重关注严重偏差电网调度会比较在意在光伏预测场景里RMSE 要重点看。因为功率一旦预测偏低可能导致备用容量不足大误差的风险远大于平均小误差的风险。MAE 则帮你理解模型的“平均水平”。R2 容易受数据方差影响晴天多的测试集 R2 会很好看阴雨连绵的月份就会掉得厉害单独看一个 R2 容易误判。4.2 我的调参经验快速拿到可靠结果的参数组合我直接给一套在这个项目里实测效果不错的参数组合可以当起点用模型关键参数备注LSTMseq_len24, hidden_size64, num_layers2, lr1e-3, batch_size64, epochs80加上 Dropout0.2 防过拟合CNN_LSTMseq_len24, cnn_filters32, kernel_size3, hidden_size64, lr1e-3, batch_size64, epochs80池化后序列长度减半XGBoostn_estimators500, max_depth5, learning_rate0.05, subsample0.8, colsample_bytree0.8训练速度很快建议同时跑多组参数比较LSTM 类模型最让我头疼的问题不是模型结构而是“已经收敛了指标却不理想”。这时候第一步不是堆参数而是回去看特征工程——滞后特征和滚动统计特征有没有加时间特征有没有做周期编码。深度学习模型的表达能力是够的但如果没有合适的特征作为输入再深也白搭。XGBoost 调整方向则不同。它的训练快所以我一般直接用小网格搜索加早停来选参数固定一个比较大的n_estimators设置early_stopping_rounds50同时观察验证集的 RMSE。XGBoost 的eval_set参数可以直接指定验证集非常方便。4.3 结果分析不同天气条件下的差异有多大跑完这个项目你会发现一个非常典型的现象晴天和稳定天气下三个模型的表现都很好R2 经常能到 0.97 以上而在阴天、多云或雷阵雨天气预测误差会显著放大。原因也很简单光伏功率曲线在晴天基本是一条平滑的钟形曲线模型很容易学到“上午走高、下午走低”的日周期规律但云层移动会带来瞬时遮挡导致功率在几分钟内骤降再爬升这种高频变化对任何模型都是挑战。所以如果你要对外汇报结果我强烈建议按天气类型分组统计指标而不是只给一个总体的 R2。这样既能解释误差来源也能让你更清楚模型的适用边界。实测下来LSTM 在面对天气转换时的记忆能力稍好一点CNN_LSTM 在局部波动形态识别上更稳XGBoost 则在有充分滞后特征的条件下阴天时段也能给出很合理的预测结果。5. 常见问题与排错指南5.1 归一化泄漏测试集指标虚高这是最隐蔽也最伤的一个问题。症状是训练过程一切正常测试集 R2 高得离谱但模型一部署到新数据上立刻拉胯。原因多半是你用scaler.fit_transform(all_x)对整个数据集做了归一化测试集的均值和最值也参与了训练阶段的信息统计。解决方式就是我一直强调的先按时间顺序划分再在训练集上fit测试集只调用transform。我建议把这个逻辑封装成一个函数以后任何项目都复用省得每次手写的时候漏一步。5.2 预测结果是一条直线或全是 0这种情况常见于 LSTM 类模型。排查优先级为先看目标变量是否被归一化到了特别窄的区间比如功率本来就是 0 到 1 之间MinMaxScaler 之后区间过窄模型很容易输出分布中心附近的值再看学习率是否过大导致梯度震荡最终参数崩掉最后看序列构造时是不是用dropna把有效样本全部删除了导致训练集剩下大量接近 0 的夜间样本模型学成了“输出均值”。一个很实用的检查方法把测试集预测值画出来如果曲线像一条在平均值附近轻微抖动的直线基本可以断定模型退化成了均值预测器。这时候不仅要调参还要重新审视训练集的样本分布——光伏数据里夜间样本占了接近一半如果不对这些样本做特殊处理模型很容易被夜间 0 值主导。5.3 XGBoost 做序列预测时为什么需要显式构造样本很多人第一次用 XGBoost 做时间序列直接把原始时序数据丢进fit结果模型完全不会预测这是缺失“滑窗样本构造”这一步。树模型本质上学习的是“当前时刻特征到目标值”的映射它看不到“过去到现在的顺序”。你必须像 3.3 节的build_supervised一样把过去 lookback 个时刻的特征展平成一条样本模型才能感知到时间上下文。这里还有一个额外的好处一旦你构造了这样的表格特征就可以更自由地做特征工程比如把前一天的功率曲线峰值、低谷时刻、上升斜率全部显式算出来放到表格里让 XGBoost 用这种灵活性是深度模型做不到的。5.4 模型对比的公平性问题做对比实验时三个模型要使用同一个测试集、同一段预测目标特征源也尽量保持一致。LSTM 和 CNN_LSTM 用的是三维序列XGBoost 用的是一维展开特征看起来好像不公平但实际业务中每个模型都有自己最合适的输入形式让它们各自发挥最强能力再做对比才是公平的。同时要固定随机种子。PyTorch 和 XGBoost 都要设置random_state或torch.manual_seed否则每次跑出来的结果都不同你根本没法判断模型的差异是真实差距还是随机波动。5.5 部署阶段的一个精度提醒如果你后续打算把这个预测模型部署到边缘设备比如用 INT8 定点量化加速推理一定要在量化后用一批训练集样本重新评估精度。我见过不少模型量化后 R2 从 0.96 掉到 0.90 甚至更低的情况通常原因是激活值分布和归一化参数在量化校准阶段失配。解决办法是量化校准集尽量从训练集均匀抽样覆盖各类天气时段而不是随便选一段。这类问题虽然不发生在训练阶段但属于模型上线前的“最后一公里”。我的建议是深度学习模型在部署前先确认推理框架对 LSTM/卷积层的算子支持程度如果量化掉点严重优先保精度用 FP16或者退回 XGBoost 版本作为轻量级兜底方案。最后分享一个我在评估这类时间序列模型时养成的习惯永远在测试集的最后一段时间单独画一张预测值和真实值的对比图。如果模型在训练后期指标很好但最后这段持续性波动的区间表现明显拉胯那基本可以怀疑模型学到的是训练集分布而不是真正的时间依赖规律。这个习惯帮我过滤了至少三个看起来不错、实际上不能用的候选模型。如果你准备复现这个项目建议先把单一模型完整跑通再加入第二个模型最后做三模型对比。过程中如果遇到 PyTorch 版本或者 XGBoost 版本差异导致的告警优先锁定环境把 numpy、pandas、torch、xgboost 的版本固定好再继续往下调。光伏预测不是一个特别难的任务但只要你把数据、特征、评估三个环节做扎实三个模型都会给你稳定且可信的结果。

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

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

免费获取报价 →
↑