数据编码是特征工程中重要的一步,特征工程还包括缺失值处理、异常值处理、变量转化、特征筛选及降维,其中《特征工程系统综合指南》可查看【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
使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。
离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1。
为什么特征向量要映射到欧式空间?
将离散特征通过one-hot编码映射到欧式空间,是因为在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。
总的来说,要是one hot encoding的类别数目不太多,建议优先考虑。
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# Encode categorical integer features as a one hot numeric array.
print(OneHotEncoder.__doc__)
Parameters:
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。
pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False)
print(pd.get_dummies.__doc__)
label encoding 就是用标签进行编码的意思,即将原始特征值编码为自定义的数字标签完成量化编码过程。
例如,假如有三种颜色特征:红、黄、蓝。 在利用机器学习的算法时一般需要进行向量化或者数字化。那么你可能想令 红=1,黄=2,蓝=3. 那么这样其实实现了标签编码,即给不同类别以标签。
主要参考:http://t.csdn.cn/QehL6
对于定类类型的数据,建议使用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。
以上两点考量需要综合考虑,而非单独判断。也就是说需要结合数据类型和模型的情况来具体选择编码方式。
from sklearn.preprocessing import LabelEncoder
print(LabelEncoder.__doc__)
# le = LabelEncoder()
# le.fit(["xx","yy"])
# le.classes_
# le.transform(["yy"])
# le.inverse_transform([1])
本文在数据编码部分仅介绍了主要的两种编码方式,其他的方式,例如二进制编码也经常使用,特征工程还包括缺失值处理、异常值处理、变量转化、特征筛选及降维,其中《特征工程系统综合指南》可查看【EDA与特征工程】数据探索与特征工程综合指南,《特征筛选及降维》可查看【特征工程】重要特征识别理论。