【数据编码】构造虚拟特征变量(OneHotEncode)

文章目录

  • 前言
  • 一、独热编码
    • 1. 为什么要使用独热编码
    • 2. 独热编码优缺点
    • 3. 什么情况下(不)用独热编码
    • 4. 什么情况下(不)需要对编码后的数据归一化
    • 5. One Hot Encode 在sklearn中的实现
    • 6. One Hot Encode 在Pandas中实现
  • 二、标签编码
    • 1.什么是Label encoding
    • 2. 特点
  • 三、如何区分两种编码?
    • 1.特征数据类型
    • 2.所使用的模型
    • 3. Label在sklearn中的实现
  • 总结


前言

  数据编码是特征工程中重要的一步,特征工程还包括缺失值处理、异常值处理、变量转化、特征筛选及降维,其中《特征工程系统综合指南》可查看【EDA与特征工程】数据探索与特征工程综合指南,《特征筛选及降维》可查看【特征工程】重要特征识别理论。


一、独热编码

  独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效。

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

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

  对于每一个特征,如果它有m个可能值,那么经过独热编码后,就变成了m个二元特征(每一个寄存器位由0/1构成)。并且,这些特征互斥,每次只有一个激活。因此,数据会变成稀疏的。

主要参考:https://www.cnblogs.com/zongfa/p/9305657.html
OneHotEncoder官方网址:OneHotEncoder

1. 为什么要使用独热编码

  使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。

  离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1。

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

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

2. 独热编码优缺点

  • 优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。
  • 缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。除此之外,可考虑二进制编码,其很好的解决的特征空间过大的问题,但可解释性不强。

3. 什么情况下(不)用独热编码

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

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

4. 什么情况下(不)需要对编码后的数据归一化

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

5. One Hot Encode 在sklearn中的实现

from sklearn.preprocessing import OneHotEncoder
import numpy as np

# Encode categorical integer features as a one hot numeric array.
print(OneHotEncoder.__doc__)

Parameters:

  • categories=‘aoto’: 每个特征使用几维的数值由数据集自动推断,即几种类别就使用几位来表示。也可以自己指定即categories=[2,3,4],表示对三个特征分别使用2,3,4维数组进行编码;
  • drop=None :用于从每个特征中舍去特定的分类,默认为None,且不能与categories、n_values同用;
  • dtype=np.float64 : 表示编码数值格式,默认是浮点型;
  • sparse=True : 表示编码的格式,默认为 True,即为稀疏的格式,指定 False 则就不用 toarray();
  • handle_unknown=’error’:其值可以指定为 “error” 或者 “ignore”,即如果碰到未知的类别,是返回一个错误还是忽略它;
  • categorical_features = 'all’:这个参数指定了对哪些特征进行编码,默认对所有类别都进行编码。也可以自己指定选择哪些特征,通过索引或者 bool 值来指定;

example:

from sklearn.preprocessing import  OneHotEncoder

enc = OneHotEncoder()
enc.fit([[0, 0, 3],
         [1, 1, 0],
         [0, 2, 1],
         [1, 0, 2]])

ans = enc.transform([[0, 1, 3]]).toarray() 
"""
 如果不加 toarray() 的话,输出的是稀疏的存储格式,即索引加值的形式,也可以通过参数指定 sparse = False 来达到同样的效果
"""
print(ans) 
#输出 [[ 1.  0.  0.  1.  0.  0.  0.  0.  1.]]

  对于输入数组,依旧是把每一行当作一个样本,每一列当作一个特征,第一个特征,即第一列 [0,1,0,1],也就是说它有两个取值 0 或者 1,那么 one-hot 就会使用两位来表示这个特征,[1,0] 表示 0, [0,1] 表示 1,在上例输出结果中的前两位 [1,0…] 也就是表示该特征为 0。

6. One Hot Encode 在Pandas中实现

pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False)

print(pd.get_dummies.__doc__)

二、标签编码

1.什么是Label encoding

  label encoding 就是用标签进行编码的意思,即将原始特征值编码为自定义的数字标签完成量化编码过程。

  例如,假如有三种颜色特征:红、黄、蓝。 在利用机器学习的算法时一般需要进行向量化或者数字化。那么你可能想令 红=1,黄=2,蓝=3. 那么这样其实实现了标签编码,即给不同类别以标签。

主要参考:http://t.csdn.cn/QehL6

2. 特点

  • 优点:解决了分类编码的问题,可以自由定义量化数字。但其实也是缺点,因为数值本身没有任何含义,只是排序。如大中小编码为123,也可以编码为321,即数值没有意义。
  • 缺点:可解释性比较差。比如有[dog,cat,dog,mouse,cat],我们把其转换为[1,2,1,3,2],这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。因此,Label encoding编码其实并没有很宽的应用场景。

三、如何区分两种编码?

1.特征数据类型

  对于定类类型的数据,建议使用one-hot encoding。 定类类型就是纯分类,不排序,没有逻辑关系。比如性别分男和女,男女不存在任何逻辑关系,我们不能说男就比女好,或者相反。再者,中国各省市分类也可以用独热编码,同样各省不存在逻辑关系,这时候使用one-hot encoding会合适些。但注意,【一般会舍去一个变量(最后一个)】,比如男的对立面肯定是女,那么女就是重复信息,所以保留其中一个变量即可。

  对于定序类型的数据,建议使用label encoding。 定序类型也是分类,但有排序逻辑关系,等级上高于定类。比如,学历分小学,初中,高中,本科,研究生,各个类别之间存在一定的逻辑,显然研究生学历是最高的,小学最低。这时候使用Label encoding会显得更合适,因为自定义的数字顺序可以不破坏原有逻辑,并与这个逻辑相对应。

2.所使用的模型

  对数值大小敏感的模型必须使用one-hotencoding。 典型的例子就是LRSVM。二者的损失函数对数值大小是敏感的,并且变量间的数值大小是有比较意义的。而Label encoding的数字编码没有数值大小的含义,只是一种排序,因此对于这些模型都使用one-hot encoding。

  对数值大小不敏感的模型(如树模型)不建议使用one-hotencoding。 一般这类模型为树模型。如果分类类别特别多,那么one-hot encoding会分裂出很多特征变量。这时候,如果我们限制了树模型的深度而不能向下分裂的话,一些特征变量可能就因为模型无法继续分裂而被舍弃损失掉了。因此,此种情况下可以考虑使用Label encoding。

以上两点考量需要综合考虑,而非单独判断。也就是说需要结合数据类型和模型的情况来具体选择编码方式。

3. Label在sklearn中的实现

from sklearn.preprocessing import LabelEncoder
print(LabelEncoder.__doc__)

# le = LabelEncoder()
# le.fit(["xx","yy"])
# le.classes_
# le.transform(["yy"])
# le.inverse_transform([1])

总结

  本文在数据编码部分仅介绍了主要的两种编码方式,其他的方式,例如二进制编码也经常使用,特征工程还包括缺失值处理、异常值处理、变量转化、特征筛选及降维,其中《特征工程系统综合指南》可查看【EDA与特征工程】数据探索与特征工程综合指南,《特征筛选及降维》可查看【特征工程】重要特征识别理论。

你可能感兴趣的:(特征工程,sklearn,python)