🔻 one-hot编码
独热编码即 One-Hot 编码,又称一位有效编码。其方法是使用N位状态寄存器来对 N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。
举例如下:
假设我们有四个样本(行),每个样本有三个特征(列),如下:
Feature_1 | Feature_2 | Feature_3 | |
---|---|---|---|
Sample_1 | 1 | 4 | 3 |
Sample_2 | 2 | 3 | 2 |
Sample_3 | 1 | 2 | 2 |
Sample_4 | 2 | 1 | 1 |
上述feature_1有两种可能的取值,比如是男/女,这里男用1表示,女用2表示。feature_2 和 feature_3 各有4种取值(状态)。
one-hot 编码就是保证每个样本中的单个特征只有1位处于状态1,其他的都是0。
上述状态用 one-hot 编码如下表所示:
Feature_1 | Feature_2 | Feature_3 | |
---|---|---|---|
Sample_1 | 0 1 | 1 0 0 0 | 1 0 0 |
Sample_2 | 1 0 | 0 1 0 0 | 0 1 0 |
Sample_3 | 0 1 | 0 0 1 0 | 0 1 0 |
Sample_4 | 1 0 | 0 0 0 1 | 0 0 1 |
具体一般使用方法B = pd.get_dummies(A)
实现。
这个方法其实意思为获得哑变量,但是它可以用于产生one-hot编码,也可以用于产生哑变量编码。
当drop_first=True时为哑变量编码,当为False时为one-hot编码。
🔻one-hot编码和哑变量编码的区别
那么哑变量编码是什么呢?我们可以从两者区别对比来看,如下:
Feature_1 | one-hot | dummy | |
---|---|---|---|
Sample_1 | 1 | 0 0 1 | 0 1 |
Sample_2 | 2 | 0 1 0 | 1 0 |
Sample_3 | 3 | 1 0 0 | 0 0 |
Sample_4 | 4 | 0 0 1 | 0 1 |
可以看出:
- 哑变量编码的生成的特征值比one-hot少一个,也就是比对应特征的种类取值要少1个;
- 哑变量编码中有(0,0)出现,即可以不出现1,而one-hot编码中每个区值对应的编码有且仅有一个是1。
哑变量编码的这些特征其实是对应的,因为生成的特征比原有的特征种类少一个,所以用(0,0)来表示sample3的feature1既不为1也不为2,默认feature1的值为3。
但是one-hot编码中的特征是二值性的,上述例子代表的意义是:feature1是否为3,feature1是否为2,feature1是否为1。
🔻哑变量编码的优势
哑变量编码其实比较聪明,因为这样的做法避免了多重共线性 (Multicollinearity)问题。
也就是说如果特征变量之间有相关性,模型将很难说出某个变量对目标的影响有多大。
比如说如上图所示,当gender特征变成gender_male和gender_female的时候,这两个特征之间其实是冗余的。因为我们如果gender_male=1,那么gender_female=0,反过来也一样。这个问题在数学中称为多重共线性,在pandas处理的时候有人也叫它虚拟变量陷阱(Dummy Variable Trap)。
对于两个变量以上的情况也一样:
🔻为什么可以用get_dummies(),drop_first=true代替one-hot编码
那么drop_first是什么呢?drop_first的意思是是否删除第一个类别,只保留其他类别的哑变量编码。一般情况下drop_first的默认值是false,也就是说直接把B = pd.get_dummies(A)这个方法当作one-hot编码使用是可行的。
具体看代码:
```#
# one-hot编码
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# 创建一个示例DataFrame
data = {'color': ['red', 'blue', 'green', 'red', 'blue']}
df = pd.DataFrame(data)
onehot = OneHotEncoder(sparse_output=False)
data_encoded = onehot.fit_transform(df[['color']])
print("one-hot编码结果如下:")
print(data_encoded)
print(type(data_encoded))
# 哑变量编码
# pd.get_dummies()方法即可以用于产生One-Hot编码,也可以用于产生哑变量编码
# 当drop_first=True时为哑变量编码,当为False时为One-Hot编码
data = pd.get_dummies(df['color'], drop_first=True)
print("哑变量编码结果如下:")
print(data)
print(type(data))
运行结果分别是:
当drop_first=True时,get_dummies()删除了例子中的第一个类别’blue’,保留了’green’和’red’ (第一个类别不是’red’,因为原始输出应该长这样:)
其中’red’是第一个样本,它的特征’red’为True;对于第二个样本’blue’,它的两个特征均为False,删去的’blue’为True…
当drop_first=False时,可以看到输出结果类似one-hot编码:
data_dummies2 = pd.get_dummies(df['color',drop_first=False])
print("当drop_first=False时,哑变量编码结果如下:")
print(data_dummies2)
print(type(data_dummies2))
所以get_dummies()方法本体就是one-hot编码,当drop_first=True时,回归了哑变量编码。
🔻如何取舍one-hot编码和哑变量编码
在实际的应用中,比如说模型
其中自变量满足
(模型是one-hot获得的,只有一个状态位为1,其余都为0),所以
,代入得
这两个参数是等价的。
为了解决模型的稳定性问题,可以采取三种手段:L2正则化、去除偏置项和使用哑变量代替one-hot编码。
1)L2正则化,给参数的选择加一个限制:选择参数元素值小的为最终参数,这样得到的参数就唯一,模型也就稳定了;
2)去除偏置项
,此时有
由于去除了偏置项,变成了两个模型,也就不存在参数等价的问题了。
3)在加上偏置项的前提下,使用哑变量代替one-hot编码,这时去除了
,也就不存在前面说的一种特征可以用其他特征表示的问题了。这种方法的好处是保留了固有属性,即偏置项。
🔻总结
当我们使用one-hot编码时,我们的模型不加bias项(或者加bias后用L2正则化约束参数);
当我们使用哑变量编码时,通常我们的模型都会加bias项,因为不加bias项会导致固有属性的丢失。
🔻参考
pandas的get_dummies方法在机器学习中的应用及其陷阱 | 数据学习者官方网站(Datalearner)
离散型特征编码方式:one-hot与哑变量* - ML小菜鸟 - 博客园 (cnblogs.com)
个人学习整理,欢迎大佬指正。
感谢看到这里的你,一起进步!🤞🤞