1. 类别编码基础:为什么我们需要编码?
在机器学习项目中,我们经常会遇到包含类别型特征的数据集。比如用户的性别(男/女)、产品类别(电子产品/服装/食品)或者地区名称(北京/上海/广州)。这些非数值型数据无法直接被大多数机器学习算法处理,因为算法本质上是基于数学运算的。这时候就需要**类别编码(Categorical Encoding)**技术来将这些文本或符号转换为数值形式。
我刚开始接触这个问题时,曾经天真地认为直接把"男"替换为1,"女"替换为0就可以了。结果模型表现很差,后来才明白这种简单的序数编码会引入错误的顺序关系。比如,如果编码为男=1,女=2,算法会误认为"女"比"男"大,这在很多场景下是不合理的。
类别编码的核心挑战在于:
- 如何保留类别本身的语义信息
- 避免引入虚假的数值关系
- 处理高基数(high-cardinality)特征(即类别取值很多的情况)
- 防止过拟合,特别是在有监督编码中
2. One-Hot编码:最直观的解决方案
2.1 One-Hot编码原理
One-Hot编码(独热编码)是我最早学会的编码方法,也是应用最广泛的。它的核心思想很简单:对于一个有N个不同取值的类别特征,我们创建N个新的二进制特征,每个特征对应原始特征的一个可能取值。
举个例子,假设我们有一个"颜色"特征,可能的取值为红、绿、蓝。One-Hot编码后会生成三个新特征:
- 颜色_红
- 颜色_绿
- 颜色_蓝
当原始值为"红"时,只有"颜色_红"这一列为1,其他为0。这种编码完全消除了任何人为引入的顺序关系。
2.2 Python实现与参数详解
在Python中,我们可以使用category_encoders库的OneHotEncoder:
import pandas as pd
import numpy as np
from category_encoders import OneHotEncoder
# 创建示例数据
data = pd.DataFrame({
'颜色': ['红', '绿', '蓝', '绿', '红'],
'尺寸': ['S', 'M', 'L', 'XL', 'M']
})
# 初始化编码器
encoder = OneHotEncoder(
cols=['颜色', '尺寸'], # 指定要编码的列
use_cat_names=True, # 使用类别名作为新列名前缀
handle_unknown='value', # 处理未知类别的方式
handle_missing='value' # 处理缺失值的方式
)
# 拟合并转换数据
encoded_data = encoder.fit_transform(data)
print(encoded_data)
关键参数说明:
handle_unknown: 处理训练时未见过的类别- 'error': 报错
- 'return_nan': 设为NaN
- 'value': 设为0
- 'indicator': 新增一列指示未知类别
handle_missing: 处理缺失值,选项同上use_cat_names: 是否在列名中包含原始类别名
2.3 优缺点与适用场景
优点:
- 完全消除类别间的虚假顺序关系
- 实现简单直观
- 适用于线性模型和距离度量算法
缺点:
- 对于高基数特征会导致维度爆炸
- 生成的特征矩阵非常稀疏
- 可能引入多重共线性问题
适用场景:
- 类别数量较少(一般<15个)
- 使用基于树的模型时
- 需要完全保留类别信息的情况
我在电商用户画像项目中就吃过亏,对用户浏览的"商品类别"直接使用One-Hot编码,结果生成了上千个新特征,不仅训练速度变慢,模型效果反而下降了。这时候就需要考虑其他编码方式了。
3. Target Encoding:利用目标信息的智能编码
3.1 Target Encoding原理
Target Encoding(目标编码)是一种有监督的编码方法,它使用目标变量的统计信息来编码类别特征。对于分类问题,它用该类别下目标变量的平均概率来替代原始类别;对于回归问题,则使用目标变量的均值。
数学表达式为:
编码值 = λ × 类别内目标均值 + (1 - λ) × 全局目标均值
其中λ是一个介于0和1之间的权重,取决于类别的大小和设定的平滑参数。
这种编码的优势在于:
- 将类别信息与预测目标直接关联
- 不会增加特征维度
- 对高基数特征特别有效


1199

被折叠的 条评论
为什么被折叠?



