4、特征工程(下):温度敏感负荷建模(HDD/CDD)、虚拟变量编码、特征选择(相关性分析/树模型重要性)
好,咱们接着聊特征工程的下半场。
上一节我们把时间特征、滞后特征、滑动窗口这些基础活儿都捋了一遍。这一节,咱们要啃几块硬骨头——温度敏感负荷、虚拟变量,还有特征选择。这三样东西,说白了就是让你的模型更“懂”真实世界。
4.1 温度敏感负荷建模:HDD 与 CDD
先问个问题:你家夏天电费高,还是冬天高?
答案很明显。空调和暖气是负荷的两大“杀手”。但问题来了——怎么把温度这个因素,量化成模型能吃的特征?
直接扔个温度值进去?效果很差。因为人体对温度的感知是非线性的。25度和26度差别不大,但35度和36度,空调压缩机可能就多转半小时。
所以,电力系统里有两个经典指标:HDD(采暖度日数)和CDD(制冷度日数)。
核心公式:
- HDD = max(0, 基准温度 - 日平均温度) —— 天冷了,需要供暖
- CDD = max(0, 日平均温度 - 基准温度) —— 天热了,需要制冷
基准温度一般取18°C(有些地方用18.3°C或15°C,看当地习惯)。
我个人习惯用18°C。为什么?因为这是人体舒适区的下限。低于这个温度,大家就开始想开暖气了。
举个例子:
某天平均温度5°C,那么:
- HDD = 18 - 5 = 13
- CDD = 0(因为没超过18°C)
如果某天平均温度32°C,那么:
- CDD = 32 - 18 = 14
- HDD = 0
你看,这样就把温度对负荷的影响,变成了一个“累积效应”的指标。模型学起来轻松多了。
我的经验:
我在做某南方城市负荷预测时,发现直接用温度值,模型R²只有0.6。换成CDD后,直接跳到0.85。你想想看,这差距有多大。
另外,我建议把HDD和CDD同时作为特征输入。因为有些地区春秋季可能同时需要供暖和制冷(比如早晚温差大),模型自己会去学权重。
4.2 虚拟变量编码:把“类别”变成数字
模型不认识“星期一”、“星期二”这种文字。它只认数字。所以我们需要把类别特征编码成数值。
最常用的方法就是独热编码(One-Hot Encoding),也叫虚拟变量编码。
举个例子:
假设我们有一个“季节”特征,有4个取值:春、夏、秋、冬。
独热编码后,会变成4列:
| 原始季节 | is_春 | is_夏 | is_秋 | is_冬 |
|---|---|---|---|---|
| 春 | 1 | 0 | 0 | 0 |
| 夏 | 0 | 1 | 0 | 0 |
| 秋 | 0 | 0 | 1 | 0 |
| 冬 | 0 | 0 | 0 | 1 |
嗯,这里要注意:虚拟变量陷阱。如果你有k个类别,只需要创建k-1个虚拟变量。否则会造成多重共线性。比如上面季节的例子,我们只需要3列(比如去掉“冬”),因为“不是春、夏、秋”就自动等于“冬”。
我曾经踩过的坑:
有一次我把星期几(1-7)直接当成数值特征扔进模型。结果模型学出来:星期7的负荷比星期1高很多。但实际是因为周末和节假日的影响,而不是数字7比1大。后来改成独热编码,模型才正常。
所以记住:没有大小关系的类别,千万别用数值编码。
在Python里,用pandas的get_dummies()或者sklearn的OneHotEncoder都能轻松搞定。
import pandas as pd
# 假设df有'weekday'列
df_encoded = pd.get_dummies(df, columns=['weekday'], drop_first=True)
# drop_first=True 就是去掉第一列,避免虚拟变量陷阱
4.3 特征选择:别让模型“吃”太多垃圾
特征工程做完了,你可能搞出了几十甚至上百个特征。但问题来了——不是所有特征都有用。有些特征和负荷几乎没关系,有些特征之间高度相关(多重共线性),还有些特征纯粹是噪声。
特征选择,就是帮模型“减肥”。
4.3.1 相关性分析
最简单粗暴的方法:计算每个特征与目标变量(负荷)的皮尔逊相关系数。
相关系数范围在[-1, 1]之间:
- 接近1:强正相关(温度越高,负荷越大)
- 接近-1:强负相关(温度越低,负荷越大)
- 接近0:没啥关系
我一般会设定一个阈值,比如0.3。低于这个阈值的特征,直接扔掉。
我的习惯:
我还会看特征之间的相关性。如果两个特征相关系数超过0.8,我会只保留其中一个。比如“前1小时负荷”和“前2小时负荷”可能高度相关,留一个就够了。
不然模型会“左右为难”,学出来的权重也不稳定。
4.3.2 树模型特征重要性
相关性分析只能捕捉线性关系。但现实世界很多关系是非线性的。比如温度对负荷的影响,前面说了,是非线性的。
这时候,树模型(随机森林、XGBoost、LightGBM)的特征重要性就派上用场了。
树模型在训练过程中,会自动计算每个特征对预测的贡献度。贡献度越高,特征越重要。
具体做法:
- 先用所有特征训练一个随机森林或XGBoost模型
- 查看模型的
feature_importances_属性 - 把重要性低于某个阈值(比如0.01)的特征去掉
- 用剩下的特征重新训练模型
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X_train, y_train)
# 查看特征重要性
importances = model.feature_importances_
# 可以排序后看看哪些特征最重要
避坑指南:
我曾经犯过一个错误:直接用树模型的重要性做特征选择,然后发现模型效果反而下降了。为什么?
因为树模型的重要性会偏向数值型特征和高基数特征。比如你有一个“用户ID”特征,有1000个取值,树模型可能会觉得它很重要,但实际上它只是过拟合了。
所以我的建议是:相关性分析 + 树模型重要性,两者结合使用。先用相关性筛掉明显无关的特征,再用树模型重要性做精细筛选。
4.4 本章知识体系
为了让你更直观地理解这一章的内容,我画了一张图:
好了,这一节的内容就到这儿。温度敏感负荷、虚拟变量编码、特征选择,这三板斧砍下去,你的特征工程基本就到位了。下一节,咱们开始聊模型本身——从线性回归到XGBoost,一步步把预测精度提上去。
公众号:蓝海资料掘金营,微信deep3321