4. 特征工程:气象特征提取与选择
大家好,我是老张。干风电这行十几年了,今天咱们聊聊特征工程。说白了,就是把原始气象数据变成模型能听懂的语言。这一步做不好,后面再牛的算法也白搭。
核心观点:特征工程不是简单的数据搬运,而是对物理规律的数学表达。我见过太多项目,模型调参调了三个月,最后发现是特征没选对。
4.1 气象特征提取:从传感器到特征
先说说最基本的四个气象要素:气压、温度、湿度、风向。嗯,这里要注意,原始数据不能直接用。
4.1.1 气压特征
气压变化能反映天气系统的移动。我个人习惯提取三个维度:
- 瞬时气压:当前时刻的实测值,单位hPa
- 气压变化率:过去1小时的变化量,ΔP/Δt
- 相对气压:与同期历史均值的偏差
我的经验:有一次在海上风场,模型总是预报不准。后来发现是没考虑气压梯度力。加上相邻测站的气压差后,预测精度提升了12%。
4.1.2 温度特征
温度直接影响空气密度,进而影响风能。我建议这样处理:
- 温度绝对值:注意传感器安装高度,一般取轮毂高度
- 温度梯度:垂直方向温差,判断大气稳定度
- 日温差:最高温与最低温的差值
4.1.3 湿度特征
湿度对空气密度影响很大。湿空气比干空气轻,你想想看,同样的风速,湿度大的时候发电量会少一些。
| 湿度范围 | 对空气密度影响 | 建议处理方式 |
|---|---|---|
| <40% | 可忽略 | 直接使用 |
| 40%-80% | 中等 | 需校正 |
| >80% | 显著 | 必须考虑 |
4.1.4 风向特征
风向是环形变量,0°和360°其实是同一个方向。直接输入数值会出问题。
# 风向的正弦余弦编码
import numpy as np
def wind_direction_encoding(degrees):
"""将风向转换为正弦余弦特征"""
rad = np.deg2rad(degrees)
sin_component = np.sin(rad)
cos_component = np.cos(rad)
return sin_component, cos_component
# 示例:风向270°(西风)
sin_val, cos_val = wind_direction_encoding(270)
print(f"正弦分量: {sin_val:.3f}, 余弦分量: {cos_val:.3f}")
# 输出:正弦分量: -1.000, 余弦分量: 0.000
避坑指南:我曾经直接把风向度数喂给模型,结果模型死活学不会。后来才意识到,350°和10°明明只差20°,但数值上差了340°。用正弦余弦编码后,问题迎刃而解。
4.2 时序特征构建:让模型记住历史
风电预测本质上是时间序列问题。模型需要知道过去发生了什么,才能预测未来。
4.2.1 滑动窗口特征
我最常用的方法:取过去N个时间步的统计量。
def create_window_features(df, window_size=6):
"""构建滑动窗口特征"""
features = pd.DataFrame()
# 均值特征
features['wind_speed_mean_6h'] = df['wind_speed'].rolling(window_size).mean()
# 最大值特征
features['wind_speed_max_6h'] = df['wind_speed'].rolling(window_size).max()
# 趋势特征(线性拟合斜率)
def trend_slope(series):
x = np.arange(len(series))
if len(series) < 2:
return 0
slope, _ = np.polyfit(x, series, 1)
return slope
features['wind_speed_trend_6h'] = df['wind_speed'].rolling(window_size).apply(trend_slope)
return features
4.2.2 时间编码特征
风电有很强的日周期和年周期。我建议加入:
- 小时的正弦余弦:24小时周期
- 月份的正弦余弦:12个月周期
- 季节标志:0/1/2/3 四分类
4.2.3 滞后特征
为什么用滞后特征?因为大气运动有惯性。今天的风速和昨天的风速高度相关。
# 构建滞后特征
def create_lag_features(df, lags=[1, 3, 6, 12, 24]):
"""构建滞后特征"""
for lag in lags:
df[f'wind_speed_lag_{lag}h'] = df['wind_speed'].shift(lag)
return df
4.3 特征选择方法:去粗取精
特征不是越多越好。我见过有人搞了200多个特征,结果模型过拟合得一塌糊涂。
4.3.1 过滤法
先算相关性,把明显没用的特征剔除。
| 方法 | 原理 | 适用场景 |
|---|---|---|
| 皮尔逊相关系数 | 线性相关 | 连续变量 |
| 互信息 | 非线性相关 | 复杂关系 |
| 方差阈值 | 低方差剔除 | 常数特征 |
4.3.2 包裹法
用模型本身来选特征。我个人喜欢用递归特征消除(RFE)。
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestRegressor
# 递归特征消除
estimator = RandomForestRegressor(n_estimators=100)
selector = RFE(estimator, n_features_to_select=10, step=1)
selector.fit(X_train, y_train)
# 查看选中的特征
selected_features = X_train.columns[selector.support_]
print(f"选中的特征: {list(selected_features)}")
4.3.3 嵌入法
L1正则化(Lasso)自带特征选择功能。它会自动把不重要的特征系数压到0。
from sklearn.linear_model import Lasso
# Lasso特征选择
lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)
# 系数非零的特征
important_features = X_train.columns[lasso.coef_ != 0]
print(f"重要特征: {list(important_features)}")
我的建议:三种方法结合使用。先用过滤法粗筛,再用包裹法精挑,最后用嵌入法验证。我在西北某风场就是这么做的,特征从50个降到12个,模型精度反而提升了8%。
4.4 知识体系总览
下面这张图,是我梳理的特征工程整体流程。你仔细看看,每一步都有讲究。
这张图展示了特征工程的完整链路。从原始数据出发,经过提取、构建、选择三步,最终得到高质量的特征集。每一步都有对应的技术方法,咱们刚才都讲到了。
总结一下:特征工程是风电预测的基石。气压、温度、湿度、风向这四个基础特征要处理到位,时序特征要构建合理,特征选择要讲究方法。我在实际项目中,花在特征工程上的时间通常占整个项目的60%以上。这一步做扎实了,后面的建模就是水到渠成的事。