电力系统有一个残酷的特点:电很难大规模存储,发电和用电必须实时平衡。新能源占比越来越高之后,风电光伏的波动性让这个平衡变得极难维持——靠人工经验和传统统计方法已经顶不住了。这正是 AI 进入电网的核心动因。本文聚焦两个最落地的方向:负荷预测和智能调度,聊聊模型选型、数据工程和生产部署的实际问题。
负荷预测:电网的"天气预报"
负荷预测按时间尺度分四类:超短期(分钟到小时,用于实时调度)、短期(日前,用于发电计划)、中期(周到月,用于检修安排)、长期(年到十年,用于规划)。商业化最成熟的是短期预测,直接决定电力现货市场的报价策略。
影响负荷的因素非常杂:历史负荷、温度湿度、节假日、工作日类型、产业开工率,甚至重大赛事直播都会在负荷曲线上砸出一个坑。所以特征工程往往比模型本身更花时间。几个经验性的要点:
- 温度的影响是非线性的,夏季空调负荷存在"拐点温度",直接用原始温度做特征不如加入制冷度日(CDD)和采暖度日(HDD)这类变换量。
- 节假日必须单独建模,春节的负荷曲线和任何工作日、周末都不像。
- 极端天气样本稀少但影响巨大,需要做样本加权或专门的极端事件分支模型。
模型选型:从 LightGBM 到时序大模型
实际项目里的选型对比大致如下:
| 模型 | 精度(MAPE) | 训练成本 | 可解释性 | 适用场景 | |------|------------|---------|---------|---------| | ARIMA/指数平滑 | 5%~10% | 极低 | 强 | 基线、小台区 | | LightGBM/XGBoost | 3%~5% | 低 | 较强 | 短期预测主力 | | LSTM/GRU | 3%~5% | 中 | 弱 | 中长期依赖场景 | | Transformer(Informer/PatchTST) | 2%~4% | 高 | 弱 | 多区域联合预测 | | 时序基础模型(TimesFM/TimeGPT) | 视微调而定 | 推理成本高 | 弱 | 冷启动、零样本 |
一个反直觉的事实:在单区域短期负荷预测上,调好的 LightGBM 经常打平甚至超过深度模型,而且训练只要几分钟。深度模型的优势在多变量联合预测(几百个台区一起预测、共享表示)和超长输入窗口。2024 年以来时序基础模型进展很快,但生产环境大面积铺开还受限于推理成本和稳定性验证,目前更多用于新投运台区的冷启动——那里根本没有历史数据,零样本预测是刚需。
一个可跑的短期负荷预测示例
下面用 LightGBM 演示特征工程 + 训练的核心逻辑:
import pandas as pd import lightgbm as lgb from sklearn.metrics import mean_absolute_percentage_error def build_features(df: pd.DataFrame) -> pd.DataFrame: """df 含列: timestamp, load, temperature""" df = df.copy() df["hour"] = df["timestamp"].dt.hour df["dayofweek"] = df["timestamp"].dt.dayofweek df["is_weekend"] = (df["dayofweek"] >= 5).astype(int) # 温度非线性:制冷/采暖度日 df["cdd"] = (df["temperature"] - 26).clip(lower=0) df["hdd"] = (18 - df["temperature"]).clip(lower=0) # 滞后特征:同时刻昨日/前周负荷 df = df.set_index("timestamp").sort_index() df["load_lag_1d"] = df["load"].shift(96) # 15min级数据, 96点/天 df["load_lag_1w"] = df["load"].shift(96 * 7) # 滑动窗口统计 df["load_roll_mean_4h"] = df["load"].rolling(16).mean() return df.dropna().reset_index() FEATURES = ["hour", "dayofweek", "is_weekend", "cdd", "hdd", "temperature", "load_lag_1d", "load_lag_1w", "load_roll_mean_4h"] data = build_features(pd.read_csv("load_data.csv", parse_dates=["timestamp"])) train, test = data.iloc[:-672], data.iloc[-672:] # 最后一整周做测试 model = lgb.LGBMRegressor( n_estimators=800, learning_rate=0.03, num_leaves=63, subsample=0.8, colsample_bytree=0.8 ) model.fit(train[FEATURES], train["load"]) pred = model.predict(test[FEATURES]) print(f"MAPE: {mean_absolute_percentage_error(test['load'], pred):.2%}")这套骨架在省级电网数据集上通常能做到 3%