一句话概括:one hot编码是将类别变量转换为机器学习算法易于利用的一种形式的过程。
通过例子可能更容易理解这个概念。
假设我们有一个迷你数据集:
公司名 | 类别值 | 价格 |
---|---|---|
VW | 1 | 20000 |
Acura | 2 | 10011 |
Honda | 3 | 50000 |
Honda | 3 | 10000 |
其中,类别值是分配给数据集中条目的数值编号。比如,如果我们在数据集中新加入一个公司,那么我们会给这家公司一个新类别值4。当独特的条目增加时,类别值将成比例增加。
在上面的表格中,类别值从1开始,更符合日常生活中的习惯。实际项目中,类别值从0开始(因为大多数计算机系统计数),所以,如果有N个类别,类别值为0至N-1.
sklear的LabelEncoder可以帮我们完成这一类别值分配工作。
现在让我们继续讨论one hot编码,将以上数据集one hot编码后,我们得到的表示如下:
VW | Acura | Honda | 价格 |
---|---|---|---|
1 | 0 | 0 | 20000 |
0 | 1 | 0 | 10011 |
0 | 0 | 1 | 50000 |
0 | 0 | 1 | 10000 |
在我们继续之前,你可以想一下为什么不直接提供标签编码给模型训练就够了?为什么需要one hot编码?
标签编码的问题是它假定类别值越高,该类别更好。“等等,什么!”
让我解释一下:根据标签编码的类别值,我们的迷你数据集中VW > Acura > Honda。比方说,假设模型内部计算平均值(神经网络中有大量加权平均运算),那么1 + 3 = 4,4 / 2 = 2. 这意味着:VW和Honda平均一下是Acura。毫无疑问,这是一个糟糕的方案。该模型的预测会有大量误差。
我们使用one hot编码器对类别进行“二进制化”操作,然后将其作为模型训练的特征,原因正在于此。
当然,如果我们在设计网络的时候考虑到这点,对标签编码的类别值进行特别处理,那就没问题。不过,在大多数情况下,使用one hot编码是一个更简单直接的方案。
另外,如果原本的标签编码是有序的,那one hot编码就不合适了——会丢失顺序信息。
最后,我们用一个例子总结下本文:
假设“花”的特征可能的取值为daffodil
(水仙)、lily
(百合)、rose
(玫瑰)。one hot编码将其转换为三个特征:is_daffodil
、is_lily
、is_rose
,这些特征都是二进制的。
原文 What is One Hot Encoding? Why And When do you have to use it?
离散特征的编码分为两种情况:
1、离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码
2、离散特征的取值有大小的意义,比如size:[X,XL,XXL],那么就使用数值的映射{X:1,XL:2,XXL:3}
使用pandas可以很方便的对离散型特征进行one-hot编码
- import pandas as pd
- df = pd.DataFrame([
- ['green', 'M', 10.1, 'class1'],
- ['red', 'L', 13.5, 'class2'],
- ['blue', 'XL', 15.3, 'class1']])
- df.columns = ['color', 'size', 'prize', 'class label']
- size_mapping = {
- 'XL': 3,
- 'L': 2,
- 'M': 1}
- df['size'] = df['size'].map(size_mapping)
- class_mapping = {label:idx for idx,label in enumerate(set(df['class label']))}
- df['class label'] = df['class label'].map(class_mapping)
Using the get_dummies
will create a new column for every unique string in a certain column:使用get_dummies进行one-hot编码
- pd.get_dummies(df)