LightGBM 如何处理类别特征?
简化版
LightGBM 可原生处理类别特征:类别以非负整数编码并显式声明后,训练器按节点的一二阶统计对类别排序并寻找类别集合二分,而不是把编码大小当作连续顺序。编码需落在实现支持的整数范围内,负值通常按缺失处理。训练与推理必须共享类别语义;高基数、稀有类别和未知类别仍需专门验证。
详细版
-
类别编码使用实现支持的非负整数 ID,不代表数值顺序;负编码通常会被当作 missing。
-
原生算法避免 one-hot 高维并能组合类别集合。
-
排序统计由当前训练节点的一二阶信息计算,仍需
cat_smooth、最小组样本等约束防小类别过拟合。 -
训练和推理必须共享类别到整数的映射。
-
高基数 ID 仍可能记忆样本,不因原生支持就安全。
完整版教学
一、原生类别切分寻找集合而非数值阈值
无序 K 类穷举所有子集代价指数级。
LightGBM 按类别聚合当前目标的一阶/二阶统计并排序,再扫描排序边界,避免指数穷举。具体评分随目标和版本实现变化,不应笼统说成用全局标签均值做目标编码。
这是一种高效近似:切分含义是某类别集合走左,而不是编码小于某数就天然相似。
二、底层机制与公式
categorical rule: category in {c2,c5,c9} -> left
not: encoded_value <= 5 as ordinal meaning
三、带数字的推演
城市编码 {北京:0,上海:1,深圳:2,成都:3}。
最佳集合可能是 {北京,成都} 对 {上海,深圳};连续阈值无法用一次切分表达该非相邻组合。
四、方案对比
| 方案/对象 | 核心特点 | 代价或边界 |
|---|---|---|
| 原生类别 | 集合切分、维度低 | 依赖库和正确声明 |
| One-hot | 通用透明 | 高基数维度爆炸 |
| 目标编码 | 可跨模型 | 泄漏与平滑复杂 |
五、执行流程
训练集建立非负整数映射 -> 标记 categorical columns -> 设置稀有/未知类
-> 训练与验证 -> 保存映射和模型 -> 线上拒绝映射漂移
六、边界条件与工程代价
Pandas category code 若训练与线上分别生成,整数可能对应不同城市,模型不会报错却会静默误判。未见类别若被编码成 -1,LightGBM 通常按缺失值处理;若业务想使用显式 unknown 类,应在训练映射中预留非负 ID 并让训练数据覆盖其路由语义。
映射必须作为模型资产。
类别数接近样本数的 ID 特征会产生高方差切分,应删除、聚合或严格用时间外验证。
记忆钩子:原生类别特征的关键是“整数只是 ID,切分是类别集合”。
七、常见误区与追问
-
误区:整数编码后可按连续特征使用。 无序编号的大小没有语义。
-
追问:原生处理为何比穷举快? 先按统计排序再扫描有限边界。
-
误区:原生支持就不会过拟合高基数。 小类别和 ID 仍有巨大方差。
-
追问:未知类别怎么办? 明确选择按缺失路由,或在训练映射中预留非负 unknown 类;两种策略都要用未见类别样本验收,不能让线上编码器临时发号。
-
追问:为何必须保存映射? 同一个整数在训练和线上必须表示同一类别。
八、加强记忆
原生类别特征的关键是“整数只是 ID,切分是类别集合”。
算法减少搜索,不替你解决高基数、未知类别和映射漂移。