对离散特征进行数据预处理:独热编码、标签编码及二值化

简介: 使用机器学习时,会存在不同的特征类型:连续型特征和离散型特征。针对连续性特征,我们通常将其线性缩放到[-1, 1]区间或者缩放到均值为0,方差为1的范围。但是,特征并不总是连续值,而有可能是分类值、离散值。因此,我们也需要对离散值进行特征编码数据预处理。

使用机器学习时,会存在不同的特征类型:连续型特征和离散型特征。

针对连续性特征,我们通常将其线性缩放到[-1, 1]区间或者缩放到均值为0,方差为1的范围。

但是,特征并不总是连续值,而有可能是分类值、离散值。因此,我们也需要对离散值进行特征编码数据预处理。

离散特征的编码分为两种情况:

  1. 如果离散特征的取值之间没有大小的意义,比如,颜色:[红色, 蓝色, 黄色],那么就使用独热编码(one-hot)编码,即,红色:1 0 0 ,黄色: 0 1 0,蓝色:0 0 1
  2. 如果离散特征的取值有大小的意义,比如,衣服的型号:[X, XL, XXL],那么就使用标签编码,对数值进行映射:{X:1, XL:2, XXL:3}


独热编码


什么是独热编码

独热编码(one-hot encoding), 直观来说就是有多少个状态就有多少比特,而且只有一个比特为1,其他全为0的一种码制。

针对独热编码,该离散特征有多少取值,就用多少维来表示该特征。

独热编码优缺点

优点:

独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。

缺点:

当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且独热编码+PCA这种组合在实际中也非常有用。


如何判断用不用独热编码

用:

独热编码用来解决类别型数据的离散值问题。

不用:

将离散型特征进行独热编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用独热编码就可以很合理的计算出距离,那么就没必要进行独热编码。

有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是个类别符号,所以不用进行独热编码。

树模型不太需要独热编码,对于决策树来说,独热编码的本质是增加树的深度。

总的来说,要是独热编码的类别数目不太多,建议优先考虑。


 

如何判断需不需要归一化

  • 需要: 基于参数的模型或基于距离的模型,都是要进行特征的归一化。
  • 不需要:基于树的方法是不需要进行特征的归一化,例如随机森林,bagging 和 boosting等。

示例代码

pandas实现

import pandas as pd
data = pd.Series(list('abca'))
print(data)
print("----------")
# 独热编码
# 参数说明
# data : array-like, Series, or DataFrame ,输入的数据
# prefix : string, list of strings, or dict of strings, default None ,get_dummies转换后,列名的前缀 
# columns : list-like, default None,指定需要实现类别转换的列名
# dummy_na : bool, default False,增加一列表示空缺值,如果False就忽略空缺值
# drop_first : bool, default False,获得k中的k-1个类别值,去除第一个
result = pd.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False)
print(result)
print("----------")
# 哑编码
result2 = pd.get_dummies(data,drop_first=True)
print(result2)
复制代码


运行结果:

0    a
1    b
2    c
3    a
dtype: object
----------
   a  b  c
0  1  0  0
1  0  1  0
2  0  0  1
3  1  0  0
----------
   b  c
0  0  0
1  1  0
2  0  1
3  0  0
复制代码


关于独特编码与哑编码的区别与联系

哑变量编码直观的解释就是任意的将一个状态位去除。 拿上面的例子来说,我们用2个状态位就足够反应上述3个类别的信息。

独特编码与哑编码的的“思想路线”是相同的,只是哑变量编码觉得独特编码太罗嗦了,所以它就很那么很明显的东西省去了。这种简化不能说到底好不好,这要看使用的场景。

sklearn实现

from sklearn.preprocessing import OneHotEncoder
import numpy as np
target = np.array([[1],[2],[3],[4]])
ohe = OneHotEncoder()
ohe.fit(target)
print(ohe.get_feature_names())
ohe_r = ohe.transform([[4],[3],[1],[4]]).toarray()
print(ohe_r)
复制代码


运行结果:

['x0_1' 'x0_2' 'x0_3' 'x0_4']
[[0. 0. 0. 1.]
 [0. 0. 1. 0.]
 [1. 0. 0. 0.]
 [0. 0. 0. 1.]]
复制代码


针对多个特征进行特征编码:

# 多个特征独热编码
from sklearn import preprocessing
import numpy as np
data = np.array([[0, 0, 3], 
                 [1, 1, 0], 
                 [0, 2, 1], 
                 [1, 0, 2]])
enc = preprocessing.OneHotEncoder()
enc.fit(data)   # fit来学习编码
enc.transform([[0, 1, 3]]).toarray()    # 进行编码
复制代码


运行结果如下:

array([[1., 0., 0., 1., 0., 0., 0., 0., 1.]])
复制代码


上面的代码说明如下:

