第十八篇:特征工程到底在做什么——为什么很多时候数据比模型更重要

很多人刚开始学机器学习的时候,最容易把注意力全放在模型上。

比如:

  • 这题该用逻辑回归还是随机森林?
  • 要不要试试 XGBoost?
  • SVM 会不会比 KNN 更准?
  • 参数是不是还能再调一下?

这些问题当然都重要。
但如果你真的开始做一个完整项目,很快就会发现一件很现实的事:

模型能发挥到什么程度,很大程度上取决于你喂给它什么样的特征。

换句话说,模型不是凭空变聪明的。
它只能在你提供的信息上做判断。

如果你给它的特征本身就不够好、不够稳定、不够贴近问题本质,那模型再高级,也很难凭空补出真正有效的信息。

这就是为什么在机器学习里,总有人会说:

很多时候,数据和特征比模型更重要。

这句话听起来像鸡汤,但它其实非常现实。

这一篇我们就专门讲清楚:
特征工程到底是什么,它为什么重要,它通常在做什么,又容易踩什么坑。


1. 先说最核心的一句:特征工程是在帮模型更容易看到规律

如果你只记一句话,我建议你记这句:

特征工程的本质,是把原始数据变成更适合模型学习的表达。

这里面有两个关键词:

  • 原始数据
  • 更适合模型学习的表达

很多真实数据,并不是天然就长成“模型一看就明白”的样子。
你得先把它整理、转换、组合、提炼,让真正和任务有关的结构更容易被模型捕捉。

也就是说,特征工程并不是在“制造魔法”,而是在做一件很朴素但很关键的事:

把问题翻译成模型更容易理解的形式。


2. 原始数据,不一定等于好特征

这个点特别重要。

很多人一开始会下意识觉得:

我把手头所有字段全扔进去,不就信息最全了吗?

但现实里,原始字段和“好特征”之间,中间通常隔着很长一段距离。

举几个很常见的例子。

例子一:时间戳

假设你有一个字段是:

2026-04-09 18:37:42

你直接把这个时间戳原封不动扔给模型,通常意义不大。
但如果你把它拆成:

  • 小时
  • 星期几
  • 是不是周末
  • 是不是节假日
  • 是白天还是晚上

那这些新特征很可能就更有用。

因为模型真正需要的,不是“这一串时间字符串”,而是这背后和行为模式有关的结构。


例子二:出生年份

假设你有用户出生年份:

  • 1998
  • 2001
  • 1987

如果你直接用出生年份,模型当然也能学。
但很多时候你真正关心的是:

  • 年龄
  • 年龄段

因为“年龄”比“出生年份”更直接对应现实意义。


例子三:商品标题

假设你在做电商预测,手里有商品标题:

  • 2026新款轻薄羽绒服男短款立领
  • 春季休闲运动鞋女透气跑步鞋

原始文本当然有用,但如果你先提取出:

  • 是否包含“新款”
  • 品类
  • 性别
  • 季节属性
  • 价格区间
  • 标题长度

这些结构化特征,往往能帮传统机器学习模型更直接地学习。


这些例子都在说明一件事:

原始数据是素材,特征是你从素材里提取出来、真正让模型拿来判断的输入。


3. 特征工程并不神秘,它通常就在做这几类事

如果把特征工程拆开来看,其实它做的事情大致就几种。


第一类:清洗和修正

先把明显有问题的数据处理掉。

比如:

  • 缺失值填补
  • 异常值识别
  • 重复值清理
  • 单位统一
  • 格式统一

严格说,这一部分你前面在数据预处理那篇已经讲过。
但它和特征工程是紧密连在一起的。

因为脏数据不处理,你后面做再多特征,也可能建立在不靠谱的基础上。


第二类:变换

把原始字段换一种更适合学习的表达方式。

比如:

  • 时间戳拆成小时、星期几
  • 对数变换
  • 分箱
  • 标准化
  • 类别编码

这类操作的特点是:

信息未必变多了,但表达方式更合理了。


