one-hot编码

为了防止将编号0到17的特征认为是连续型的特征,即认为1和2相似,4和10不同,但其实这是没有意义的,对于两个特征,要么它是一个特征,要么不同,没有中间状态。

为了消除这种和实际情况不一致 的现象,使用OneHotEncode编码把这些整数转化为二进制。每个特征用一个二进制数字来表示。例如,特征A分配的数值为7,那么one-hot编码为它分配的二进制数字的第七位就是1,其余位为0.


在实际的应用场景中,有非常多的特征不是连续的数值变量,而是某一些离散的类别。比如在广告系统中,用户的性别,用户的地址,用户的兴趣爱好等等一系列特征,都是一些分类值。这些特征一般都无法直接应用在需要进行数值型计算的算法里,比如CTR预估中最常用的LR。那针对这种情况最简单的处理方式是将不同的类别映射为一个整数,比如男性是0号特征,女性为1号特征。这种方式最大的优点就是简单粗暴,实现简单。那最大的问题就是在这种处理方式中,各种类别的特征都被看成是有序的,这显然是非常不符合实际场景的。

例如,考虑一下的三个特征:

["male", "female"]

["from Europe", "from US", "from Asia"]

["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]

如果将上述特征用数字表示,效率会高很多。例如:

["male", "from US", "uses Internet Explorer"] 表示为[0, 1, 3]

["female", "from Asia", "uses Chrome"]表示为[1, 2, 1]

但是,即使转化为数字表示后,上述数据也不能直接用在我们的分类器中。因为,分类器往往默认数据数据是连续的,并且是有序的。但是,按照我们上述的表示,数字并不是有序的,而是随机分配的。


one hot编码的优点: 
1.能够处理非连续型数值特征。 
2.在一定程度上也扩充了特征。比如性别本身是一个特征,经过one hot编码以后,就变成了男或女两个特征。

注意:此处一定将训练特征和测试特征一起转化,因为转化之后数组的维度将会发生变化,有一个不转化,就会出错。

enc.fit(train_feature) 
train_feature = enc.transform(train_feature).toarray() 
test_feature = enc.transform(test_feature).toarray()

首先上一段sklearn的自带例子:

  1. # one-hot编码过程  

import numpy as np
from sklearn.preprocessing import OneHotEncoder

enc = OneHotEncoder()
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1],[1, 0, 2]])
print "enc.n_values_ is:",enc.n_values_
print "enc.feature_indices_ is:",enc.feature_indices_
print enc.transform([[0, 1, 1]]).toarray()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码运行结果

enc.n_values_ is: [2 3 4]
enc.feature_indices_ is: [0 2 5 9]
[[ 1.  0.  0.  1.  0.  0.  1.  0.  0.]]

categorical_features:代表类别属性的索引数值,注意:类别属性尽量处理为从0开始的整数,像(0,1,2,3,4,5)

n_values_:是一个数组,代表categorical_features中每个属性含有多少个类别。

具体到代码里,[[0, 0, 3], [1, 1, 0], [0, 2, 1],[1, 0, 2]]是我们的样本矩阵,[0, 0, 3]是一个样本,每个样本有三维,即三类特征。

对于第一维或者说第一类特征,有0,1两种取值;第二类特征,有0,1,2两类特征;第三类特征,有0,1,2,3三类特征,所以

enc.n_values_ is: [2 3 4]
  • 1
  • 1

feature_indices_:根据说明,明显可以看出其是对n_values的一个累加。 

enc.feature_indices_ is: [0259]

最后enc.transform([[0, 1, 1]]).toarray(),就是将[0,1,1]这个输入样本,用one-hot编码出来的结果[[ 1. 0. 0. 1. 0. 0. 1. 0. 0.]]

有如下三个特征属性:
  • 性别:["male","female"]
  • 地区:["Europe","US","Asia"]
  • 浏览器:["Firefox","Chrome","Safari","Internet Explorer"]
对于上述的问题,性别的属性是二维的,同理,地区是三维的,浏览器则是三维的,这样,我们可以采用One-Hot编码的方式对上述的样本“["male","US","Internet Explorer"]”编码,“male”则对应着[1,0],同理“US”对应着[0,1,0],“Internet Explorer”对应着[0,0,0,1]。则完整的特征数字化的结果为:[1,0,0,1,0,0,0,0,1]。这样导致的一个结果就是数据会变得非常的稀疏。

将编码后的写入文本文件

  1. # 如何将data_hoted(数组形式)写入文本  
  2. num_rows, num_cols = shape(data_hoted)  
  3. print '写入文本'  
  4. f = open("G:/one_hoted.txt""w")  
  5. for i in range(num_rows):  
  6.         print >>f, data_hoted[i,:]  
  7. f.close()  
  8. print '写入文本完成'  


没有更多推荐了,返回首页