机器学习 LabelEncoding OnehotEncoding

终于看到一篇靠谱的文章:link

Label encoding

就是采用类似字典的思想,将类别变量的每个取值对应一个整数。
在python中的实现主要有两种方法:

  1. sklearn中preprocessing库的LabelEncoder类。
  2. pandas中的factorize()函数/方法。

1.LabelEncoder类

sklearn.preprocessing.LabelEncoder
常用方法:
fit(y) :fit可看做一本空字典,y可看作要塞到字典中的词。
fit_transform(y):相当于先进行fit再进行transform,即把y塞到字典中去以后再进行transform得到索引值。
inverse_transform(y):根据索引值y获得原始数据。
transform(y) :将y转变成索引值。

使用kaggle钻石数据集进行测试:

le = LabelEncoder()
le_cut = le.fit_transform(diamonds_data['cut'])
print(le.classes_)
print(le_cut)
['Fair' 'Good' 'Ideal' 'Premium' 'Very Good']
[2 3 1 ... 4 3 2]

多列数据进行编码:

le = LabelEncoder()
list_to_encode = ['cut', 'color', 'clarity']

for col in list_to_encode:
    diamonds_data[col] = le.fit_transform(diamonds_data[col])
    print(col + ":")
    print(le.classes_)
print(diamonds_data)
cut:
['Fair' 'Good' 'Ideal' 'Premium' 'Very Good']
color:
['D' 'E' 'F' 'G' 'H' 'I' 'J']
clarity:
['I1' 'IF' 'SI1' 'SI2' 'VS1' 'VS2' 'VVS1' 'VVS2']
       carat  cut  color  clarity  depth  table  price     x     y     z
1       0.23    2      1        3   61.5   55.0    326  3.95  3.98  2.43
2       0.21    3      1        2   59.8   61.0    326  3.89  3.84  2.31
3       0.23    1      1        4   56.9   65.0    327  4.05  4.07  2.31
4       0.29    3      5        5   62.4   58.0    334  4.20  4.23  2.63
5       0.31    1      6        3   63.3   58.0    335  4.34  4.35  2.75
...      ...  ...    ...      ...    ...    ...    ...   ...   ...   ...
53936   0.72    2      0        2   60.8   57.0   2757  5.75  5.76  3.50
53937   0.72    1      0        2   63.1   55.0   2757  5.69  5.75  3.61
53938   0.70    4      0        2   62.8   60.0   2757  5.66  5.68  3.56
53939   0.86    3      4        3   61.0   58.0   2757  6.15  6.12  3.74
53940   0.75    2      0        3   62.2   55.0   2757  5.83  5.87  3.64

2.pandas中的factorize()函数/方法

pandas.factorize(values, sort=False, na_sentinel=- 1, size_hint=None)

将对象编码为枚举类型或分类变量。
使用kaggle的钻石数据集测试了一下:

codes, unique = pd.factorize(diamonds_data['cut'])
print(codes)
print(unique)
[0 1 2 ... 3 1 0]
Index(['Ideal', 'Premium', 'Good', 'Very Good', 'Fair'], dtype='object')

还可以设置参数sort=True,对unique进行排序后,再编码:

codes, unique = pd.factorize(diamonds_data['cut'], sort=True)
print(codes)
print(unique)
[2 3 1 ... 4 3 2]
Index(['Fair', 'Good', 'Ideal', 'Premium', 'Very Good'], dtype='object')

总结:
Label Encoding只是将文本转化为数值,并没有解决文本特征的问题:所有的标签都变成了数字,算法模型直接将根据其距离来考虑相似的数字,而不考虑标签的具体含义。使用该方法处理后的数据适合支持类别性质的算法模型,如LightGBM。

独热编码(One-Hot Encoding)

独热编码优缺点:
优点: 独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。
缺点: 当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA(主成分分析)来减少维度。而且One-Hot Encoding+PCA这种组合在实际中也非常有用。

更多详见开头的博文。

基于Scikit-learn 的one hot encoding:
有两种方式:

  1. LabelBinarizer
  2. OneHotEncoder

1. LabelBinarizer:

将对应的数据转换为二进制型,类似于onehot编码,这里有几点不同:

  • 可以处理数值型和类别型数据.
  • 输入必须为1D数组.
  • 可以自己设置正类和负类的表示方式.

例子:

list_to_encode = ['cut', 'color', 'clarity']
lb = LabelBinarizer()
for col in list_to_encode:
    print(col + ":")
    print(lb.fit_transform(diamonds_data[col]))
    print(lb.classes_)