原始数据矩阵为4*3,即4个样本数据,3个特征维度。

  • 观察数据矩阵,第一列为第一个特征维度,有两种取值0\1. 所以对应编码方式为10 、01。
  • 同理,第二列为第二个特征维度,有三种取值0\1\2,所以对应编码方式为100、010、001。
  • 同理,第三列为第三个特征维度,有四中取值0\1\2\3,所以对应编码方式为1000、0100、0010、0001。

再来看要进行编码的参数[0 , 1,  3], 0作为第一个特征编码为10,  1作为第二个特征编码为010, 3作为第三个特征编码为0001。

故此编码结果为 1 0 0 1 0 0 0 0 1


标签编码


什么是标签编码

标签编码,就是根据字符串形式的特征值在特征序列中的位置,为其指定一个数字标签,用于提供给基于数值算法的学习模型。

利用LabelEncoder对不连续的数字或者文本进行编号,转换成连续的数值型变量。

示例代码

对文本标签进行编号的示例代码如下:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(["Japan", "china", "Japan", "Korea","china"])
print('标签个数:%s' % le.classes_)
print('标签值标准化:%s' % le.transform(["Japan", "china", "Japan", "Korea","china"]))
print('标准化标签值反转:%s' % le.inverse_transform([0, 2 ,0 ,1 ,2]))
复制代码


运行结果:

标签个数:['Japan' 'Korea' 'china']
标签值标准化:[0 2 0 1 2]
标准化标签值反转:['Japan' 'china' 'Japan' 'Korea' 'china']
复制代码


对不连续的数字进行编号的示例代码如下:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
# 对不连续的数字进行编号
le.fit([1,5,67,100])
result = le.transform([1,1,100,67,5])
print(f"编号:{result}")
print("逆过程:%s"%le.inverse_transform([0,0,3,2,1]))
复制代码


运行结果:

编号:[0 0 3 2 1]
逆过程:[  1   1 100  67   5]
复制代码


二值化


什么是二值化

设置一个条件,把离散(或连续)数据分类两类。比如Age,大于30和小于30。大于30为1,小于等于30为0。

示例代码

from sklearn.preprocessing import Binarizer
binerize = Binarizer(threshold = 30)
x = np.array([30, 20, 45, 99, 87, 25, 31]) # 提取数据
trans = binerize.fit_transform(x.reshape(-1,1))
trans.tolist()
复制代码


运行结果:

[[0], [0], [1], [1], [1], [0], [1]]
复制代码


参考文档


相关文章
|
传感器 数据采集 供应链
港口智能化,我们这样做!
港口智能化,我们这样做!
556 0
港口智能化,我们这样做!
|
11月前
|
机器学习/深度学习 自然语言处理 数据管理
GraphRAG核心组件解析:图结构与检索增强生成
【10月更文挑战第28天】在当今数据科学领域,自然语言处理(NLP)和图数据管理技术的发展日新月异。GraphRAG(Graph Retrieval-Augmented Generation)作为一种结合了图结构和检索增强生成的创新方法,已经在多个应用场景中展现出巨大的潜力。作为一名数据科学家,我对GraphRAG的核心组件进行了深入研究,并在此分享我的理解和实践经验。
479 0
|
11月前
|
机器学习/深度学习 Python
堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能
本文深入探讨了堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能。文章详细介绍了堆叠的实现步骤,包括数据准备、基础模型训练、新训练集构建及元学习器训练,并讨论了其优缺点。
596 3
|
11月前
|
机器学习/深度学习 算法 数据挖掘
如何利用 BI 工具分析客户流失原因?
如何利用 BI 工具分析客户流失原因?
294 10
|
人工智能 小程序 编译器
Ant Design Mini 问题之Antd Mini 使用小程序函数式组件(functional-mini)来确保组件逻辑适配到双端,如何实现
Ant Design Mini 问题之Antd Mini 使用小程序函数式组件(functional-mini)来确保组件逻辑适配到双端,如何实现
196 1
|
存储 编解码 PyTorch
Transformers 4.37 中文文档(九十七)(1)
Transformers 4.37 中文文档(九十七)
156 1
|
存储 分布式计算 监控
Spark中广播变量
【8月更文挑战第13天】
473 0
|
数据挖掘 索引 Python
python_DataFrame的loc和iloc取数据 基本方法总结
python_DataFrame的loc和iloc取数据 基本方法总结
2164 0
python_DataFrame的loc和iloc取数据 基本方法总结
|
机器学习/深度学习 算法 Python
在Python中,独热编码(One-Hot Encoding)
在Python中,独热编码(One-Hot Encoding)
1375 8
|
机器学习/深度学习 算法 前端开发
基于Python的随机森林(RF)回归与变量重要性影响程度分析
基于Python的随机森林(RF)回归与变量重要性影响程度分析
309 1