【机器学习】onehot编码的各种实现

  • 对于定类类型的数据,建议使用one-hot encoding。定类类型就是纯分类,不排序,没有逻辑关系。比如性别分男和女,男女不存在任何逻辑关系,我们不能说男就比女好,或者相反。再者,中国各省市分类也可以用独热编码,同样各省不存在逻辑关系,这时候使用one-hot encoding会合适些。但注意,一般会舍去一个变量,比如男的对立面肯定是女,那么女就是重复信息,所以保留其中一个变量即可。
  • 对于定序类型的数据,建议使用label encoding。定序类型也是分类,但有排序逻辑关系,等级上高于定类。比如,学历分小学,初中,高中,本科,研究生,各个类别之间存在一定的逻辑,显然研究生学历是最高的,小学最低。这时候使用Label encoding会显得更合适,因为自定义的数字顺序可以不破坏原有逻辑,并与这个逻辑相对应。
  • 数值大小敏感的模型必须使用one-hot encoding或者Dummy。典型的例子就是LR和SVM。二者的损失函数对数值大小是敏感的,并且变量间的数值大小是有比较意义的。而Label encoding的数字编码没有数值大小的含义,只是一种排序,因此对于这些模型都使用one-hot encoding。
  • 对数值大小不敏感的模型(如树模型)不建议使用one-hot encoding。一般这类模型为树模型。如果分类类别特别多,那么one-hot encoding会分裂出很多特征变量。这时候,如果我们限制了树模型的深度而不能向下分裂的话,一些特征变量可能就因为模型无法继续分裂而被舍弃损失掉了。因此,此种情况下可以考虑使用Label encoding

目录

one-hot编码vs哑变量dummy编码

from sklearn.preprocessing import OneHotEncoder

1. 将标签处理成二进制(one-hot)

2. 多标签分类

from sklearn import preprocessing import LabelEncoder

如何保存下来呢?

Pytorch实现

torch.scatter

torch.nn.functional.one_hot

连续值的离散化为什么会提升模型的非线性能力?


one-hot编码vs哑变量dummy编码

其实是不一样的,之前总以为是一样的。

关于Onehot编码的总结_AI浩的博客-CSDN博客_onehot编码

one-hot编码和哑变量(dummy)编码_Sun_Sherry的博客-CSDN博客_哑变量编码

这两种编码的区别和联系

  • One-Hot编码和哑变量编码都只能对离散型变量进行编码。
  • One-Hot编码之后生成的新特征数等于对应特征的不同种类取值个数,feature1中共有3种不同的取值,One-Hot编码之后生成的新特征数就是3。而哑变量编码之后生成的新特征数比对应特征的取值个数少1个。
  • One-Hot编码之所以叫One-Hot编码,是因为每个取值对应的编码中有且只有一个是1,其余都是0。而哑变量编码允许不出现1。
  • One-Hot编码形成的新特征都是二值型特征,比如,上述One-Hot编码形成的三个新维度的意义为:feature1是否为3,feature1是否为2,feature1是否为1;哑变量编码在这一点上与One-Hot类似,只不过当编码全为0是表示 feature1既不是1也不是2,这种情况下默认feature1为3。
  • 离散型特征编码方式:one-hot与哑变量* - ML小菜鸟 - 博客园
  • 总结:我们使用one-hot编码时,通常我们的模型不加bias项 或者 加上bias项然后使用
    L2 正则化手段去约束参数;当我们使用哑变量编码时,通常我们的模型都会加bias项,因为不加bias项会导致固有属性的丢失

    选择建议:我感觉最好是选择正则化 + one-hot编码;哑变量编码也可以使用,不过最好选择前者。虽然哑变量可以去除one-hot编码的冗余信息,但是因为每个离散型特征各个取值的地位都是对等的,随意取舍未免来的太随意。

df = pd.DataFrame([  
            ['green' , 'A'],   
            ['red'   , 'B'],   
            ['blue'  , 'A']])  
df.columns = ['color',  'class'] 


df

 onehot编码

#one-hot编码
from sklearn.preprocessing import OneHotEncoder

onehot=OneHotEncoder(sparse=False)
data=onehot.fit_transform(df[['color']])

print("one-hot编码结果如下:")
print(data)
print(type(data))


one-hot编码结果如下:
[[0. 1. 0.]
 [0. 0. 1.]
 [1. 0. 0.]]
<class 'numpy.ndarray'>

哑变量编码

pd.get_dummies()方法即可以用于产生One-Hot编码,也可以用于产生哑变量编码。当drop_first=True时为哑变量编码,当为False时为One-Hot编码。

# 哑变量编码
# 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))



哑变量编码结果如下:
   green   red
0      1    0
1      0    1
2      0    0
<class 'pandas.core.frame.DataFrame'>

from sklearn.preprocessing import OneHotEncoder

【机器学习】OneHotEncoder编码固定长度_littlemichelle的博客-CSDN博客  处理拟合阶段没有见过的类别。

from sklearn.preprocessing import LabelBinarizer

sklearn处理标签问题

1. 将标签处理成二进制(one-hot)

导入库:from sklearn.preprocessing import label_binarize

参数:

  1. y:标签(你需要转化的标签);
  2. classes:这些标签的集合(不重复,比如10分类时,这10中类别的集合);
  3. neg_label:当为负类时将被编码的数字。默认为“0”;
  4. pos_label:当为正类时将被编码为的数字。默认为1;
from sklearn.preprocessing import label_binarize

label_binarize([1, 6], classes=[1, 2, 4, 6])
# array([[1, 0, 0, 0],[0, 0, 0, 1]])

