1. OneHot独热编码介绍
1.1 为什么要用One-hot编码?
在建模过程中,我们通常会碰到各种类型的属性,如果是标称型属性(非数值类型的属性),也就是不具备序列性、不能比较大小的属性,通常我们不能用简单的数值来粗暴替换。因为属性的数值大小会影响到权重矩阵的计算,不存在大小关系的属性,其权重也不应该发生相应的变化,那么我们就需要用到One-hot编码(也有人称独热编码)这种特殊的编码方式了。
1.2 One-hot举例
data = pd.DataFrame([ [ 'M', 10.1], [ 'L', 13.5], [ 'XL', 15.3], [ 'XL', 16.3]])
One-hot编码后变为:
data = array([[0, 1, 0, 10.1],
[1, 0, 0, 13.5],
[0, 0, 1, 15.3],
[0, 0, 1, 16.3]])
1.3 One-hot使用范围
one-hot通常用在GBDT、XGBoost这些模型里面都挺好的,但是用在逻辑回归里不行。因为逻辑回归要求变量间相互独立,如果你只有一个属性需要做one-hot编码还好,如果你有多个属性需要做one-ont编码,那么当某个样本的多个one-hot属性同时为1时,这两个属性就完全相关了,必然会导致singular error,也就是非奇异矩阵不能求解唯一解,得不出唯一的模型,但是你又不可能把同一个属性的某一个one-hot延伸变量删除。
如果在逻辑回归中入模标称属性,可以直接替换成数值,然后做woe变换,用每个类别的woe值来代替原来的数值,这样既能够避免生成相关性强的变量,又能避开类别间大小无法比较的问题。
创建基础数据
import pandas as pd import numpy as np
data = pd.DataFrame([ ['yellow', 'M', 10.1, 'class1'], ['red', 'L', 13.5, 'class2'], ['blue', 'XL', 15.3, 'class1'], ['green', 'XL', 16.3, 'class3']]) data.columns = ['颜色', '大小', '价格', '类别标签'] data
2. sklearn机器学习中Onehot编码方式
2.1 将分类特征进行数字编码—LabelEncoder将分类特征数字化
from sklearn.preprocessing import LabelEncoder encoder = LabelEncoder() category = encoder.fit_transform(data['颜色']) print("颜色编码:",category) print("编码对应的颜色:",encoder.classes_)
颜色编码: [3 2 0 1] 编码对应的颜色: ['blue' 'green' 'red' 'yellow']
但是LabelEncoder一次只能处理一个属性,因此需要使用循环分别对属性进行处理
columns = ['颜色','大小','类别标签'] data2 = data.copy() for column in columns: data2[column] = encoder.fit_transform(data[column]) print("{}编码顺序:{}".format(column, encoder.classes_)) data2
颜色编码顺序:['blue' 'green' 'red' 'yellow'] 大小编码顺序:['L' 'M' 'XL'] 类别标签编码顺序:['class1' 'class2' 'class3']
2.2 Onehot编码方法一:LabelEncoder后使用OneHotEncoder
from sklearn.preprocessing import OneHotEncoder columns = ['颜色','大小','类别标签'] enc = OneHotEncoder() # 将['颜色','大小','类别标签']这3列进行独热编码 enc.fit_transform(data2[columns]).toarray()
array([[0., 0., 0., 1., 0., 1., 0., 1., 0., 0.], [0., 0., 1., 0., 1., 0., 0., 0., 1., 0.], [1., 0., 0., 0., 0., 0., 1., 1., 0., 0.], [0., 1., 0., 0., 0., 0., 1., 0., 0., 1.]])
2.3 Onehot编码方法二:直接对文本使用LabelBinarizer
LabelBinarizer 每次也只能对一个特征进行独热编码,需要使用循环对每个特征进行编码
from sklearn.preprocessing import LabelBinarizer enc = LabelBinarizer() transform_data = enc.fit_transform(data['颜色']) transform_data
array([[0, 0, 0, 1], [0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0]])
transform_data = enc.fit_transform(data['大小']) transform_data
array([[0, 1, 0], [1, 0, 0], [0, 0, 1], [0, 0, 1]])
2.4 Onehot编码方法三:DictVectorizer
from sklearn.feature_extraction import DictVectorizer dict = DictVectorizer(sparse=False) dict_data= dict.fit_transform(data.to_dict(orient="records")) dict_data
array([[10.1, 0. , 1. , 0. , 1. , 0. , 0. , 0. , 0. , 0. , 1. ], [13.5, 1. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 1. , 0. ], [15.3, 0. , 0. , 1. , 1. , 0. , 0. , 1. , 0. , 0. , 0. ], [16.3, 0. , 0. , 1. , 0. , 0. , 1. , 0. , 1. , 0. , 0. ]])
# 查看各列标签名称 dict.get_feature_names()
['价格', '大小=L', '大小=M', '大小=XL', '类别标签=class1', '类别标签=class2', '类别标签=class3', '颜色=blue', '颜色=green', '颜色=red', '颜色=yellow']
3. Pandas中Onehot编码方式
3.1 Pandas将分类特征进行数字编码方式–pd.factorize()
data_category, data_class = pd.factorize(data['大小']) print(data_category) print(data_class)
[0 1 2 2] Index(['M', 'L', 'XL'], dtype='object')
3.2 Onehot编码–pd.get_dummies()
data_oneHot = pd.get_dummies(data) • 1
data_oneHot
4. 总结
综合上述方法:
个人认为下面两种方式转化为One_hot类型特征最方便:
- sklearn中使用DictVectorizer
- Pandas中使用pd.get_dummies