机器学习之离散型特征处理 -- 独热码(one_hot_encoding)


原文链接: 机器学习之离散型特征处理 -- 独热码(one_hot_encoding)

scikit-learn中离散特征二值化 - 天泽28的专栏 - CSDN博客
[scikit-learn] 特征二值化编码函数的一些坑 - han_sen cloud network - CSDN博客
1、什么是独热码

  独热码,在英文文献中称做 one-hot code, 直观来说就是有多少个状态就有多少比特,而且只有一个比特为 1,其他全为 0 的一种码制,更加详细参加 one_hot code(维基百科)。在机器学习中对于离散型的分类型的数据,需要对其进行数字化比如说性别这一属性,只能有男性或者女性或者其他这三种值,如何对这三个值进行数字化表达?一种简单的方式就是男性为 0,女性为 1,其他为 2,这样做有什么问题?

  使用上面简单的序列对分类值进行表示后,进行模型训练时可能会产生一个问题就是特征的因为数字值得不同影响模型的训练效果,在模型训练的过程中不同的值使得同一特征在样本中的权重可能发生变化,假如直接编码成 1000,是不是比编码成 1 对模型的的影响更大。为了解决上述的问题,使训练过程中不受到因为分类值表示的问题对模型产生的负面影响,引入独热码对分类型的特征进行独热码编码。

2、编码过程

  假如只有一个特征是离散值:

    {sex:{male, female,other}}

  该特征总共有 3 个不同的分类值,此时需要 3 个 bit 位表示该特征是什么值,对应 bit 位为 1 的位置对应原来的特征的值(一般情况下可以将原始的特征的取值进行排序,以便于后期使用),此时得到独热码为 {100} 男性 ,{010}女性,{001}其他

  假如多个特征需要独热码编码,那么久按照上面的方法依次将每个特征的独热码拼接起来:

    {sex:{male, female,other}}
    {grade:{一年级, 二年级,三年级}}
    {class:{一班, 二班,三班, 四班}}

  此时对于输入为 {sex:male; grade: 四年级} 进行独热编码,可以首先将 sex 按照上面的进行编码得到{100},然后按照 grade 进行编码为{0001},那么两者连接起来得到最后的独热码{1000001};

3、独热码的函数库

  使用 python 的话 scikit_learn 中就封装了现成的编码函数,以下为代码示例:

from sklearn import preprocessing
enc = preprocessing.OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
enc.transform([[0, 1, 3]]).toarray()

one_hot encoding
  输出结果:
array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])

spark 中也有相应的函数不做介绍自行百度或者 google。

标签编码LabelEncoder

作用: 对不连续的数字利用LabelEncoder() 将转换成连续的数值型变量。即是对不连续的数字或者文本进行编号例如:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit([1,5,67,100])
le.transform([1,1,100,67,5])
# 输出: array([0,0,3,2,1])


>>> le = preprocessing.LabelEncoder()
>>> le.fit(["paris", "paris", "tokyo", "amsterdam"])
LabelEncoder()
>>> list(le.classes_)
['amsterdam', 'paris', 'tokyo']     # 三个类别分别为0 1 2
>>> le.transform(["tokyo", "tokyo", "paris"]) 
array([2, 2, 1]...)    
>>> list(le.inverse_transform([2, 2, 1]))   # 逆过程
['tokyo', 'tokyo', 'paris']

限制:上文颜色的例子已经提到标签编码了。Label encoding在某些情况下很有用,但是场景限制很多。再举一例:比如有[dog,cat,dog,mouse,cat],我们把其转换为[1,2,1,3,2]。这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。所以目前还没有发现标签编码的广泛使用。

`