label_binarize([1, 6], classes=[1, 2, 4, 6],neg_label=2,pos_label=3) #可以体会一下neg_label,pos_label
# array([[3, 2, 2, 2],[2, 2, 2, 3]])



label_binarize(['yes', 'no', 'no', 'yes'], classes=['no', 'yes'])
# array([[1], [0], [0], [1]])

二进制标签逆转例子

from sklearn. preprocessing import LabelBinarizer #导入库

all_label = ['yes', 'no', 'no', 'yes'] #所有的标签
LB = LabelBinarizer() #实例化
LB.fit(All_label) #把标签全送进LB中

Y=np.array([[0],[1]]) #要逆转的标签
LB.inverse_transform(Y,threshold=0.5) # 这里有个阈值参数,因为在神经网络的最后一层每个神经元输出的值肯定是个小数,要把小数进行二值化就得有个阈值。

# array(['no', 'yes'], dtype='<U3')

这个类虽然好用,但是有个问题。当我们面对的是一个未知的数据集时,我们可能不知道这个数据集需要分成几类。

from sklearn.preprocessing import LabelBinarizer

主要方法有三个:

  1. fit:把数据集的所有标签全都送进这个方法;
  2. classes:可以返回整个数据集有多少个类别;
  3. transform:将标签转化为one-hot格式;
from sklearn. preprocessing import LabelBinarizer # 导入库
LB = LabelBinarizer() # 实例化
All_label = [1,1,1,1,1,2,5,8,8,4,25,6,8,4] # 数据集中的所有标签
LB.fit(All_label) # 把标签全送进LB中

LB.classes_ # 返回数据集中有哪些标签
# array([ 1, 2, 4, 5, 6, 8, 25])

LB.transform([1,4,6,25]) # 转化标签为二进制
# onehot结果
array([[1, 0, 0, 0, 0, 0, 0],
        [0, 0, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0, 0, 1]])

2. 多标签分类

from sklearn.preprocessing import MultiLabelBinarizer # 导入类

MLB = MultiLabelBinarizer() #实例化类
all_label = [[1,2,3],[1,],[2,3]] #所有的标签
MLB.fit(all_label) #把标签送进MLB中

MLB.classes_ #查看标签的种类
# array([1, 2, 3])


MLB.transform([[1,3],[2,],[3,]]) # 转化标签为二进制
# array([[1, 0, 1],
#        [0, 1, 0],
#        [0, 0, 1]])

多标签分类的逆转示例

from sklearn.preprocessing import MultiLabelBinarizer # 导入库、
MLB = MultiLabelBinarizer() #实例化

all_label=[['猫','狗','鼠'],['猫','狗'],['鼠']] #所有的标签

MLB.fit(all_label) #把标签全送进MLB中

Y=np.array([[1,1,0],[1,1,1]]) #要逆转的标签

MLB.inverse_transform(Y)
# [('狗', '猫'), ('狗', '猫', '鼠')]

from sklearn import preprocessing import LabelEncoder

将标签值统一转换成 range(0,标签值个数)范围内 数值。

from sklearn.preprocessing import LabelEncoder
# 将标签值统一转换成 range(0,标签值个数)范围内 数值

le = LabelEncoder()  
# 编码
le.fit(["苹果", "香蕉", "西瓜", "葡萄"]) # LabelEncoder()
# 标签个数
le.classes_
# array(['苹果', '葡萄', '西瓜', '香蕉'], dtype='<U2')


# 标签值标准化
le.transform(["苹果", "苹果", "葡萄"])
# array([0, 0, 1])
le.transform(["西瓜", "西瓜", "香蕉"])
# array([2, 2, 3])


# 标准化标签值反转
le.inverse_transform([2, 2, 1])
# le.inverse_transform([2, 2, 1])
array(['西瓜', '西瓜', '葡萄'], dtype='<U2')

处理pandas dataframe

## pandas dataframes

data = pd.DataFrame({'name':['joe','john','bob','kevin'],
           'age':[10,20,30,10],
           'sex':['male','male','female','male']})
# data

 查看一下类型

data['name']
0    1
1    2
2    0
3    3
Name: name, dtype: int64


type(data['name'])
pandas.core.series.Series

开始编码

# 创建 LabelEncoder 对象
le = LabelEncoder()
# 调用fit方法开始离散化
data['name'] = le.fit_transform(data['name'])   
data['age'] = le.fit_transform(data['age'])
data['sex'] = le.fit_transform(data['sex']) 


data

 

如何保存下来呢?

Pytorch实现

torch.scatter

torch.Tensor — PyTorch master documentation

torch.nn.functional.one_hot

详见:one-hot编码 - image processing

连续值的离散化为什么会提升模型的非线性能力?

简单的说,使用连续变量的LR模型,模型表示为公式(1),而使用了one-hot或哑变量编码后的模型表示为公式(2)

 式中X1表示连续型特征,\theta _1\theta _2\theta _3 分别是离散化后在使用one-hot或哑变量编码后的若干个特征表示。这时我们发现使用连续值的LR模型用一个权值去管理该特征,而one-hot后有三个权值管理了这个特征,这样使得参数管理的更加精细,所以这样拓展了LR模型的非线性能力。

  这样做除了增强了模型的非线性能力外,还有什么好处呢?这样做了我们至少不用再去对变量进行归一化,也可以加速参数的更新速度;再者使得一个很大权值管理一个特征,拆分成了许多小的权值管理这个特征多个表示,这样做降低了特征值扰动对模型为稳定性影响,也降低了异常数据对模型的影响,进而使得模型具有更好的鲁棒性

 

参考:

关于Onehot编码的总结_AI浩的博客-CSDN博客_onehot编码

one-hot编码 - image processing

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值