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)的特征重要性就派上用场了。

树模型在训练过程中,会自动计算每个特征对预测的贡献度。贡献度越高,特征越重要。

具体做法:

  1. 先用所有特征训练一个随机森林或XGBoost模型
  2. 查看模型的feature_importances_属性
  3. 把重要性低于某个阈值(比如0.01)的特征去掉
  4. 用剩下的特征重新训练模型
from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor()
model.fit(X_train, y_train)

# 查看特征重要性
importances = model.feature_importances_
# 可以排序后看看哪些特征最重要

避坑指南:

我曾经犯过一个错误:直接用树模型的重要性做特征选择,然后发现模型效果反而下降了。为什么?

因为树模型的重要性会偏向数值型特征高基数特征。比如你有一个“用户ID”特征,有1000个取值,树模型可能会觉得它很重要,但实际上它只是过拟合了。

所以我的建议是:相关性分析 + 树模型重要性,两者结合使用。先用相关性筛掉明显无关的特征,再用树模型重要性做精细筛选。

4.4 本章知识体系

为了让你更直观地理解这一章的内容,我画了一张图:

特征工程(下)知识体系 温度敏感负荷建模 HDD = max(0, T_base - T_avg) CDD = max(0, T_avg - T_base) 基准温度:18°C 虚拟变量编码 独热编码 (One-Hot) 避免虚拟变量陷阱 k个类别 → k-1个变量 特征选择 相关性分析(线性) 树模型重要性(非线性) 两者结合使用 核心逻辑 原始数据 → 温度特征(HDD/CDD) + 类别特征(虚拟变量) → 特征选择(相关性+树模型) → 高质量特征集 → 输入模型训练

好了,这一节的内容就到这儿。温度敏感负荷、虚拟变量编码、特征选择,这三板斧砍下去,你的特征工程基本就到位了。下一节,咱们开始聊模型本身——从线性回归到XGBoost,一步步把预测精度提上去。


公众号:蓝海资料掘金营,微信deep3321