什么是类别特征(Categorical Features)
类别特征: 表示“类型 / 状态 / 身份”的变量,没有数值大小意义
常见示例:
- 性别:Male / Female
- 婚姻:Single / Married
- 职业:Engineer / Teacher
- 国家 / 城市
- 产品类别
- 客户类型(新客 / 老客)
类别特征的两种类型
| 类型 | 特点 | 示例 |
|---|---|---|
| 名义型(Nominal) | 无顺序 | 性别、国家 |
| 有序型(Ordinal) | 有自然顺序 | 教育程度、评分 |
绝大多数 Kaggle / 风控类别特征都是 Nominal
为什么类别特征必须处理?
模型无法直接处理字符串 强行转数字会引入错误的“大小关系” 编码方式不当会严重影响模型效果
类别特征处理是特征工程中最关键的一步之一
Label Encoding(标签编码)
基本原理
把每个类别映射为一个整数:
| 类别 | 编码 |
|---|---|
| A | 0 |
| B | 1 |
| C | 2 |
sklearn 示例
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['gender_le'] = le.fit_transform(df['gender'])
优点
- 简单
- 维度不增加
- 对树模型友好
致命缺点(非常重要)
模型会误以为类别之间有大小关系:
Engineer (2) > Teacher (1) > Sales (0)
One-Hot Encoding(独热编码)
基本原理
一个类别 → 多个 0/1 特征
原始变量:
color = red / blue / green
编码后:
| color_red | color_blue | color_green |
|---|---|---|
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 1 |
pandas 实现
pd.get_dummies(df, columns=['color'])
sklearn 实现(推荐)
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(sparse=False)
X_encoded = ohe.fit_transform(df[['color']])
One-Hot 的优点
- 不引入大小关系
- 对线性模型安全
- 模型可解释性好
One-Hot 的缺点
- 维度增加
- 高基数特征会爆炸
- 容易掉进「虚拟变量陷阱」
虚拟变量陷阱(Dummy Variable Trap)
什么是虚拟变量陷阱?
如果一个类别有 K 种取值,你生成了 K 个 one-hot 特征
则存在:
x1 + x2 + ... + xk = 1
完全共线(Perfect Multicollinearity)
会带来什么问题?
对以下模型 非常致命:
- Linear Regression
- Logistic Regression
后果:
- 参数不稳定
- 矩阵不可逆
- 系数解释错误
正确解决方案:Drop One(K-1)
pandas 推荐写法
pd.get_dummies(df, columns=['color'], drop_first=True)
sklearn 写法
OneHotEncoder(drop='first', sparse=False)
只要知道前 K−1 个类别是否成立,就能推断最后一个类别 因此保留 K−1 个特征即可
六、不同模型的最佳编码策略(总结表)
| 模型 | 推荐编码 |
|---|---|
| Linear Regression | One-hot + drop_first |
| Logistic Regression | One-hot + drop_first |
| SVM / KNN | One-hot |
| Decision Tree | Label / One-hot |
| Random Forest | Label / One-hot |
| XGBoost | Label / One-hot |
| LightGBM | Label / 原生类别 |
| CatBoost | 无需编码 |
实战中的关键注意事项
训练集 & 测试集必须一致
错误做法:
pd.get_dummies(train)
pd.get_dummies(test)
正确做法:
- 先合并再编码
- 或用
OneHotEncoder只fit(train)