《百面》第二章「类别型特征」,提出一个问题:
在对数据进行预处理时,应该怎样处理类别型特征?
仔细研究才发现,这里面竟然有很多以前从未听过的知识——毕竟研究生不会有人手把手教你这么系统地去学,只有老板给什么就去实现什么而已……那么开始吧~
什么是类别型特征
看名字就知道,是机器学习的输入数据中,表示类别的特征。比如:
| 数据ID | 性别 | 学历 | 出生城市 | 10年内深圳买房(y) |
|---|---|---|---|---|
| 1 | 男 | 博士 | 深圳 | 是 |
| 2 | 女 | 硕士 | 重庆 | 否 |
| 3 | 男 | 大学 | 哈尔滨 | 否 |
| 4 | 女 | 高中 | 成都 | 是 |
| 5 | 男 | 初中 | 湖南 | 是 |
这些数据需要被通过某种方法转换为数字,也就是所谓的编码,才能更好地被那些机器学习算法中建立的各种数学模型来使用。我以前的转换手段就是暴力的:
- 女=0,男=1
- 初中=0,高中=1,大学=2,硕士=3,博士=4
- 深圳=0,重庆=1,哈尔滨=2,成都=3,湖南=4
- 否=0,是=1
非常简单,然而这其实并不是最好的处理方式,好在,我一直学习和使用的都是树模型……
类别型特征的处理方法
序号编码(Label Encoding)
上面的暴力方法就是序号编码,通过数字和值的一一映射达到编码的目的。但它适合于处理具有大小关系的特征,比如学历从低到高正好对应了数字从小到大,没有改变特征的特性。如果把它用于处理没有任何大小关系的特征,比如出生城市,所有的城市都是平级的,转变为数值之后却莫名地增加了一层大小关系,这对于数值大小敏感的模型(比如SVM支持向量机)是致命的——因为会影响损失函数之类计算结果。
python的机器学习包sklearn的LabelEncoder实现了序号编码。
独热编码(One-hot Encoding)
独热编码也成为哑变量编码(Dummy Encoding)(不过有的也将哑变量编码区分为“随机去项的降维独热编码”),指的是,将原始特征变量转换为原始特征值分类的多维度变量,在每个维度上使用0/1来进行是/否、有/无的量化。通俗来说就是,把每个取值作为一个新特征,一行数据中,取到了这个值就是1,没取到这个值就是0。用出生城市来举个例子:
| 数据ID\出生城市 | 深圳 | 重庆 | 哈尔滨 | 成都 | 湖南 |
|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 0 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 | 0 |
| 4 | 0 | 0 | 0 | 1 | 0 |
| 5 | 0 | 0 | 0 | 0 | 1 |
这样做的好处在于:
- 没有了数值大小关系,SVM也可以尽情使用哦~
- 扩充了特征,将一个“出生城市”的特征扩充为了5个新特征,有效地减少了过拟合风险。
然而也很容易看出缺点:
- 如果取值较多,很可能会分裂出大量的新特征,导致维度过高不容易处理。
- 非常不适合树模型。如果特征很多,取这个值的数量又很少,那么一些特征变量很可能因为树模型的参数配置而无法向下分裂,导致这些信息白白丢失掉了。
- 一个特征变为多个特征,当数据条数越多的时候,整体的数据量会暴增。
所以,在使用独热编码的时候可以这样做:
- 使用稀疏向量节省空间。
独热编码只有一个取值1,其余为0,符合稀疏向量的特性。也就是说,我们把上述出生城市改写为:
| 数据ID | 出生城市 |
|---|---|
| 1 | 5, (1,1) |
| 2 | 5, (2,1) |
| 3 | 5, (3,1) |
| 4 | 5, (4,1) |
| 5 | 5, (5,1) |
只是表述方式上变了,数据量减小了,但仍然是拆分成了5个特征。
- 配合特征选择来降低维度。
我们都知道,K近邻算法需要有效地去衡量两点之间的距离,因此通常需要进行降维。独热编码带来的维度灾难副作用可以通过降维来减少其影响。常见的降维方式有PCA主成分分析、随机特征选择等等。我个人是最喜欢用随机了,因为通常采用的是树模型,而且随机能有效减少树的过拟合,实现起来又简单。
python的机器学习包sklearn的OneHotEncoder实现了独热编码,pandas的get_dummies同样实现了独热编码,推荐pandas。
二进制编码(Binary Encoding)
就是用二进制去表示类别,比如出生城市可以表示为:
| 数据ID\出生城市 | F1 | F2 | F3 |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| 4 | 0 | 1 | 1 |
| 5 | 1 | 0 | 0 |
有的同学会说,哎这不是有大小关系了吗。但仔细看会发现,这种大小关系在单独一列中是不会体现出来的。不过似乎没有看到过这种二进制编码有具体应用,只看见过理解神经网络的中间层原理的时候,发现它利用了这种二进制机制。
平均数编码(Mean Encoding)
划重点!
这个方法是在kaggle圈的各位大佬们针对“高基数类别型特征(High-Cardinality Categorical Attributes)”使用之后发现非常有效(AUC的提升)的方法,它并没有被大量研究,中文资料甚至更少,但是实践真的有奇效。平均数编码的提出是在2001年的论文《A Preprocessing Scheme for High-Cardinality Categorical Attributes in Classification and Prediction Problems》,其实是相当古老的论文了,只有2017年的一篇《CatBoost: unbiased boosting with categorical features》提到了它。
1、clustering和smoothing
平均数编码主要用于处理高基数类别型特征,高基数的意思就是类别非常多,比如邮编(000001-999999)、区号、IP、家庭住址,这类特征如果直接用独热编码就不要想了。所以目前常见的做法就是:
- 将1到N(N非常大)的映射问题通过聚类转换为1到K(K<<N)
- 然后再进行独热编码
这种方法统称为clustering。
举个直观但不真实的例子,虽然颜色可能有——深蓝、浅蓝、湖蓝、碧蓝、靛蓝、钴蓝、蔚蓝、宝蓝、藏蓝、冰蓝、宝石蓝、海蓝、湛蓝、橙红、粉红、紫红(N=16),那么我们根据分类取值(Y=0/1)把这些颜色都聚合为蓝色、红色(K=2)这两个值,一下就减少了大量的特征取值。然后再将蓝色、红色通过独热编码变为2列,就完成了类别值到数值的转换。然而这种做法导致了特征信息的丢失(本来有很多种蓝色特征,结果我都看成一种蓝色特征了)。
那么我们把这种clustering泛化一下,不要强迫为蓝色、红色(=0、=1)了,改成概率估计是蓝色的概率,是红色的概率(=0~1之间的小数),也就产生了smoothing。
平均数编码就是smoothing的一种实现。
2、以二值目标分类理解平均数编码
假设我们有一个二值分类问题,给定特征X是高基数类别型特征,
由于后面需要用这些特征去训练机器学习模型,所以在特征处理这一步,我们只能使用训练数据去估计这个特征值的后验概率。设训练集有
其中
其中,
对比一下神经网络中常常使用的Sigmod函数:
从图像上说,相当于把Sigmod函数图像向右平移k个单位+拉伸f倍。
从意义上说,
以上
3、处理缺失值
我们只用了训练数据,在测试数据里很可能有根本没有出现过的取值,对于这个公式来讲,处理缺失值非常简单,只需要增加一个空缺值
这样做的好处在于,如果缺失值和分类有很大相关性,那么这个公式就可以很好地表达这种相关信息;反之如果缺失值和分类没有太大关系,那么
4、多分类问题
只需要将估计的概率转变一下就好啦:
注意之前二分类的时候我们是直接替换的那些类别型特征值,而这里多分类的时候,假设有C个类,会产生C列。为什么之前C=2的时候只有1列呢?因为特征线性相关了,比如求
5、连续型类别问题(回归)
对于回归来说,只需要把概率估计改为期望估计就可
如果把二分类的类别标记为0/1,那么二分类和回归可以用相同的公式计算。
6、具有层次结构的类别型特征
有的时候我们的类别型特征可能具有层级结构,比如邮编,北京市前两位全是10开头的,然后再继续往后细分是哪个区。我们可以利用这种层级关系来使得每个取值的样本数目更加合适一点。设5位邮编为ZIP5,4位ZIP4,以此类推。那么最开始的计算公式是这样的:
当ZIP5样本很稀疏的时候,它几乎所有的取值都会依赖于先验概率。而我们可以用这种层次结构来尽可能地提取出新的信息。很明显,ZIP5的先验概率可以用ZIP4去估计:
当样本充足时,会用ZIP5的后验概率,当样本不充足时,会去考虑ZIP4的后验概率,逐级向上,相当于根据数据密度进行了自动调节。
7、平均数编码的过拟合问题
有同学在实践中发现,如果使用全部训练数据去处理特征,那么之后的机器学习模型会产生过拟合问题。所以一种解决方法是,分成k份,每份内的特征值处理采用其他k-1份组成的数据集来训练平均数编码模型,再替换自己的值。
总结
| 编码方式 | 适用类型 | 实现难度 | 效果 |
|---|---|---|---|
| 序号编码 | 大小不敏感模型(树) | 容易 | 好 |
| 独热编码 | 特征取值少、非树模型 | 容易 | 好 |
| 二进制编码 | - | 容易 | - |
| 平均数编码 | 高基数类别型特征 | 困难 | 非常好 |



粤公网安备44030002014216号