机器学习中的特征工程
做机器学习时,我们经常会听到一句话:
模型的选择决定性能上限,特征的选择决定性能下限。
模型再强,如果喂进去的是“模糊、失真”的数据,结果很难好到哪里去。特征工程要做的事情,就是把原始数据,变成对当前问题更“像样”的描述,让模型看得懂、抓得住重点。
这篇文档想回答的是一个朴素的问题:
手里就这些数据,怎么整理,才能尽量代表我真正关心的业务问题?
在动手做特征工程之前,先把问题想清楚
特征工程不是随便造几个列、跑几个脚本,它背后有一套很朴素的思考顺序:
-
用什么指标衡量好坏?
- 回归问题常用:RMSE、MAE 等误差指标
- 分类问题常用:AUC、F1、准确率、召回率等 指标不同,对特征的敏感区域也不同,比如 AUC 更在意排序,而不是绝对值。
-
当前问题到底是什么类型?
- 回归:预测一个连续值(房价、销量、转化率)
- 分类:预测离散类别(是否违约、是否流失)
- 排序、时间序列、推荐等也会有各自特点
-
大致打算用什么模型?
- 线性模型对线性相关、尺度差异比较敏感
- 树模型对特征缩放不敏感,却很吃“分箱、组合、比率”之类的特征
- 时间序列模型关心顺序和时间间隔 用什么模型,会反过来影响特征应该长什么样。
-
现在手里的数据,能在多大程度上代表这个问题?
- 有哪些字段?哪些是“直接描述问题本身”的?
- 哪些是容易出错或缺失的?
- 哪些字段和目标变量可能存在强关系?
很多时候,特征工程做不好,并不是变换不够花哨,而是最开始的问题理解就偏了。
特征工程的整体流程:把数据喂给模型之前要做什么?
可以粗暴地记成三步:
- Select(选择):选哪些原始字段?哪些可以直接用,哪些要丢掉?
- Clean(清洗):错误值、缺失值、脏数据怎么处理?
-
Transform & Enrich(转换与增强):
- 从原始字段中提取结构化特征
- 从已有特征中构造新特征
- 进行必要的编码、标准化、降维等
这些步骤没有唯一顺序,但大致会在项目中反复迭代。
特征是从原始数据到可用信号
特征可以简单理解为:
输入到机器学习算法中的“信息片段”。
它有几个不同的视角:
按使用场景看
- 计算机视觉:像素点、颜色直方图、边缘特征、深度特征等
- 自然语言处理:词、短语、n-gram、句向量、文档向量
- 金融市场:价格、成交量、波动率、技术指标(均线、MACD 等)
按模型类型看
- 时间序列模型:滞后值(lag)、移动平均、滚动窗口统计量等
- 图像模型:原始像素或卷积提取的特征图
- 强化学习:环境状态编码(位置、速度、奖励历史等)
按数据获取方式看
- 直接使用原始字段:时间、金额、类别标签等
-
特征提取:
- 文本分词、提取关键词、embedding
- 图片提取纹理、边缘、深度特征
-
特征构造:
- 时间差、比率、交叉特征
- 聚合特征(例如“过去 7 天的平均值”)
从这个角度看,特征工程就是在回答:
在现有数据基础上,我还能挖掘出多少有用的“信号”?
数据清洗
先把“脏活累活”做好
纠错
- 修正明显异常值(负年龄、超过合理范围的数值等)
- 统一格式:时间格式、货币单位、编码方式
- 处理重复样本、逻辑上互斥的字段组合
缺失值处理
常见做法包括:
-
简单填补
- 数值特征:均值、中位数
- 类别特征:众数或额外增加一个“缺失”类别
-
基于模型的填补
- 使用 Matrix Factorization(矩阵分解) 或回归模型来预测缺失值
- 适用于协同过滤、评分数据等场景
有时候,“是否缺失”本身就是一个有用特征,可以显式增加一个缺失标记。
数据转换
常见的例子:
-
One-Hot Encoding:
- 把类别变量编码成 0/1 向量,适用于线性模型、树模型等
-
文本处理:
- 分词(Tokenizing)
- 词袋(Bag-of-Words)、TF-IDF
- 词向量(Word2Vec、GloVe 等),再组合成句子/文档向量
这一步的目标,是把“人好理解的形式”,变成“模型好计算的形式”。
数据选择
选什么特征,砍掉什么特征?
特征选择既考验专业背景,也考验直觉和实验能力。
依赖领域知识
- 资深业务同事往往能直接告诉你: “这个字段基本没用”“真正影响结果的是这些因素”。
- 在信用评分、风险控制、医疗等领域,这一步尤其重要。
依赖数据分析
可以用一些轻量的分析手段帮你“扫一眼”:
- 简单的 线性回归 或 树模型 看特征权重/重要性
- 相关性分析:皮尔逊相关系数、Spearman 等
- 信息增益(information gain)、互信息等指标
这些方法不会告诉你“唯一正确答案”,但能帮你排除一部分“明显没贡献”的特征。
用模型结果倒推
- 尝试不同特征组合对模型表现的影响
- 尝试在不同样本量下,特征对性能的边际贡献
-
检查噪声和脏数据:
- 某些特征对训练集有效,对验证集却表现不稳,可能意味着它更像噪声
注意特征之间的关系
- 对于 普通最小二乘(Ordinary Least Squares) 这类线性模型, 特征之间强线性相关(多重共线性) 会导致参数不稳定
- 这类场景下,要么删掉高度相关的特征,要么加正则化,或者用降维方法处理
数据转换与数据增强
从“有数据”到“有信号”
这一步的核心,是从已有特征中“榨出更多信息”。
从已有特征构造新特征
常见手段包括:
-
基本算术运算:加、减、乘、除、平均
- 例如:单价 = 总价 / 数量
-
比率特征
- 如:点击率(点击数/曝光数)、转化率等
-
多项式特征
- 在 SVM 中常见的 kernel trick 本质上就是高维特征映射
-
非线性变换
- 对数、平方根、指数、Sigmoid 等
- 例如:对长尾分布做 log 变换,让模型更容易学习
-
频域变换
- 对时间序列做傅里叶变换、拉普拉斯变换等,提取周期性或趋势信息
类型变量编码
除了 One-Hot,还可以用:
- 目标编码(target encoding)
- 频数编码
- embedding 形式的稠密向量表示
选择哪种方式,和模型类型、数据规模、过拟合风险都有关系。
降维:在信息和复杂度之间找平衡
当特征数量变多,模型会变得更复杂,训练与推理成本升高,过拟合风险也随之增加。这时就需要考虑降维。
常见方式:
-
直接删掉不重要的特征
- 基于特征重要性、相关性或业务判断
- 优点是可解释性好
-
主成分分析(PCA)
- 通过线性变换,找到方差最大的方向,用少量主成分替代原始特征
- 常用于去冗余、可视化、预处理
-
因子分析
- 尝试用少量“潜在因子”解释观察到的多个特征
- 更适合探索数据内部结构和潜在变量
降维的本质,是在“保留信息量”和“降低复杂度”之间找一个合适的折中。
关于如何提高特征工程的水平
特征工程很难有“最优解”,原因在于:
- 每个问题不一样
- 每个行业的数据分布不一样
- 每次手里能拿到的数据也不一样
但有两条路几乎对所有人都有效:
-
多做项目,多反复
- 在实际任务中尝试不同特征方案
- 总结“哪类特征在什么问题上经常有效”,形成自己的经验库
-
多看别人怎么做
- Kaggle 比赛分享、技术博客、公开演讲
- 观察优秀方案是如何构造、筛选和组合特征的
参考资料
- Discover Feature Engineering, How to Engineer Features and How to Get Good at It
- Art of Feature Engineering for Data Science - Nabeel Sarwar
-
[**Kaggle Tips for Feature Engineering and Selection by Gilberto Titericz Kaggle Days Meetup Madrid**](https://www.youtube.com/watch?v=RtqtM1UJfZc&ab_channel=KaggleDaysMeetupSpain) - scikit-learn: Preprocessing data