类别特征有哪些编码方式?One-Hot、Label、Target Encoding 怎么选?
简化版
类别特征不能直接喂给大多数模型,要先编码成数值。常用三类:Label Encoding(每个类别映射一个整数,简单但引入了虚假的大小顺序,适合有序类别;无序类别是否可用取决于树库是否原生按类别处理);One-Hot Encoding(每个类别一列 0/1,无序类别的默认选择,缺点是高基数会维度爆炸);Target Encoding(用该类别对应的目标均值替换,适合高基数,但容易过拟合、会数据泄露,必须配合平滑和交叉折内编码)。选择时可从这里起步:无序低基数用 One-Hot,有序用 Ordinal,高基数考虑 Target/频率/哈希或原生类别模型;普通数值阈值树不要无条件直接用 Label。
详细版
常见编码方式对比:
| 编码 | 做法 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| Label / Ordinal | 类别→整数(如 红=0,绿=1,蓝=2) | 简单、不增维 | 引入虚假大小关系 | 有序类别、树模型 |
| One-Hot | 每类一列 0/1 | 无序、不失真 | 高基数维度爆炸、稀疏 | 无序、低基数 |
| Target(均值) | 用类别的目标均值替换 | 不增维、含目标信息、抗高基数 | 易过拟合、易泄露 | 高基数类别 |
| 频率 / 计数 | 用类别出现频次替换 | 不增维、简单 | 不同类别频率相同会冲突 | 高基数、树模型 |
| Embedding | 学一个低维稠密向量 | 表达力强、抗高基数 | 需要神经网络/训练 | 深度学习、超高基数 |
关键陷阱:
- Label Encoding 别用在线性/距离模型的无序特征上——模型会误以为「蓝(2) > 红(0)」有数值意义。
- One-Hot 遇到几千个类别(如用户 ID、邮编)会产生几千列稀疏特征,内存和过拟合都成问题。
- Target Encoding 必须防泄露:不能用「包含当前样本」的目标均值,要用交叉折 / 留一 + 平滑。
完整版教学
一、为什么类别特征要编码
现实数据里大量是类别(离散)特征:颜色、城市、职业、设备型号。大多数模型(线性模型、SVM、神经网络、KNN)内部做的是数值运算(加权求和、距离、内积),字符串没法直接参与。所以必须先把类别转成数值。
难点在于:转换不能凭空造出错误信息。比如把「红/绿/蓝」编成 0/1/2,模型就会以为它们之间有「蓝比红大 2」这种数值关系——可颜色本身无序,这个大小关系是编码硬塞进去的假象。不同编码方式,本质就是在「不增维」和「不引入虚假信息」之间做不同取舍。
二、Label / Ordinal Encoding:给类别编号
做法:给每个类别分配一个整数。
- 红=0,绿=1,蓝=2。
问题:这个编号隐含了顺序和间距。线性模型会认为「蓝(2) 是红(0) 的两倍」,KNN 会认为「绿(1) 离红(0) 比离蓝(2) 近」——对无序类别,这些全是错的。
什么时候能用:
- 类别本身有序(Ordinal):如学历「小学 < 初中 < 高中 < 本科」、评分「差 < 中 < 好」,此时整数的大小关系恰好对应真实顺序,用 Ordinal Encoding 反而是对的。
- 树模型要区分实现:普通 CART 若把编码后的整数当连续值,只能先做阈值切分,任意编号会引入人为顺序,可能需要多层才能表达一个类别子集;CatBoost、LightGBM 等原生类别处理又有各自算法和配置。因而不能笼统说“树模型直接 Label 就没问题”,必须确认具体库如何解释该列。
三、One-Hot Encoding:无序类别的标准解法
做法:一个有 k 个取值的类别,展开成 k 列(或 k-1 列),每行只有对应类别那列为 1,其余为 0。
颜色 红 绿 蓝
红 → 1 0 0
绿 → 0 1 0
蓝 → 0 0 1
优点:彻底消除虚假大小关系,每个类别是独立的一维,线性模型可以给每个类别单独学一个权重。这是无序类别的默认选择。
缺点与细节:
- 高基数灾难:类别数一多(城市几百、用户 ID 几万),列数随之爆炸,特征矩阵极稀疏,内存暴涨、模型易过拟合、训练变慢。
- 要不要丢一列(drop one)? 线性模型 + 有截距项时,k 列会和截距线性相关(多重共线性 / 哑变量陷阱),常 drop 掉一列变 k-1 列;树模型、正则化模型一般保留全部 k 列更直观。
- 测试集出现训练集没见过的新类别:要预先设定
handle_unknown='ignore'(全 0)或归到「其他」类,否则报错。
四、Target Encoding:用目标均值压缩高基数
当类别基数很高(几千上万),One-Hot 维度爆炸、Label 又引入虚假顺序,**Target Encoding(目标编码 / 均值编码)**是常用武器。
做法:用该类别对应的目标变量均值替换类别。比如做 CTR 预测,「城市=北京」的样本平均点击率是 0.23,就把「北京」编码为 0.23。
- 优点:无论多少类别都只占一列,还直接把「这个类别和目标的关系」编码进去,信息量大,对高基数特别有效。
致命风险——过拟合与数据泄露,这是面试必问:
- 泄露:如果用「包含当前样本自己」的目标均值来编码当前样本,就等于把答案(label)偷偷泄露进特征,训练集表现虚高、上线崩盘。
- 小类别过拟合:某类别只有 2 个样本、恰好都点击了,均值 = 1.0,这个 1.0 根本不可信。
正确做法(两道防线):
- 交叉折 / 留一编码(防泄露):算某样本的类别编码时,只用其他折 / 其他样本的目标均值,绝不含自己。
- 平滑(防小样本过拟合):把类别均值向全局均值收缩,样本越少越靠近全局均值:
编码值 = (n × 类别均值 + m × 全局均值) / (n + m)
n = 该类别样本数,m = 平滑强度
小类别 n 小,编码值主要由全局均值主导,不会被偶然的极端均值带偏。
五、其他实用编码
- 频率 / 计数编码:用类别出现的频次或占比替换。不增维、抗高基数,树模型里常用;缺点是两个频率相同的不同类别会撞成一样的值。
- 二进制 / 哈希编码(Hashing):把类别哈希到固定数量的桶,控制维度上限,适合超高基数和在线场景,代价是有哈希冲突、可解释性差。
- Embedding 编码:深度学习里把每个类别映射成一个可学习的低维稠密向量(如推荐系统的 user/item embedding)。表达力最强,能学出类别间语义相似度,但需要神经网络来训练。
六、怎么选——决策路径
类别有序吗?
├─ 有序 → Ordinal Encoding(保留顺序)
└─ 无序 →
基数高不高(类别数多不多)?
├─ 低基数(几个~几十个)→ One-Hot(首选)
└─ 高基数(几百~几万)→
用原生类别树? → 按该库类别接口;普通树仍需验证编码
用线性/NN? → Target Encoding(配交叉折+平滑)或 Embedding
再叠加模型因素:原生支持类别的树模型可按库接口处理;普通阈值树对任意 Label 编码并非天然安全;线性模型 / 距离模型 / 神经网络无序类别别用 Label,优先 One-Hot 或(高基数时)Target/Embedding。
七、用数字和工程流程校验理解
颜色只有红、绿、蓝 3 类时,One-Hot 只增加 3 列;用户 ID 有 100 万类时则可能产生 100 万维稀疏空间。Target Encoding 能压成 1 列,但必须在训练折外计算编码,避免当前样本标签泄露。
| 对象/方案 | 核心机制 | 选择或风险 |
|---|---|---|
| Ordinal/Label | 有真实顺序或树模型类别编号 | 无序线性模型会引入伪距离 |
| One-Hot | 低基数无序类别 | 维度随类别数增长 |
| Target Encoding | 高基数且有监督 | 平滑、OOF 计算、防泄露 |
把面试题落到可执行流程:
split folds
for each fold: fit mapping on other folds
encode held-out fold
test/online use full-train mapping + unknown fallback
Label Encoding 给出的 0、1、2 只是代码;在线性模型和 KNN 中会被误解为大小与距离,树模型的行为则取决于具体实现。
八、常见误区与追问
- 误区:Label Encoding 和 Ordinal Encoding 在任何模型中都一样安全。 只有类别确有顺序或模型原生按类别处理时,编号才不制造错误几何关系。
- 误区:Target Encoding 用全量训练标签求均值没有泄露。 样本自己的标签会进入其编码,必须使用 OOF、留一法和平滑。
- 追问:未知类别怎么处理? One-Hot 可忽略为全零,Target Encoding 常回退到全局均值或先验。
- 追问:Hashing Encoding 的代价是什么? 维度固定且无需词表,但不同类别可能哈希冲突,可解释性也较弱。
- 追问:高基数类别能直接用 embedding 吗? 可以,但需要足够数据、合理未知项策略和端到端训练。
九、加强记忆
记忆时抓住这条主线:类别编码在「不增维」和「不引入虚假顺序」之间做取舍。Label/Ordinal 编成整数——适合有序类别;无序类别会造出假的大小关系,树模型也要看具体实现是否原生支持类别;One-Hot 每类一列 0/1——无序低基数的默认解,缺点是高基数维度爆炸;Target Encoding 用类别的目标均值替换——专治高基数,但必须交叉折防泄露 + 平滑防小样本过拟合,否则把 label 泄露进特征就翻车;超高基数还有频率编码、哈希编码、Embedding。选择主线:有序→Ordinal,无序低基数→One-Hot,高基数→结合原生类别模型、频率、Target、哈希或 Embedding,并严格防泄露。