电力负荷预测入门:用 LightGBM 做层次化多步时序预测

背景

GEFCom2012(Global Energy Forecasting Competition 2012)是 IEEE 能源预测工作组组织的竞赛。本文基于其层次负荷预测赛道,目标是预测美国某电力公司 20 个区域 + 系统总负荷(共 21 条时间序列)的每小时用电量。

数据时间跨度为 2004-2008 年(4.5 年训练数据),其中故意挖去 8 个非连续星期作为回测验证,最后留 1 个预测周作为最终评估。评分使用加权均方根误差(WRMSE),预测周系统负荷权重最高(160),回测周区域负荷权重最低(1)。

总体流程

数据加载 → 特征工程 → 构建多步训练数据 → LightGBM 训练 → 直接多步预测 → WRMSE 评估

1. 数据预处理

(代码仓库:https://github.com/pcl-sa/GEFCom2012
原始 CSV 是"宽表"格式 — 每天一行,24 个 h1~h24 列代表每小时负荷。第一步转为更适合建模的"长表":每行 = 一个 zone 的一个小时。

from src.data_preprocessing import LoadProcessor

processor = LoadProcessor()
df = processor.load_raw('data/.../Load_history.csv')
# (792000, 7)  →  zone_id, datetime, year, month, day, hour, load

这里有个坑:原始 CSV 的负荷值带千分位逗号("16,853"),LoadProcessor.load_raw() 内部自动处理了。

2. 特征工程

电力负荷有极强的周期性,特征工程是模型效果的关键。

2.1 时间特征

小时、星期、月份的周期编码(sin/cos),加上是否周末、季节:

df = processor.add_time_features(df)
# 新增: hour_sin/cos, dow_sin/cos, month_sin/cos, is_weekend, season, dow

2.2 滞后特征

负荷预测最核心的特征——昨天同一时刻、上周同一时刻的负荷:

df = processor.add_lag_features(df, lags=[1, 2, 3, 24, 48, 168])
# lag_1: 前一小时; lag_24: 昨天同时; lag_168: 上周同时

2.3 滚动统计

过去一段时间负荷的均值、标准差,反映近期趋势和波动:

df = processor.add_rolling_features(df, windows=[24, 48, 168])
# rolling_mean_24, rolling_std_24, rolling_mean_48, ...

所有滚动特征先 shift(1)rolling,杜绝未来信息泄露。

2.4 外生变量

气温和节假日是负荷的重要驱动因素。气温来自 11 个气象站,取均值合并:

temp_df = processor.load_temperature()
df = processor.merge_temperature(df, temp_df, strategy='average')

df = processor.merge_holidays(df)

最终特征 24 列:

horizon, hour_sin, hour_cos, dow_sin, dow_cos, month_sin, month_cos,
is_weekend, season, dow,
lag_1, lag_2, lag_3, lag_24, lag_48, lag_168,
rolling_mean_24, rolling_std_24, rolling_mean_48, rolling_std_48,
rolling_mean_168, rolling_std_168,
temp_avg, is_holiday

3. 多步预测策略

最大的挑战:每个缺口需要预测连续 168 小时

3.1 递归预测(第一版,失败)

最初尝试"预测→写回历史→再预测"的递归策略。在第 1 小时有 ~600kW 误差,这个误差被当成 lag_1 用于预测第 2 小时,导致误差越来越大——到第 168 小时误差已膨胀到数万 kW。整体 WRMSE 高达 833,062,远差于基线。

3.2 直接多步预测(第二版)

改用 horizon 特征:告诉模型"预测未来第几小时"。所有 lag/rolling 特征只基于缺口前的实际历史,不写入预测值。168 次预测完全独立,无误差传递。

# 训练数据构建
train_df = build_multistep_train_data(df, sample_step=24, max_horizon=168)
# 5,285,280 条训练样本 (20 zones × 1650天 × 每24h采样 × 168 horizon)

# 预测
preds = direct_multistep_predict(
    model, history_df, gap_start, gap_end, temp_df, holiday_df, feature_cols
)

核心改动在 build_multistep_train_data:对每个参考点,一次性生成 horizon=1…168 的 168 行数据,其中基础特征(lag/rolling)都来自参考点的实际历史,只有时间特征和气温随 horizon 变化。

4. 模型训练

LightGBM 回归器,关键超参:

参数 说明
learning_rate 0.03 适中学习率
num_leaves 127 较大叶子数,捕捉复杂交互
subsample 0.8 行采样防过拟合
colsample_bytree 0.6 列采样
early_stopping 100 轮 验证集 RMSE 不再下降时停止

验证集按时间切分:2008-01-01 之前训练,之后验证。

model, importance = train_model(train_df, val_cutoff='2008-01-01')

5. 评估体系

GEFCom2012 使用 WRMSE,权重分布:

任务 层级 权重
预测周 系统负荷 160
预测周 区域负荷 8
回测周 系统负荷 20
回测周 区域负荷 1

这意味着预测周系统负荷的准确性是回测周区域负荷的 160 倍重要

评估时需计算 zone_id=21(系统总负荷 = 20 个区域之和),并确保 pred 与 solution 按 (zone_id, year, month, day) 严格对齐:

system_preds = all_preds.groupby('datetime')['load'].sum().reset_index()
system_preds['zone_id'] = 21
all_preds = pd.concat([all_preds, system_preds])

# 宽表转换 + weight 合并 + 交集对齐
pred_wide = to_wide_format(all_preds)
solu_wide = to_wide_format(solu_raw)
overall_score = wrmse(solu_aligned, pred_aligned)

6. 结果分析

指标
训练样本 5,285,280
验证 RMSE 12,585.65
整体 WRMSE 693,857.27
特征重要性 Top 3 rolling_std_168, temp_avg, rolling_mean_168

特征重要性解读

rolling_std_168    20,151  ← 过去一周负荷波动是最大信号
temp_avg           19,172  ← 气温对负荷影响极大
rolling_mean_168   18,612  ← 过去一周平均负荷水平
lag_168            17,201  ← 上周同时刻负荷
rolling_std_48     14,517
rolling_std_24     13,819

长周期特征(168h)远超短周期(1h/24h),说明周模式是最强的预测信号。

7. 工程总结

模块组织

src/
├── data_preprocessing/     # LoadProcessor(数据加载、特征工程)
├── eval_sys/               # WRMSE 评估
└── plan1_lightgbm/         # LightGBM 方案
    ├── features.py         # 特征列定义
    ├── train.py            # 多步训练数据构建 + 模型训练
    └── predict.py          # 直接多步预测

关键设计决策

  • 预处理与建模分离 → LoadProcessor 可被任何方案复用
  • 特征列集中管理 → 训练/预测/评估使用同一套列名,避免不一致
  • 时间切分验证 → 不做随机 split,避免用未来信息验证过去
  • 系统负荷通过区域求和得到 → 天然满足层次一致性

从递归到直接多步的教训:时序预测中,递归策略的误差传播是致命的。即使单步 RMSE 仅 ~3800,168 步递归后也足以让整个预测崩溃。horizon 特征 + 独立预测是 LightGBM 做多步时序的正确范式。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