第三类:组合

把多个原始字段组合成一个新特征。

比如:

  • 总消费额 / 购买次数 = 客单价
  • 点击数 / 曝光数 = 点击率
  • 收入 / 家庭人数 = 人均收入
  • 房贷 / 月收入 = 负债压力比例

很多时候,模型自己并不总能轻松看出这些关系。
但你把它们提前做成特征,模型就更容易学到问题真正关心的模式。


第四类:筛选

不是所有特征都值得留下。

有些特征:

  • 几乎没信息量
  • 和目标关系很弱
  • 噪声很大
  • 和别的特征高度重复
  • 甚至可能造成泄漏

这时候做特征工程,不是“再加更多”,而是“删掉没必要的”。

这一点特别重要。
因为很多人一开始总觉得特征工程就是不断加特征,但其实:

好的特征工程,很多时候也包括敢于减特征。


4. 为什么好特征经常比换模型更有效

这个结论在实践里非常常见,而且对初学者特别重要。

很多时候你会发现:

  • 换一个更复杂的模型,只提升一点点
  • 但改好几个关键特征,效果直接明显改善

为什么?

因为模型再强,它也得建立在输入信息之上。
如果输入本身就缺少关键结构,模型很难无中生有。

比如你要预测用户是否流失。
如果你只给模型:

  • 用户 ID
  • 注册日期
  • 性别

那模型能学到的东西本来就有限。

但如果你进一步做出这些特征:

  • 最近 7 天活跃次数
  • 最近 30 天使用时长
  • 最近一次登录距今天数
  • 最近是否投诉
  • 历史付费金额
  • 是否连续多周下降活跃度

这时候你给模型的信息密度就完全不一样了。

所以在很多任务里,真正拉开差距的不是“你最后选了随机森林还是 XGBoost”,而是:

你到底有没有把业务里真正重要的信号变成特征。


5. 一个很典型的例子:模型不是不会学,而是你没把关键信息交给它

假设你在做外卖订单取消预测。

你如果只给模型这些字段:

  • 用户 ID
  • 商家 ID
  • 下单时间
  • 订单金额

当然也能学点东西。
但如果你进一步提取:

  • 是否高峰期下单
  • 用户过去 30 天下单取消率
  • 商家过去 7 天平均出餐时长
  • 用户和商家距离
  • 天气是否恶劣
  • 是否使用优惠券
  • 同商家近期取消率

模型的判断能力通常会强很多。

为什么?

因为这些特征更接近这个问题真实发生的机制。

订单会不会取消,往往不只是“这笔订单本身长什么样”,还和:

  • 时间场景
  • 用户历史行为
  • 商家履约能力
  • 外部环境

这些因素有关。

所以你会发现,特征工程说到底,其实很像在回答一个问题:

这个任务真正由哪些因素驱动?
我能不能把这些因素,用数据特征表达出来?

一旦你这样想,特征工程就不再是“机械加工字段”,而更像是在做问题理解。


6. 类别特征为什么经常特别值得认真处理

在真实数据里,类别特征非常常见。

比如:

  • 城市
  • 行业
  • 品类
  • 用户等级
  • 支付方式
  • 设备类型

但类别特征并不是直接扔给模型就完事的。
你得考虑怎么编码,以及编码方式会不会影响模型学习。


最常见的是独热编码

这个你前面已经提过了。

比如支付方式:

  • 微信
  • 支付宝
  • 银行卡

独热编码以后会变成几列 0/1。

它的好处是不会强行给类别引入大小关系。
适合很多线性模型和距离模型。


但有时候独热编码不够好

比如类别太多时:

  • 用户 ID
  • 商品 ID
  • 城市编码
  • 品牌编码

如果直接 one-hot,维度会爆炸。
这时候就要考虑别的方法,比如:

  • 频数编码
  • 目标编码
  • embedding(后面深度学习里更常见)

所以类别特征处理不是“有个方法就行”,而是要看:

  • 类别多少
  • 模型类型
  • 是否容易泄漏
  • 是否会过拟合

