1 为什么需要独热编码?
直接上案例,一份数据,特征为["颜色", "尺码", "喜欢度", "类别"],具体数据为[['green','M', 10.1,'class1'], ['red','L', 13.5,'class2'], ['blue','XL', 15.3,'class1']]。
这几项中,喜欢度直接是数值型,不用管。类别是label,先不说。对于颜色与尺码这两项,应该如何编码?
先说尺码,尺码的编码形式应该是{"M": 1, "L": 2, "XL": 3},直接转换成数字的形式。那么颜色这一项是否可行?直接将颜色字段编码为{"green":1, "red": 2, "blue": 3},这样似乎否可行?
先上结论,这样不行。我们在模型训练的时候,会对特征做什么?无非就是计算距离。那现在计算green,red,blue三个的距离。d(green, red)=2-1=1,d(red, blue)=3-2=1,d(green, blue)= 3-1=2。问题来了,这几个颜色之间的差距,应该是一样的。都是不同的颜色,不应该映射到欧氏空间,距离不等。这就是这种编码的问题所在。颜色这个离散特征之间没有大小的意义,应该使用独热编码。
那么型号这个字段可以吗?回答是可以的。同样计算距离。d(M,L)=2-1=1,d(L, XL)=3-2=1,d(M,XL)=3-1=2。XL是真的比M大两号的。当离散特征的取值有大小的意义,就应该使用这种数值映射。
2 独热编码现成的包
现成的包有不少,我就说一个,这个简单,能用就行了。pandas自带了独热编码的方法,get_dummies()。用起来很简单。还是以上边的例子。
import pandas as pd
data = pd.DataFrame([['green', 'M', 10.1, 'class1'], ['red', 'L', 13.5, 'class2'], ['blue', 'XL', 15.3, 'class1']])
data.columns = ['color', 'size', 'prize', 'class label']
size_d = {"M": 1, "L": 2, "XL": 3}
data["size"] = data["size"].map(size_d )
lable = {"class1": 1, "class2": 2}
data["class label"] = data["class label"].map(lable)
df = pd.get_dummies(data)
df.head()
size prize class label color_blue color_green color_red
0 1 10.1 1 0 1 0
1 2 13.5 2 0 0 1
2 3 15.3 1 1 0 0
3 独热编码的优缺点
优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。
缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且one hot encoding+PCA这种组合在实际中也非常有用。