cut:
[[0 0 1 0 0]
 [0 0 0 1 0]
 [0 1 0 0 0]
 ...
 [0 0 0 0 1]
 [0 0 0 1 0]
 [0 0 1 0 0]]
['Fair' 'Good' 'Ideal' 'Premium' 'Very Good']
color:
[[0 1 0 ... 0 0 0]
 [0 1 0 ... 0 0 0]
 [0 1 0 ... 0 0 0]
 ...
 [1 0 0 ... 0 0 0]
 [0 0 0 ... 1 0 0]
 [1 0 0 ... 0 0 0]]
['D' 'E' 'F' 'G' 'H' 'I' 'J']
clarity:
[[0 0 0 ... 0 0 0]
 [0 0 1 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 ...
 [0 0 1 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]]

2. OneHotEncoder:

  • OneHotEncoder只能对数值型数据进行处理,需要先将文本转化为数值(Label encoding)后才能使用。
  • 只接受2D数组。
class sklearn.preprocessing.OneHotEncoder(*, categories='auto', drop=None, sparse=True, dtype=<class 'numpy.float64'>, handle_unknown='error')

参数:
sparse bool, default=True : 如果设置为True,将返回稀疏矩阵,否则将返回数组。

例子:
(写了一个行数对数据中的 类别型变量 用 OneHotEncoder进行编码,最终返回整个数据)

########################################OneHotEncoder##########################
# 对钻石数据集中的类别型变量进行独热编码,最终返回整个数据集
# 注意:1.使用OneHotEncoder前,要将字符串类型的变量先使用LabelEncoder转换成数值型.2.OneHotEncoder只接受2D数组。
def LabelOneHotEncoder(data, list_to_encode):
    data_num = np.array([])
    for col in data.columns:
        if col in list_to_encode:
            le = LabelEncoder()
            data[col] = le.fit_transform(data[col])  # 先将data中的类别型变量转换成数值标签
            print(col, ':', le.classes_)
            encoder_col = OneHotEncoder(sparse=False).fit_transform(np.array(diamonds_data['cut'])[:, np.newaxis])
            if len(data_num) == 0:
                data_num = encoder_col
            else:
                data_num = np.hstack([data_num, encoder_col])
        else:
            if len(data_num) == 0:
                data_num = np.array(data[col])[:, np.newaxis]
            else:
                data_num = np.hstack([data_num, np.array(data[col])[:, np.newaxis]])
        print(data_num.shape)
    return data_num


# # 使用钻石数据集进行测试
data_transf = LabelOneHotEncoder(diamonds_data, ['cut', 'color', 'clarity'])
print(data_transf)
print(data_transf.shape)
(53940, 1)
cut : ['Fair' 'Good' 'Ideal' 'Premium' 'Very Good']
(53940, 6)
color : ['D' 'E' 'F' 'G' 'H' 'I' 'J']
(53940, 11)
clarity : ['I1' 'IF' 'SI1' 'SI2' 'VS1' 'VS2' 'VVS1' 'VVS2']
(53940, 16)
(53940, 17)
(53940, 18)
(53940, 19)
(53940, 20)
(53940, 21)
(53940, 22)
[[0.23 0.   0.   ... 3.95 3.98 2.43]
 [0.21 0.   0.   ... 3.89 3.84 2.31]
 [0.23 0.   1.   ... 4.05 4.07 2.31]
 ...
 [0.7  0.   0.   ... 5.66 5.68 3.56]
 [0.86 0.   0.   ... 6.15 6.12 3.74]
 [0.75 0.   0.   ... 5.83 5.87 3.64]]
(53940, 22)

注:结果有一点点奇怪。比如,color有7类,但是最后data_num的列数只增加了5.

OrdinalEncoder

这是最简单的一种,对于一个具有m个category的Feature,我们将其对应地映射到 [0,m-1] 的整数。
当然 Ordinal Encoding 更适用于 Ordinal Feature,即各个特征有内在的顺序。例如对于”学历”这样的类别,”学士”、”硕士”、”博士” 可以很自然地编码成 [0,2],因为它们内在就含有这样的逻辑顺序。但如果对于“颜色”这样的类别,“蓝色”、“绿色”、“红色”分别编码成[0,2]是不合理的,因为我们并没有理由认为“蓝色”和“绿色”的差距比“蓝色”和“红色”的差距对于特征的影响是不同的。

orec = OrdinalEncoder()
orec.fit(diamonds_data[['cut', 'color', 'clarity']])
print(orec.transform(diamonds_data[['cut', 'color', 'clarity']]))
[[2. 1. 3.]
 [3. 1. 2.]
 [1. 1. 4.]
 ...
 [4. 0. 2.]
 [3. 4. 3.]
 [2. 0. 3.]]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值