7. 数值特征为什么有时候也不能直接用

类别特征需要处理,这大家比较容易意识到。
但很多人会忽略,数值特征有时候也需要加工。

比如:

长尾分布

很多业务数据天然长尾,比如:

  • 用户消费金额
  • 商品销量
  • 停留时长

少数值特别大,大多数值比较小。
这种情况下,直接用原值,模型可能会被极端值影响很大。

常见做法是:

  • 对数变换
  • 截断
  • 分箱

这些操作不一定每次都要做,但你至少要意识到:

数值是数值,不代表它就已经是最适合学习的形态。


8. 分箱为什么有时候会有用

分箱这个操作看起来有点“粗”,但有时真的很有效。

比如你有年龄这个特征。
原始值当然可以直接用,但有时候你也会做成:

  • 18-24
  • 25-34
  • 35-44
  • 45+

为什么?

因为在某些任务里,模型真正需要的不是“精确到 27 岁和 28 岁的差异”,而是:

不同年龄阶段对应的行为模式差异。

分箱有时能带来两个好处:

  • 降低噪声敏感度
  • 更贴近现实业务区间

当然,分箱也不是永远更好。
它有时会损失信息。

所以重点不在于“分箱一定有用”,而在于:

你要知道什么时候连续值其实更适合变成区间。


9. 特征组合,往往是最容易出效果的一类操作

很多有用的信号,不藏在单个字段里,而藏在字段之间的关系里。

比如:

  • 访问次数很多,但下单数很少 → 转化低
  • 收入不低,但负债很高 → 财务压力大
  • 点击很多,但停留时间很短 → 可能是误点或低意愿
  • 登录频繁,但支付金额连续下降 → 活跃但价值下降

这些信息,如果只看单个字段,模型未必很容易捕捉。
但如果你提前做出:

  • 转化率
  • 负债收入比
  • 平均客单价
  • 最近活跃变化率

模型就更容易学到有意义的模式。

所以很多特征工程最值钱的地方,并不是“会不会用库”,而是:

你能不能从业务逻辑里想到有意义的特征关系。


10. 特征工程为什么特别需要业务理解

这一点很关键。

很多人学机器学习,容易把特征工程想成一个纯技术动作。
但真正做项目时,它往往特别依赖业务理解。

因为好特征往往不是“代码里长出来的”,而是:

你先理解问题,再把理解翻译成数据。

比如做用户流失预测时,一个懂业务的人很可能第一时间想到:

  • 最近活跃下降速度
  • 最近使用频率变化
  • 最近是否有负面反馈
  • 最近功能使用范围是否收缩

这些特征,不是你随便调个模型就能自动想到的。
它们来自对问题机制的理解。

这也是为什么很多真实团队里,做得好的模型,不一定是算法最花哨的,而往往是:

  • 最懂数据的人
  • 最懂业务的人
  • 最知道哪些信号真正关键的人

把特征做得更好。


11. 特征工程也很容易踩坑,尤其是数据泄漏

特征工程越重要,就越容易踩坑。
其中最大的一类坑就是:数据泄漏。

比如你要预测用户会不会流失,结果你做了一个特征:

  • “未来 7 天是否登录”

这当然特别有预测力。
问题是,这个特征在真实预测时根本拿不到。

它等于把答案偷偷塞进来了。

再比如做贷款违约预测时,你用了:

  • 放款后 30 天是否逾期

那这也不对。
因为你预测时并不知道“未来会不会逾期”。

所以特征工程有一个非常重要的原则:

所有特征都必须来自预测时刻之前、真实可获得的信息。

否则模型分数会很好看,但完全没法落地。


12. 特征太多,也不一定是好事

这是很多人很容易误判的一点。

一听说特征重要,就容易走到另一个极端:

那我把能想到的特征都加进去,不就更好吗?

不一定。

特征太多可能带来这些问题:

  • 引入更多噪声
  • 增加过拟合风险
  • 增加训练成本
  • 让模型更难解释
  • 让真正重要的信号被淹没

