一. 常见的特征类型
我们在学习机器学习的时候,往往会遇到各色各样的数据集。在拿到数据集那一刻,我们应该仔细看看数据集的内部情况。每一个样本通常带有多个特征的,一般特征类型分为连续型特征和离散型特征,离散型特征又分为类别特征和数值特征,性别(男,女)就是典型的类别特征。 编码往往应对的就是类别特征,无论是连续型特征,还是离散数值型特征,都可以通过简单的归一化就送进机器学习模型当中去。然而对于类别特征,仅有少数的模型支持字符串形式的类别特征的处理,例如决策树。因此,我们需要针对不同的场合,采用合适的编码方式对类别特征进行数值化。
二、编码方式
我们在学习sklearn和参加kaggle竞赛的时候,常常遇见各种类型的数据,需要采取适合的方式去编码,接下来就讲解目前主要的编码方式。
2.1 独热编码
什么是独热编码?为什么使用独热编码?在什么时候使用?我们需要带着这些疑问进行学习。 One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。也就是说该离散型类别特征有N个不同的取值,就有N个状态,就用N位寄存器(N位二进制)来表示N个不同的值。每N个比特位表示的值只有一个是1,其余为0,其实就是以二进制的形式表示,主要用于特征内部取值是无序的,例如颜色(红,蓝,绿。 独热编码在机器学习中的应用实例如下:
from sklearn import preprocessing.OneHotEncoder
dem = OneHotEncoder()
dem.fit([[0,0,3],
[1,1,0],
[0,2,1],
[1,0,2]]) #这里一共有4个样本,3种特征
array = dem.transform([[0,1,3]]).toarray() #这里使用一个新的数据来测试
print(array) # [[ 1 0 0 1 0 0 0 0 1]]
从中我们可以看出,对于第一个特征(0,1,0,1),有2种不同取值,故用2位比特位表示取值,0用10,1用01表示。对于第二个特征(0,1,2,0),有3种不同取值,故用3位比特位表示取值,0用100,1用010,2用001表示。 在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。 而我们使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,确实会让特征之间的距离计算更加合理。 比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是x_1 = (1), x_2 = (2), x_3 = (3)。两个工作之间的距离是,(x_1, x_2) = 1, d(x_2, x_3) = 1, d(x_1, x_3) = 2。那么x_1和x_3工作之间就越不相似吗?显然这样的表示,计算出来的特征的距离是不合理。那如果使用one-hot编码,则得到x_1 = (1, 0, 0), x_2 = (0, 1, 0), x_3 = (0, 0, 1),那么两个工作之间的距离就都是sqrt(2).即每两个工作之间的距离是一样的,显得更合理。
2.2 标签编码
传统硬编码,即直接对类别特征进行了大量映射,有多少类别取值就代表了多少。这种硬编码方式简单粗暴,方便快捷。但其仅在类别特征内部取值是有序的情况才好使用。假设特征取值有n个不同值,即n个类别,那么将按照特征数据的大小将其编码成0-(n-1)之间的整数。 标签编码在机器学习中的应用如下:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(['undergraduate', 'master', 'PhD', 'Postdoc']) #相当于训练标签编码器,得到每一个类别值所对应的编码
le.transform(['undergraduate', 'master', 'PhD', 'Postdoc'])#将上面得到的标签编码器对输入数据进行编码
经过上述程序的运行,字符串被编码0-3的整数, ‘master’——>0,‘PhD’——>1, ‘Postdoc’——>2,‘undergraduate’——>3(按Ascil码从小到大进行编排)。相信到这里,大家就知道标签编码的运行规则。
2.3 序号编码
序号编码是处理一个数据集都是类别特征的编码方法,并且其类别特征内部取值是具有大小顺序的情况,因此该方法用的较少。 信号编码在机器学习中的应用如下:
import pandas as pd
from sklearn.preprocessing import OrdinalEncoder
categorical_df = pd.DataFrame({'stuent_id': ['101', '102', '103', '104'],
'name': ['Li', 'Huang', 'Ann', 'John'],
'ranking': ['third', 'second', 'first', 'second']})
print(categorical_df)
print('--'*20)
encoder = OrdinalEncoder() #创建OrdinalEncoder对象
encoder.fit(categorical_df) #将数据categorical_df载入encoder中
categorical_df = encoder.transform(categorical_df) #将载入的数据进行OrdinalEncoder
print(categorical_df)
从输出我们可以看到所有的特征内部取值被编码,这与标签编码类似。但要注意的是标签编码只对某个特征内部取值进行编码。
2.4 频数编码
频数编码就是将类别特征内部取值用该取值出现的频数替换,这就是所谓的频数编码,不过这种编码方式用得不多。 比如某个分类中’Peking’出现了10次,那么’Peking’就会被替换为10. 我们可以用 categorical-encodings包中的CountEncoder实现。
参考资料:[机器学习中常见的编码形式]
|