原文链接:https://blog.csdn.net/randompeople/article/details/83244766
one-hot向量定义
作用:将类别变量转换为机器学习算法易于利用的一种形式。
代表:一项属性的特征向量,也就是同一时间只有一个激活点(不为0),这个向量只有一个特征是不为0的,其他都是0,特别稀疏。
例:一个特征“性别”,性别有“男性”、“女性”,这个特征有两个特征值,也只有两个特征值。
如果这个特征进行one-hot编码,则特征值为“男性”的编码为“10”,“女性”的编码为“01”。
如果特征值有m个离散特征值,则one-hot后特征值的表示是一个m维的向量,每个样本的特征只能有一个值,这个值的向量坐标上就是1,其他都是0。
如果有多个特征“性别”和“尺码”。“尺码”:M、L、XL三个值。
我们用“01”表示男性,M为“100”,L为“010”,XL为“001”,所以一个样本,【“男性”、“L”】 one-hot编码为[10 010],一个样本也就是5维的向量,这就是one-hot形式。
one-hot向量表示
长度根据特征的所有离散特征值决定,所有特征的离散特征值数目相加,一般比特征数目还多,具体的场景特征数目不一样。
from sklearn.preprocessing import OneHotEncoder
import numpy as np
enc = OneHotEncoder(categories='auto', sparse=False)
'''可以自动识别分类变量的取值范围,我们希望得到的编码结果是一个密集数组'''
enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
'''拟合了一个包含四个样本的数据集'''
print("enc.n_values_ is:", enc.categories_)
'''它包含了每个特征的分类变量的取值范围'''
print("enc.feature_indices_ is:", enc.get_feature_names_out())
'''表明每个特征在one-hot向量中的坐标范围,0-2 是第一个特征,2-5是第二个,5-9是第三个'''
print(enc.transform([[0, 1, 1]]))
print(enc.transform([[1, 1, 1]]))
print(enc.transform([[1, 2, 1]]))
'''对新的样本数据进行编码,并打印了编码结果'''
代码结果:
enc.n_values_ is: [2 3 4]
enc.feature_indices_ is: [0 2 5 9] #特征坐标
[[1. 0. 0. 1. 0. 0. 1. 0. 0.]]
[[0. 1. 0. 1. 0. 0. 1. 0. 0.]]
one-hot 优点缺点
1. 优点
能够处理非连续型数值特征,也就是离散值。
在一定程度上也扩充了特征。比如性别本身是一个特征,经过one hot编码以后,就变成了男或女两个特征,将离散特征通过one-hot编码映射到欧式空间,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。
将离散型特征使用one-hot编码,可以会让特征之间的距离计算更加合理。比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是。两个工作之间的距离是
。那么
和
工作之间就越不相似吗?显然这样的表示,计算出来的特征的距离是不合理。那如果使用one-hot编码,则得到
,那么两个工作之间的距离就都是
.即每两个工作之间的距离是一样的,显得更合理。
2. 缺点
如果原本的标签编码是有序的,那one hot编码就不合适了——会丢失顺序信息。
如果特征的特征值数目特别多,特征向量就会非常大,且非常稀疏。
实际应用场景
在自然语言领域,可以将文本分词。
分词后的所有单词作为一个总体的特征数目,进行one-hot编码,其中每一个单词就是一个one-hot向量
然后文本中每个句子也同样分词,分词后将这些单词作为一个句子的表示方式,这样一个句子就是一个二维向量,向量的行数是这个句子包含的单词总数,如此还可以用one-hot向量组成表示为文章。