所以特征工程不只是“做加法”,也常常要做减法。

你得不断问自己:

  • 这个特征真的有信息吗?
  • 它和已有特征高度重复吗?
  • 它会不会引入泄漏?
  • 它在训练集上看起来有用,是不是只是偶然?

很多时候,做完一轮特征扩展之后,接下来要做的不是继续堆,而是筛。


13. 一个简单的小例子:为什么“比例”特征经常比原始值更有用

这个例子很适合放进文章里,因为直观。

假设你要预测一个用户会不会购买。

原始字段有:

  • 商品浏览次数
  • 商品收藏次数
  • 商品加入购物车次数

这些原始值当然都可以用。
但如果你进一步做几个特征:

  • 收藏率 = 收藏次数 / 浏览次数
  • 加购率 = 加购物车次数 / 浏览次数

这通常会比单独看原始次数更有意义。

为什么?

因为:

  • 浏览 100 次收藏 10 次
  • 浏览 10 次收藏 10 次

这两个用户收藏次数一样,但意愿强度显然不一样。

比例特征,往往更能反映行为质量,而不只是行为数量。

这就是特征工程常见的价值:

不是创造信息,而是把已有信息变成更贴近问题的表达。


14. 用一个简单代码例子演示一下特征构造

下面给一个非常基础的示例,读者能直接看懂。

import pandas as pd

# 构造简单数据
data = pd.DataFrame({
    "browse_count": [100, 50, 20, 80],
    "favorite_count": [10, 5, 2, 1],
    "cart_count": [8, 3, 1, 0],
    "buy": [1, 1, 0, 0]
})

print("原始数据:")
print(data)

# 构造新特征
data["favorite_rate"] = data["favorite_count"] / data["browse_count"]
data["cart_rate"] = data["cart_count"] / data["browse_count"]

print("\n加入新特征后:")
print(data)

15. 怎么判断一个特征值不值得做

这是很多人特别想知道、但很少有人认真讲的事。

说到底,特征值不值得做,通常可以从这几个角度去想:

第一,它有没有业务意义

如果一个特征你自己都说不清它为什么可能和目标有关,那就要小心。

第二,它是不是来自真实可用信息

如果预测时根本拿不到,那再强也没意义。

第三,它是不是和已有特征高度重复

如果只是换个名字重复表达,价值未必大。

第四,它是不是只在训练集里“看起来有用”

这就要靠验证集、交叉验证去判断。

第五,它会不会让模型更容易过拟合

尤其是一些很细碎、很局部、很容易记住训练集的特征。

所以判断特征,不只是看“加了以后训练集分数涨没涨”,更重要的是看:

它是不是稳定、有意义、能泛化。


16. 这一篇真正想传达的,不是“多做特征”,而是“做对特征”

特征工程很容易被误解成一件体力活:

  • 多做几个字段
  • 多组合几列
  • 多跑几轮筛选

但真正重要的不是“做得多”,而是“做得对”。

你要让读者慢慢建立一个感觉:

好特征不是堆出来的,是理解出来的。

它来自:

  • 对数据的理解
  • 对任务的理解
  • 对业务机制的理解
  • 对模型局限的理解

所以特征工程真正厉害的地方,不是技术动作本身,而是:

你是否真的知道,模型缺的是什么信息。


17. 到这里,机器学习系列其实已经开始真正像“做项目”了

前面几篇更多是在讲模型和方法。
这一篇开始,你的系列已经明显从“认识算法”走向“开始做实战”。

因为现实里的机器学习,很少是:

  • 干净数据
  • 现成特征
  • 模型一跑就结束

更常见的是:

  • 数据脏
  • 字段杂
  • 特征不够用
  • 要不断试、不断改、不断验证

而特征工程,恰恰就是连接“原始业务数据”和“模型输入”的那一步。

所以这一篇其实很关键。
它会让读者意识到:

模型当然重要,但模型看到什么,往往更重要。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