3、特征工程入门:特征类型、标准化与缺失值处理

特征工程这东西,说白了就是给模型喂饭。饭好不好吃,直接影响模型能不能干活。我见过太多人一上来就调参、换模型,结果发现数据本身就有问题——嗯,那真是白忙活一场。

今天咱们聊聊特征工程的三个基本功:特征类型、标准化归一化、缺失值处理。别小看这些,它们能决定你因子的生死。

3.1 特征类型:数值、类别与时序

特征类型不同,处理方式天差地别。我刚开始做量化时,把类别特征直接扔进模型,结果模型学了一堆乱七八糟的东西。后来才明白,每种特征都有自己的脾气。

数值特征

数值特征就是那些能直接比较大小的数据,比如股价、成交量、市盈率。这类特征最常见,也最容易处理。但有个坑——量纲问题。比如股价是几十块,成交量是几百万股,直接放一起,模型会偏向数值大的特征。

核心要点:数值特征需要做标准化或归一化,否则模型会「偏心」。

类别特征

类别特征就是那些分门别类的数据,比如行业、板块、交易所。这类特征不能直接比较大小。你想想看,「银行」和「科技」哪个大?没法比。

处理类别特征,我习惯用独热编码(One-Hot Encoding)。举个例子:

# 原始数据:行业标签
industry = ['银行', '科技', '消费', '银行']

# 独热编码后
bank     = [1, 0, 0, 1]
tech     = [0, 1, 0, 0]
consumer = [0, 0, 1, 0]

但要注意,类别太多时独热编码会爆炸。比如股票有上百个行业,编码后特征维度暴增。这时候可以用目标编码(Target Encoding)或者嵌入(Embedding)。

避坑指南:我曾经把「股票代码」当成数值特征处理,结果模型学了一堆无意义的规律。股票代码本质上是类别特征,千万别搞混。

时序特征

时序特征有先后顺序,比如过去5天的收益率、移动平均线。这类特征最特殊,因为它有「记忆」。处理时序特征时,我一般会做滞后处理(Lag)和窗口统计(Rolling)。

举个例子:

# 生成过去3天的收益率特征
df['return_lag1'] = df['return'].shift(1)
df['return_lag2'] = df['return'].shift(2)
df['return_lag3'] = df['return'].shift(3)

# 过去5天的平均收益率
df['return_ma5'] = df['return'].rolling(5).mean()

这里有个关键点:时序特征不能泄露未来信息。我见过有人用未来数据做特征,回测时表现完美,实盘时一塌糊涂。说白了,就是作弊了。

3.2 标准化与归一化

标准化和归一化,这两个概念经常被混用。其实它们目的不同,适用场景也不同。

标准化(Standardization)

标准化的公式很简单:(x - mean) / std。处理后数据均值为0,标准差为1。它不改变数据的分布形状,只是把数据「拉」到同一个尺度。

我习惯在以下场景用标准化:

  • 模型假设数据服从正态分布(如线性回归、逻辑回归)
  • 需要保留异常值信息(标准化不会把异常值压缩到固定区间)
  • 特征之间量纲差异大,但分布形态相似

归一化(Normalization)

归一化是把数据缩放到[0,1]区间,公式是:(x - min) / (max - min)。它会把所有数据压到同一个范围,但会改变分布形状。

归一化适合的场景:

  • 模型对数值范围敏感(如神经网络、KNN)
  • 特征值有明确上下界(如百分比、比率)
  • 需要保留相对大小关系,不关心绝对数值
我的经验:做因子挖掘时,我一般先用标准化。因为很多因子是收益率、波动率这类数据,标准化后更容易发现异常模式。但如果因子是比率类(如PE、PB),归一化更合适。

什么时候不做?

有些模型不需要标准化,比如决策树、随机森林。它们基于分裂点做判断,不受量纲影响。你想想看,树模型只看特征值的大小关系,不看绝对数值。

3.3 缺失值处理策略

缺失值,是每个量化工程师的噩梦。我做过一个项目,数据缺失率高达30%,直接删除的话,样本量少得可怜。怎么办?

缺失值类型

先搞清楚缺失值的类型,这决定了处理策略:

类型 含义 例子
完全随机缺失 缺失与数据本身无关 传感器偶尔故障
随机缺失 缺失与其他特征有关 小市值股票数据更容易缺失
非随机缺失 缺失与缺失值本身有关 亏损公司不披露某些数据

常见处理策略

策略一:删除

最简单粗暴。如果缺失值占比很小(比如<5%),直接删除对应行或列。但要注意,删除可能导致样本偏差。

策略二:填充

填充方法很多,我常用的有:

  • 均值/中位数填充:适合数值特征,简单有效
  • 众数填充:适合类别特征
  • 前向/后向填充:适合时序数据,用前后值填充
  • 模型预测填充:用其他特征预测缺失值,精度高但计算量大
# 均值填充示例
df['feature'].fillna(df['feature'].mean(), inplace=True)

# 前向填充(时序数据)
df['feature'].fillna(method='ffill', inplace=True)

策略三:标记缺失

有时候缺失本身就是一个信号。比如某只股票突然不披露数据了,这可能是个危险信号。我会额外加一列,标记是否缺失。

避坑指南:我曾经用全局均值填充所有缺失值,结果模型学到的全是「均值附近」的规律。后来改用分组均值(比如按行业分组填充),效果好了很多。记住,填充要尽量保留数据原有的分布特征。

3.4 知识体系总览

说了这么多,咱们用一张图总结一下特征工程的核心逻辑:

特征工程核心流程 原始数据 特征类型判断 数值特征 类别特征 时序特征 标准化/归一化 独热编码/目标编码 滞后/窗口统计 缺失值处理(删除/填充/标记)

这张图展示了特征工程的核心流程:从原始数据出发,先判断特征类型,然后针对不同类型做相应处理,最后统一处理缺失值。每一步都有讲究,跳不得。

我的建议:做特征工程时,先花20%的时间理解数据,再花80%的时间处理数据。很多人反过来,上来就写代码,结果越做越乱。数据理解透了,后面的事就顺了。

好了,特征工程入门就聊到这儿。记住一句话:好的特征工程,胜过十个模型调参。下次咱们聊聊更深入的特征选择方法。

专注资料整理