OneHotEncoder独热编码和 LabelEncoder标签编码

学习sklearn和kagggle时遇到的问题,什么是独热编码?为何要用独热编码?什么状况下能够用独热编码?以及和其余几种编码方式的区别。html

首先了解机器学习中的特征类别:连续型特征离散型特征     算法

       拿到获取的原始特征,必须对每一特征分别进行归一化,好比,特征A的取值范围是[-1000,1000],特征B的取值范围是[-1,1].若是使用logistic回归,w1*x1+w2*x2,由于x1的取值太大了,因此x2基本起不了做用。因此,必须进行特征的归一化,每一个特征都单独进行归一化。框架

       对于连续性特征:机器学习

  • Rescale bounded continuous features: All continuous input that are bounded, rescale them to [-1, 1] through x = (2x - max - min)/(max - min).    线性放缩到[-1,1]
  • Standardize all continuous features: All continuous input should be standardized and by this I mean, for every continuous feature, compute its mean (u) and standard deviation (s) and do x = (x - u)/s.       放缩到均值为0,方差为1

       对于离散性特征:函数

  • Binarize categorical/discrete features: 对于离散的特征基本就是按照one-hot(独热)编码,该离散特征有多少取值,就用多少维来表示该特征。

 

一. 什么是独热编码?post

       独热码,在英文文献中称作 one-hot code, 直观来讲就是有多少个状态就有多少比特,并且只有一个比特为1,其余全为0的一种码制。举例以下:学习

       假若有三种颜色特征:红、黄、蓝。 在利用机器学习的算法时通常须要进行向量化或者数字化。那么你可能想令 红=1,黄=2,蓝=3. 那么这样其实实现了标签编码,即给不一样类别以标签。然而这意味着机器可能会学习到“红<黄<蓝”,但这并非咱们的让机器学习的本意,只是想让机器区分它们,并没有大小比较之意。因此这时标签编码是不够的,须要进一步转换。由于有三种颜色状态,因此就有3个比特。即红色:1 0 0 ,黄色: 0 1 0,蓝色:0 0 1 。如此一来每两个向量之间的距离都是根号2,在向量空间距离都相等,因此这样不会出现偏序性,基本不会影响基于向量空间度量算法的效果。ui

      天然状态码为:000,001,010,011,100,101this

      独热编码为:000001,000010,000100,001000,010000,100000编码

      来一个sklearn的例子:

from sklearn import preprocessing
enc = preprocessing.OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])    # fit来学习编码
enc.transform([[0, 1, 3]]).toarray()    # 进行编码

输出:array([[ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.]])

数据矩阵是4*3,即4个数据,3个特征维度。

0 0 3                      观察左边的数据矩阵,第一列为第一个特征维度,有两种取值0\1. 因此对应编码方式为10 、01

1 1 0                                               同理,第二列为第二个特征维度,有三种取值0\1\2,因此对应编码方式为100、0十、001

0 2 1                                               同理,第三列为第三个特征维度,有四中取值0\1\2\3,因此对应编码方式为1000、0100、00十、0001

1 0 2

再来看要进行编码的参数[0 , 1,  3], 0做为第一个特征编码为10,  1做为第二个特征编码为010, 3做为第三个特征编码为0001.  故此编码结果为 1 0 0 1 0 0 0 0 1

 

二. 为何要独热编码?

      正如上文所言,独热编码(哑变量 dummy variable)是由于大部分算法是基于向量空间中的度量来进行计算的,为了使非偏序关系的变量取值不具备偏序性,而且到圆点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征均可以看作是连续的特征就能够跟对连续型特征的归一化方法同样,对每一维特征进行归一化。好比归一化到[-1,1]或归一化到均值为0,方差为1。       

        为何特征向量要映射到欧式空间?

        将离散特征经过one-hot编码映射到欧式空间,是由于,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或类似度的计算是很是重要的,而咱们经常使用的距离或类似度的计算都是在欧式空间的类似度计算,计算余弦类似性,基于的就是欧式空间。

 

三 .独热编码优缺点

  • 优势:独热编码解决了分类器很差处理属性数据的问题,在必定程度上也起到了扩充特征的做用。它的值只有0和1,不一样的类型存储在垂直的空间。
  • 缺点:当类别的数量不少时,特征空间会变得很是大。在这种状况下,通常能够用PCA来减小维度。并且one hot encoding+PCA这种组合在实际中也很是有用。

 

四. 什么状况下(不)用独热编码?

  • 用:独热编码用来解决类别型数据的离散值问题,
  • 不用:将离散型特征进行one-hot编码的做用,是为了让距离计算更合理,但若是特征是离散的,而且不用one-hot编码就能够很合理的计算出距离,那么就不必进行one-hot编码。 有些基于树的算法在处理变量时,并非基于向量空间度量,数值只是个类别符号,即没有偏序关系,因此不用进行独热编码。  Tree Model不太须要one-hot编码: 对于决策树来讲,one-hot的本质是增长树的深度

总的来讲,要是one hot encoding的类别数目不太多,建议优先考虑。 

 

五.  什么状况下(不)须要归一化?

  • 须要: 基于参数的模型或基于距离的模型,都是要进行特征的归一化。
  • 不须要:基于树的方法是不须要进行特征的归一化,例如随机森林,bagging 和 boosting等。

 

六.  标签编码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。因此目前尚未发现标签编码的普遍使用。

 

 

 

 附:基本的机器学习过程

 

 

 

 

参考:

Quora:What are good ways to handle discrete and continuous inputs together?

数据预处理:独热编码(One-Hot Encoding)

 

使用sklearn优雅地进行数据挖掘

数据挖掘比赛通用框架

Label Encoding vs One Hot Encoding

[scikit-learn] 特征二值化编码函数的一些坑

相关文章
相关标签/搜索