机器学习“特征编码”的经验分享:鱼还是熊掌?
作者:xiaoyu
微信公众号:Python数据科学
知乎:python数据分析师
1. 为什么要进行特征编码?
我们拿到的数据通常比较脏乱,可能会带有各种非数字特殊符号,比如中文。下面这个表中显示了我们最原始的数据集。而实际上机器学习模型需要的数据是数字型的,因为只有数字类型才能进行计算。因此,对于各种特殊的特征值,我们都需要对其进行相应的编码,也是量化的过程。
2. 特征编码类型
本篇,我们主要说一下分类型特征的编码方式。对于分类型数据的编码,我们通常会使用两种方式来实现,分别是:one-hot encoding 和 label-encoding。下面我们先介绍一下这两种编码。
One-hot encoding
one-hot encoding
也就是我们常常听到的独热编码(哑变量)。那么到底什么是独热编码呢?我们来看一个例子,是二手房房价分析中所使用的数据:
可以看到,图中的Elevator
和Renovation
都是定类型数据。除去缺失值,Elevator
分类有电梯和无电梯两种。Renovation
分为有精装,简装,毛坯和其它四种。下面,我们要对Elevator这个变量进行编码,在pandas
中有现成的独热编码方法get_dummy
,代码如下:
pd.get_dummies(lianjia_df['Elevator'])
原来的Elevator
变量被拆分为两个单独的变量,这两个变量就是原来的分类特征值:有电梯和无电梯。并且新变量的特征值用数字0和1来替代,代表是否或者有无的概念。比如无电梯变量的1代表是(没有电梯),相反,0就代表否(有电梯)。因此概括一下,独热编码就是将原始特征变量转换成以原始特征值分类的多维度的变量,并用是否(0,1)这种方式的新特征值替代和量化。
Label encoding
label-encoding就是用标签进行编码的意思,即我们给特征变量自定义数字标签,量化特征。来看一个例子:
Class=['大一','大二','大三','大四'] df = pd.DataFrame({'Class':Class}) df
Class
特征是定序数据类型,也是分类类型,但比定类更高级,因为有排序。Label encoding
就是对特征值进行自定义式的标签编码。比如将大一变为1,大二变为2,大三为3,大四为4。那么经过编码后,特征值将变为以下的样子:
classMap = {'大一':1,'大二':2,'大三':3,'大四':4} df['Class'] = df['Class'].map(classMap) df
上面就将Class特征进行相应的编码。其实,Label encoding
并没有任何限制,你也可以将Class定义为10,20,30,40
,只不过1,2,3,4
看起来比较方便。因此总结概括,Label encoding就是将原始特征值编码为自定义的数字标签完成量化编码过程。
3. 两种编码方式的优缺点
One-hot encoding
- 优点:解决了分类器不好处理分类数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。
- 缺点:当类别的数量很多时,特征空间会变得非常大,容易造成维度灾难。
Label encoding
- 优点:解决了分类编码的问题,可以自由定义量化数字。但其实也是缺点,因为数值本身没有任何含义,只是排序。如大中小编码为
123
,也可以编码为321
,即数值没有意义。 - 缺点:可解释性比较差。比如有
[dog,cat,dog,mouse,cat]
,我们把其转换为[1,2,1,3,2]
,这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。因此,Label encoding编码其实并没有很宽的应用场景。
4. 两种编码该如何区分和使用?
明白这两种编码方式并不难,难的是如何区分和使用。好多朋友面对数据,会产生困惑,不知该使用哪种编码方式最为合适。对于这个问题,有以下几点需要考量:
- 特征的数据类型
- 所要使用的模型
事先声明:编码方式没有固定的方式,具体问题还需具体分析。对模型结果有利的编码才是最正确的。所以,实际中如果分不清哪种更好的时候,可能需要将两种都尝试进行对比。
下面分享一下自己浅显的经验(一般情况下的使用):
特征数据类型
- 对于定类类型的数据,建议使用one-hot encoding。定类类型就是纯分类,不排序,没有逻辑关系。比如性别分男和女,男女不存在任何逻辑关系,我们不能说男就比女好,或者相反。再者,中国各省市分类也可以用独热编码,同样各省不存在逻辑关系,这时候使用one-hot encoding会合适些。但注意,一般会舍去一个变量,比如男的对立面肯定是女,那么女就是重复信息,所以保留其中一个变量即可。
- 对于定序类型的数据,建议使用label encoding。定序类型也是分类,但有排序逻辑关系,等级上高于定类。比如,学历分小学,初中,高中,本科,研究生,各个类别之间存在一定的逻辑,显然研究生学历是最高的,小学最低。这时候使用Label encoding会显得更合适,因为自定义的数字顺序可以不破坏原有逻辑,并与这个逻辑相对应。
所使用的模型
- 对数值大小敏感的模型必须使用one-hotencoding。典型的例子就是LR和SVM。二者的损失函数对数值大小是敏感的,并且变量间的数值大小是有比较意义的。而Label encoding的数字编码没有数值大小的含义,只是一种排序,因此对于这些模型都使用one-hot encoding。
- 对数值大小不敏感的模型(如树模型)不建议使用one-hotencoding。一般这类模型为树模型。如果分类类别特别多,那么one-hot encoding会分裂出很多特征变量。这时候,如果我们限制了树模型的深度而不能向下分裂的话,一些特征变量可能就因为模型无法继续分裂而被舍弃损失掉了。因此,此种情况下可以考虑使用Label encoding。
以上两点考量需要综合考虑,而非单独判断。也就是说需要结合数据类型和模型的情况来具体选择编码方式。
5. 总结
以上是博主对于两种编码方式的一些理解,如果有什么不对或者需要补充的地方,请大家指正。而对于连续型的变量,如果需要编码首先需要进行离散化(分箱),然后再使用上述编码方式编码。数据离散化的内容我们后续进行介绍。
关注微信公众号:Python数据科学,发现更多精彩内容。