用来对离散的类型特征进行编码,如,不连续的数值、文本,将离散的特征转换成连续的数值型变量。基于索引的编码可以起到数据归一化的作用,如,id为1和10000,当id作为LR的特征时,id为1的用户和id为10000的用户基本属性一样,但LR算法中10000权重过大,会导致id=1的特征基本不起作用,必须进行归一化,类似特征都应单独进行归一化。
如特征A取值共有9种情况,如,[1, 200, 10000, 30000, 100000],则索引编码后为[0, 1, 2, 3, 4]。
代码示例:
from sklearn.preprocessing import LabelEncoder
a = [1, 200, 10000, 30000, 100000]
label_coder = LabelEncoder()
label_coder.fit(a)
b = label_coder.transform(a)
print(b)
OneHot编码也叫独热编码或哑编码,可以解决某些分类器不好处理离散属性数据的问题,在一定长度上也起到了对特征进行扩充的作用。
大部分算法是基于向量空间中的距离度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到圆点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1。
为什么特征向量要映射到欧式空间?
在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,如,计算余弦相似性,就是基于欧式空间。
代码示例:
from sklearn.preprocessing import OneHotEncoder
onehot_coder = OneHotEncoder()
onehot_coder.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
c = onehot_coder.transform([[0, 0, 3]])
print(c.toarray())
优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。
缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。
用
用于类别型数据的离散值。
不用
让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码。 有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是个类别符号,即没有偏序关系,所以不用进行独热编码。 Tree Model不太需要one-hot编码: 对于决策树来说,one-hot的本质是增加树的深度。
总的来说,要是oneHot encoding的类别数目不太多,即升维不大,建议优先考虑。
需要
基于参数的模型或基于距离的模型,都是要进行特征的归一化。
不需要
基于树的方法不需要进行特征的归一化,例如随机森林,bagging 和 boosting等。
顾名思义,Multiple编码特征将多个属性同时编码到一个特征中。在推荐场景中,单个用户对哪些物品感兴趣的特征就是一种Multiple编码特征,如,表示某用户对产品1、产品2、产品3、产品4是否感兴趣,则这个特征可能有多个取值,如用户A对产品1和产品2感兴趣,用户B对产品1和产品4感兴趣,用户C对产品1、产品3和产品4感兴趣,则用户兴趣特征为
用户 | UserInterests |
---|---|
A | [1, 2] |
B | [1, 4] |
C | [1, 3, 4] |
Multiple编码采用类似oneHot编码的形式进行编码,根据物品种类数目,展成物品种类数目大小的向量,当某个用户感兴趣时,对应维度为1,反之为0,如下
用户 | UserInterests |
---|---|
A | [1, 1, 0, 0] |
B | [1, 0, 0, 1] |
C | [1, 0, 1, 1] |
代码示例:
from sklearn.preprocessing import LabelEncoder
d = [[1, 2], [1, 4], [1, 3, 4]] // 原始特征
e = set()
for i in d: // 求d中所有物品类别
for j in i:
e.add(j)
// 对d中物品进行Index编码
label_coder = LabelEncoder()
label_coder.fit(list(e))
// 特征[1, 2]进行编码
f = [0]*len(e)
for i in label_coder2.transform([1, 2]):
f[i] = 1
print(f)
//[1, 2] 转换后为 [1, 1, 0, 0]
我们将多个属性同时编码到同一个特征中,目的就是同时利用多个属性的特征。经过Multiple编码后的特征大小为[batch_size, num_items],记作U,构建物品items的Embedding矩阵,该矩阵维度为[num_items, embedding_size],记作V,将矩阵U和矩阵V相乘,我们就得到了大小为[batch_size, embedding_size]的多属性表示。
上述过程实现了多维多属性特征的构建,该手段在深度学习特征工程中被广泛应用。
以下通过应用场景对以上3种编码方式进行比较:
当离散型特征的方差较大,即相似特征取值差异较大时,需要进行归一化,可采用Index编码;
当所使用的算法基于空间向量时,需要进一步对特征进行oneHot编码,需要注意避免维度爆炸,当维度较大时应考虑采用降维方法,如PCA;
当需要对特征进行多维编码时,可采用Multiple编码,多维度多属性特征的构建可以在此基础上增加Embedding的特征得到;