处理类别数据
城市、颜色、设备型号、邮编和职业都可能是特征,但模型不能直接理解字符串,也不应把任意编号误认为存在大小关系。这一章把“类别 → 词汇表 → 向量”的完整链路讲透,并处理未知值、高基数和标签质量这些真实项目一定会遇到的问题。
- 判断一列数据是数值还是类别,即使它由数字组成。
- 手工解释一条类别值经过词汇表变成独热向量再进入模型的全过程。
- 用 OOV 桶正确处理训练时没见过的类别,并知道为什么要监控它。
- 在独热、哈希和嵌入之间为高基数特征选择合理方案。
- 评估人工标注和机器打分的标签质量风险。
- 判断特征交叉是否带来真实增益,并控制其过拟合风险。
数字也可以是分类数据
分类数据(类别数据)是只能从一个有限集合中取值的特征。判断标准不是“长什么样”,而是“取值之间的数学运算有没有业务含义”。
1.1 是什么:看取值集合,不看数据类型
“红色、蓝色、绿色”是类别;“上海、北京、广州”也是类别。容易迷惑的是由数字组成的列:邮政编码 20004、商品编号 10002、楼层 3。它们在数据库里是整数,但整数之间的大小和差值没有可解释的含义——邮编 20004 不是 10002 的“两倍”,也不比它“更大”。
类别
大小和差值没有可解释的业务含义,模型若把它当数值,会错误地认为数值越大越“靠后”。
不能当连续数值直接训练数值
200 平方米是 100 平方米的两倍,差值 100 平方米也有明确含义。
适合缩放后作为数值特征1.2 为什么模型不能直接接收“红色”或编号 2?
常见模型本质上进行浮点数运算:它拿到什么数字,就默认这些数字可以比较、可以加减。如果直接给“红色=1、蓝色=2、绿色=3”,模型会认为蓝色是红色的“两倍”、绿色比蓝色“大一点”——这些关系是我们编造编号时偶然产生的,不是数据的真实规律。所以类别数据必须先编码:定义一个稳定的词汇表,再把每个类别转成向量。
拿到一列数据,问自己两个问题:① 取值是不是来自一个有限集合?② 对取值做减法、除法有没有业务含义?如果 ① 是而 ② 否,它就是类别数据,应该走本章的编码链路,而不是数值数据模块的缩放链路。
“楼层”在房价预测中可以是数值(越高越贵,差值有意义),也可以是类别(1 层带院子、顶层带阁楼,各有独立效应)。先想清楚业务假设,再决定编码方式;拿不准时,两种都试并用验证集比较。
词汇表与独热编码
编码分两步:先用词汇表固定“哪些取值是合法的、各排在第几位”,再用独热编码把类别变成只有一个是 1、其余全是 0 的向量。
2.1 词汇表:类别的“户口本”
词汇表是训练前确定的类别清单,例如颜色词汇表 [红, 蓝, 绿, 黑]。每个类别对应一个固定索引:红=0、蓝=1、绿=2、黑=3。索引只用于查表定位,不直接输入模型——否则就回到了 1.2 节的编号陷阱。词汇表必须随模型一起保存并版本化:训练时“蓝”是第 1 位,线上预测时也必须还是第 1 位。
2.2 独热编码:每个类别一个独立位置
样本颜色为“蓝”时,模型收到的不是索引 1,而是向量 [0, 1, 0, 0]。四个位置对应四个类别,每个位置会被模型学习一个独立的权重。这样“蓝”和“红”之间没有大小关系,只有各自不同的影响——正是我们想要的语义。
| 原始值 | 索引(仅用于查表) | 真正输入模型的独热向量 | 模型为它学习的权重 |
|---|---|---|---|
| 红 | 0 | [1, 0, 0, 0] | w₀(独立) |
| 蓝 | 1 | [0, 1, 0, 0] | w₁(独立) |
| 绿 | 2 | [0, 0, 1, 0] | w₂(独立) |
| 黑 | 3 | [0, 0, 0, 1] | w₃(独立) |
2.3 稀疏表示:只存等于 1 的位置
独热向量里绝大多数位置是 0,称为稀疏特征。当词汇表有 50,000 个词时,完整向量有 50,000 维,却只有 1 个位置非零。工程上通常只存储非零位置:“蓝”的稀疏表示就是索引 1。这只是存储和计算的优化,数学含义与完整独热向量完全等价。多标签场景可用多热编码:一条评论同时提到“蓝”和“黑”,向量是 [0, 1, 0, 1],稀疏存储是 [1, 3]。
类别数量不多(几个到几千个)、每个类别样本量足够时,独热编码简单可靠,是默认选择。类别数量巨大或需要表达“类别之间有多像”时,看第 4 节的高基数方案。
分类数据中的离群值
数值数据的离群值是“极端大的数”;分类数据的离群值是词汇表外的未知类别——训练时从没见过,线上却一定会出现。
3.1 是什么:未知值必有去处
训练数据里只有红、蓝、绿、黑,上线后用户选了“紫色”。这时有三种可能的处理方式:程序崩溃(最糟)、悄悄映射成某个已知类别比如“红色”(更糟,因为错误不可见)、或者进入一个专门预留的 OOV(Out-of-Vocabulary,词汇表外)位置。正确做法是第三种。
3.2 为什么不能悄悄当成已知类别?
把“紫色”当成“红色”,模型会用红色的权重处理紫色样本,预测看起来正常,错误却完全不可见——你既不知道错了多少,也不知道什么时候开始错的。OOV 的价值在于把“不认识”显式表达出来:模型为 OOV 位置学习一个专属权重,所有未知值共享它。
3.3 什么时候警惕:监控 OOV 比例
OOV 比例是重要的线上健康指标。它突然上升,通常意味着上游数据变化:新设备型号上市、新城市开通业务、或者数据管道把编码搞乱了。此时应评估是否更新词汇表并重新训练,而不是让 OOV 长期沉默吸收一切。
典型事故:训练用中文词表,线上流量混入英文词;或 App 改版新增选项,模型还在用旧词表。预防措施是词表随模型一起版本化发布,并在上线前用最近线上数据回放一遍编码流程,统计 OOV 比例。
对高维分类特征编码
高基数指一列类别特征的可能取值非常多:用户 ID 有几百万个、词汇有几十万个、邮编有几千个。基数越高,独热编码的代价越大。
4.1 高维度带来什么问题?
独热向量的维度等于词汇表大小。词汇表 50 万,每条样本就是 50 万维向量:训练和推理都变慢、内存暴涨;更关键的是,罕见类别只有极少样本,对应位置的权重学不到可靠数值,反而容易记住噪声。此外,独热编码天然认为任意两个类别的距离都一样——“iPhone 15”和“iPhone 14”并不比“iPhone 15”和某老式功能机更相似。
4.2 三种方案的取舍
| 方案 | 做法 | 优点 | 代价 | 适合 |
|---|---|---|---|---|
| 独热 + 截断词表 | 只保留出现次数最多的 N 个类别,其余进 OOV | 简单、无冲突、可解释 | 长尾类别被合并处理 | 基数中等,头部类别覆盖大部分流量 |
| 哈希 | 把类别值哈希到固定数量的桶,如 2¹⁸ 个 | 维度可控,无需维护词表,新值天然有位置 | 不同类别可能碰撞进同一桶,共享权重 | 超高基数、可容忍少量冲突的线上系统 |
| 嵌入 | 为每个类别学习一个低维稠密向量,如 32 维 | 紧凑快速,向量距离可表达相似性 | 需要随模型训练,调参更复杂 | 推荐、文本等大规模类别任务 |
哈希的碰撞是空间换稳定的交易:桶足够多时,碰撞的类别大多本来就罕见,影响有限。嵌入则是通往后续「嵌入」模块的桥梁——它把“类别是互相孤立的点”变成“类别在连续空间中有位置”。
先问基数多大、样本多不多:类别几千以内且样本充足,直接独热;基数几十万但头部集中,独热 + 截断词表;基数百万级或需要相似性,用哈希过渡或直接上嵌入。任何方案都要在训练集上确定配置并随模型保存。
标签从哪里来:人工评分员与机器评分员
分类模型需要类别标签,而类别标签常常来自“判断”:这条评论是否有毒?这张图是猫还是狗?判断可以来自人,也可以来自另一个模型。
5.1 人工评分员:质量高,但慢、贵、有分歧
人工标注能理解语境和业务规则,是标签质量的上限;但它慢、昂贵,难以覆盖海量数据。更隐蔽的问题是分歧:同一条评论“算不算攻击性言论”,不同标注员可能给出相反答案。这不是谁偷懒,而是任务本身有模糊地带。
5.2 机器评分员:快而便宜,但会继承偏差
用已有模型批量给新数据打分,可以低成本获得大量标签,这类标签常被称为银标签(相对人工的“金标签”)。风险在于:旧模型的错误会被固化成“事实”,旧模型的系统性偏差(比如对某种方言识别率更低)会被新模型原样继承,甚至放大。
5.3 什么时候用哪种?
- 标签定义模糊、需要语境理解(毒性、质量分)。
- 数据量可控,或用于建金标准评测集。
- 做法:标注规范、多人标注、一致性检查、定期抽样复核。
- 任务成熟、已有可靠旧模型(OCR、成熟分类器)。
- 需要海量标签做预训练或粗筛。
- 做法:抽样人工复核,监控机器标签与人工标签的差异率。
标注规范要像代码一样版本化:写清楚边界案例怎么判、给标注员看正反例、用多人重叠标注计算一致性。发现一致性低时,先修规范再扩量——否则你花钱买来的是噪声。
特征交叉与使用时机
特征交叉是把两个或多个特征的组合作为一个新特征,让模型学习“这些条件同时发生”时的额外信号。
6.1 是什么:组合成为新类别
例如“手机 × 晚间”可能比“手机”或“晚间”单独更能预测购买:通勤路上刷手机下单是独特场景。交叉后每种组合是一个新类别,如 mobile__night,再对它做独热编码,模型为每个组合学习独立权重。这对线性模型特别有价值——没有交叉时,线性模型只能表达各特征的独立影响之和。
6.2 为什么不能滥用:组合爆炸与过拟合
两个特征的交叉组合数 = 两者基数相乘。“城市(300)× 商品类别(200)”会产生 60,000 个组合,其中绝大多数只出现过几次甚至没出现过。样本极少的组合,模型只能记住偶然噪声——这正是过拟合的温床。
6.3 什么时候用:三步判断
能讲出“为什么这个组合有额外含义”再做:手机×晚间、节假日×景区。不要穷举所有特征对。
极少出现的组合学不到可靠权重;必要时把长尾组合并入“其他”桶。
训练集指标改善不算数;验证集也改善,交叉才有泛化价值。
类别特征先用稳定的词汇表定义可能值,再转为独热向量(工程上用稀疏表示);未知值进 OOV 并被监控;高基数特征在截断词表、哈希、嵌入之间按基数和样本量取舍;标签来源决定了质量上限;特征交叉只在有业务假设、样本充足且验证集确认时使用。
本模块术语速查
- 类别特征
- 只能从有限集合取值的特征;数字组成的列也可能是类别。
- 词汇表
- 训练期间认可的类别集合及其固定索引,需随模型版本化。
- 独热编码
- 一个类别对应一个位置为 1、其余为 0 的向量;每个位置学习独立权重。
- 稀疏表示
- 只存储非零位置的存储方式,与完整独热向量数学等价。
- 多热编码
- 多标签场景中多个位置同时为 1 的向量。
- OOV
- 词汇表外类别的统一容器;其比例是线上健康指标。
- 高基数
- 可能类别数量非常多的特征,独热编码代价随之增大。
- 哈希技巧
- 把类别哈希到固定桶数控制维度,代价是可能的碰撞。
- 银标签
- 机器评分员产生的标签;便宜但继承旧模型偏差。
- 特征交叉
- 将多个特征的组合当作新特征,捕捉联合条件的信号。