特征工程基础:特征构建、特征选择、特征缩放

各位同学,今天我们来聊聊特征工程。说实话,这是整个建模流程里最「脏」最「累」的活,但也是最能体现功力的地方。我见过太多人拿着原始数据直接丢进模型,结果跑出来一团糟——嗯,我自己也踩过这个坑。

特征工程说白了就三件事:造特征、挑特征、调特征。咱们一个一个说。

一、特征构建:从原始数据里「挖」出新信息

原始数据往往不够用。比如你拿到一个时间戳字段,模型根本不知道「星期几」和「是否节假日」对销量有影响。这时候就需要我们自己动手造特征。

我个人习惯把特征构建分成三类:

  • 统计特征:均值、方差、最大值、最小值、分位数等。比如用户过去7天的平均消费金额。
  • 时间特征:年、月、日、星期几、是否周末、是否节假日、距离上次事件的天数。
  • 交叉特征:把两个或多个字段组合起来。比如「年龄×收入」可能比单独用它们效果更好。

核心原则:特征构建不是越多越好。每个新特征都要有业务逻辑支撑,否则就是噪音。

我在项目中遇到过一件事:有个同学为了提升模型效果,一口气造了200多个特征,结果模型过拟合得一塌糊涂。后来我帮他删掉那些没逻辑的特征,只留了30个,效果反而提升了15%。

# 一个简单的特征构建示例
import pandas as pd
import numpy as np

# 原始数据
df = pd.DataFrame({
    '交易时间': ['2024-01-01 10:30:00', '2024-01-02 14:15:00'],
    '金额': [100, 250],
    '用户ID': ['A001', 'A002']
})

# 构建时间特征
df['交易时间'] = pd.to_datetime(df['交易时间'])
df['星期几'] = df['交易时间'].dt.dayofweek
df['是否周末'] = df['星期几'].isin([5, 6]).astype(int)
df['小时'] = df['交易时间'].dt.hour

# 构建统计特征(按用户)
df['用户平均金额'] = df.groupby('用户ID')['金额'].transform('mean')

二、特征选择:去粗取精,留下真正有用的

特征造完了,接下来就是挑。你想想看,如果100个特征里有80个是噪音,模型怎么可能学得好?

特征选择的方法我常用三种:

方法 原理 适用场景
过滤法 计算每个特征与目标变量的相关性,设定阈值 特征数量很大时,快速筛选
包裹法 用模型反复训练,评估特征子集的效果 特征数量适中,追求最优组合
嵌入法 利用模型自身的特征重要性(如树模型) 特征数量中等,且模型支持

我的建议:先用过滤法快速砍掉明显没用的特征,再用嵌入法精挑细选。包裹法虽然效果好,但计算成本太高,一般最后才用。

我曾经犯过一个错误:用皮尔逊相关系数做过滤,结果把两个非线性相关的强特征给删了。后来改用互信息(Mutual Information)才补回来。所以啊,选方法要看数据分布,不能一招鲜吃遍天。

# 使用随机森林的特征重要性做选择
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel

model = RandomForestClassifier(n_estimators=100)
model.fit(X_train, y_train)

# 只保留重要性大于阈值的特征
selector = SelectFromModel(model, threshold='median')
X_selected = selector.transform(X_train)

三、特征缩放:让所有特征站在同一起跑线

这一步很多人会忽略,但后果很严重。你想想,如果「年龄」范围是0-100,「收入」范围是0-100000,模型会天然认为「收入」更重要——因为它的数值更大。这显然不合理。

特征缩放主要有两种:

  • 标准化(Standardization):减去均值,除以标准差。结果服从均值为0、方差为1的分布。适合数据近似正态分布的情况。
  • 归一化(Normalization):缩放到[0,1]区间。适合数据有明确边界的情况,比如像素值0-255。

注意:树模型(随机森林、XGBoost)对特征缩放不敏感,但线性模型、SVM、神经网络非常依赖缩放。千万别搞混了。

我记得有一次做客户流失预测,用逻辑回归跑出来AUC只有0.6。排查了半天,发现是「月消费金额」和「注册天数」的量级差了1000倍。标准化之后,AUC直接跳到0.82。嗯,从那以后我再也不敢跳过这步了。

# 标准化 vs 归一化
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 标准化
scaler_std = StandardScaler()
X_std = scaler_std.fit_transform(X)

# 归一化
scaler_mm = MinMaxScaler()
X_mm = scaler_mm.fit_transform(X)

四、知识体系总览

下面这张图是我自己整理的,把特征工程的三个核心环节串起来了。你可以把它当作一个检查清单,每次做特征工程时对照着看。

特征工程核心流程 特征构建 特征选择 特征缩放 统计特征 时间特征 交叉特征 过滤法 包裹法 嵌入法 标准化 归一化 三者顺序:先构建 → 再选择 → 最后缩放 注意:缩放要在训练集上拟合,再应用到测试集

总结一下:特征工程没有银弹。每个数据集都有自己的脾气,你需要多试、多调、多复盘。我做了这么多年,依然会在新项目上踩坑——但每次踩完,都会把经验记下来。

好了,这一章的内容就到这里。记住:好的特征胜过复杂的模型。把时间花在特征工程上,绝对值得。

专注资料整理