3. 特征工程基础:风速、风向、温度、气压等气象特征分析,时间特征提取(小时、季节)

各位同学,咱们今天聊聊特征工程。说白了,就是怎么把原始的气象数据,变成模型能听懂、爱吃的好东西。

我刚开始做风功率预测那会儿,犯过一个傻。直接把风速、风向扔进模型,结果预测结果惨不忍睹。后来才明白,原始数据 ≠ 有效特征。你想想看,模型又不是人,它哪知道「北风」和「东北风」有什么区别?它只知道数字。

3.1 风速特征:不只是「多少米每秒」

风速是预测的核心。但直接拿原始风速序列去建模,效果往往一般。为什么?因为风速的波动太大了,模型很难抓住规律。

我个人习惯,会从三个维度去处理风速:

  • 原始风速:保留,但会做平滑处理(比如滑动平均)。
  • 风速变化率:计算前后时刻的差值。这能反映风速的「脾气」——是平稳还是暴躁。
  • 风速的平方/立方:因为风功率和风速的三次方成正比。这个物理关系,模型不一定能自己学出来,我们帮它一把。

核心经验:我在项目中遇到过,单纯用原始风速,模型在低风速段和高风速段表现差异巨大。加入风速的平方项后,高风速段的预测精度提升了约15%。

代码实现很简单,比如用pandas:

import pandas as pd
import numpy as np

# 假设 df 包含 'wind_speed' 列
df['ws_smooth'] = df['wind_speed'].rolling(window=3, min_periods=1).mean()
df['ws_diff'] = df['wind_speed'].diff()
df['ws_square'] = df['wind_speed'] ** 2
df['ws_cube'] = df['wind_speed'] ** 3

3.2 风向特征:别让「0°」和「360°」打架

风向是个环形变量。0°和360°其实是一个方向,但模型会认为它们差360个单位。这会导致严重的误差。

我曾经吃过这个亏。有一次模型在冬季预测偏差特别大,排查了半天,发现是风向处理出了问题——北风(0°)和北风(360°)被当成了两个完全不同的特征。

正确的做法是:将风向分解为正弦和余弦分量

# 风向角度转弧度
wind_rad = np.deg2rad(df['wind_direction'])
df['wd_sin'] = np.sin(wind_rad)
df['wd_cos'] = np.cos(wind_rad)

这样处理后,0°和360°的正弦值都是0,余弦值都是1。模型就不会再「打架」了。

小技巧:如果你觉得正弦余弦还不够,可以试试风向的「扇形编码」。比如把360°分成16个扇区,每个扇区用一个0/1变量表示。这在某些树模型里效果不错。

3.3 温度与气压:别小看这两个「配角」

温度和气压,看起来不如风速那么直接。但它们对空气密度有影响,而空气密度直接影响风功率。

公式很简单:
P = 0.5 * ρ * A * v³

其中ρ(空气密度)和温度、气压密切相关。温度越高,空气密度越低;气压越高,密度越高。

我建议构造两个衍生特征:

  • 空气密度估算值:用温度和气压近似计算。
  • 温度变化率:反映大气稳定度。温度骤降往往意味着冷锋过境,风速会突变。
# 空气密度近似计算(单位:kg/m³)
# 标准海平面条件下,ρ ≈ 1.225
# 修正公式:ρ = 1.225 * (P/1013.25) * (288.15 / (T + 273.15))
df['air_density'] = 1.225 * (df['pressure'] / 1013.25) * (288.15 / (df['temperature'] + 273.15))

注意:温度和气压的测量高度要和风速保持一致。如果风速是轮毂高度(比如80米),温度和气压却是地面数据,那算出来的空气密度会有偏差。我见过有人直接用地面温度去算,结果模型在夏季偏差很大。

3.4 时间特征:模型也得知道「现在几点」

风是有「作息规律」的。白天和晚上不一样,夏天和冬天也不一样。模型如果不知道时间,它就会把白天的大风规律套用到晚上,结果可想而知。

时间特征提取,我一般分两步:

  1. 周期性编码:小时、月份都是环形变量。和风向一样,用正弦余弦处理。
  2. 季节划分:直接给一个季节标签(春/夏/秋/冬)。
# 小时特征(0-23)
hour_rad = 2 * np.pi * df['hour'] / 24
df['hour_sin'] = np.sin(hour_rad)
df['hour_cos'] = np.cos(hour_rad)

# 月份特征(1-12)
month_rad = 2 * np.pi * (df['month'] - 1) / 12
df['month_sin'] = np.sin(month_rad)
df['month_cos'] = np.cos(month_rad)

# 季节标签
def get_season(month):
    if month in [3,4,5]: return 0  # 春
    elif month in [6,7,8]: return 1  # 夏
    elif month in [9,10,11]: return 2  # 秋
    else: return 3  # 冬

df['season'] = df['month'].apply(get_season)

嗯,这里要注意:季节标签最好用one-hot编码,或者直接作为类别特征输入树模型。别用0,1,2,3这样的数值,模型会以为「冬季=3倍春季」,这就不对了。

3.5 知识体系总览

说了这么多,咱们用一张图来总结一下。这张图展示了特征工程的完整流程:

特征工程知识体系 原始气象数据 风速特征 原始值·变化率·平方/立方 风向特征 正弦·余弦·扇区编码 温压特征 空气密度·变化率 时间特征 小时·月份·季节 平滑·差分·幂变换 三角函数分解 物理公式推导 周期编码·类别化 最终特征集 → 输入模型

这张图把咱们刚才讲的内容串起来了。从原始数据出发,经过四个分支的特征处理,最终汇聚成模型能用的特征集。

3.6 避坑指南

最后,分享几个我踩过的坑:

  • 不要一次性生成所有特征。特征太多,模型容易过拟合。我建议先做相关性分析,剔除冗余特征。
  • 注意特征的时间对齐。风速、风向、温度、气压的采样频率可能不同。一定要统一到同一个时间戳上。
  • 小心「未来信息」。比如用t时刻的温度去预测t时刻的功率,没问题。但如果你不小心用了t+1时刻的温度,那就是作弊了。模型在训练时表现很好,上线后一塌糊涂。

一句话总结:特征工程不是越多越好,而是越「对」越好。把物理规律和统计方法结合起来,才能做出靠谱的预测模型。


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