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

简介: 使用机器学习时,会存在不同的特征类型:连续型特征和离散型特征。针对连续性特征,我们通常将其线性缩放到[-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]]
复制代码


参考文档


相关文章
|
6天前
|
算法 搜索推荐
解读双编码器和交叉编码器:信息检索中的向量表示与语义匹配
在信息检索领域(即从海量数据中查找相关信息),双编码器和交叉编码器是两种至关重要的工具。它们各自拥有独特的工作机制、优势和局限性。本文将深入探讨这两种核心技术。
19 3
解读双编码器和交叉编码器:信息检索中的向量表示与语义匹配
|
2月前
|
自然语言处理 数据挖掘
数据特征包括分布特征、统计特征、对比特征、帕累托特征和文本特征
数据特征包括分布特征、统计特征、对比特征、帕累托特征和文本特征
97 4
|
6月前
|
自然语言处理 Python
【Python自然语言处理】文本向量化的六种常见模型讲解(独热编码、词袋模型、词频-逆文档频率模型、N元模型、单词-向量模型、文档-向量模型)
【Python自然语言处理】文本向量化的六种常见模型讲解(独热编码、词袋模型、词频-逆文档频率模型、N元模型、单词-向量模型、文档-向量模型)
1058 0
|
移动开发 数据可视化 算法
Pointnet语义分割任务S3DIS数据集
Pointnet语义分割任务S3DIS数据集
481 0
|
6月前
|
机器学习/深度学习 自然语言处理
向量的编码详解2
向量的编码详解2
65 1
|
6月前
|
自然语言处理
将向量提取器用于平行语料对齐的一个小示例
将向量提取器用于平行语料对齐的一个小示例
41 0
|
存储 算法 数据安全/隐私保护
图像相似性:哈希和特征
图像相似性:哈希和特征
150 0
|
编解码
编码生成矩阵与检错监督矩阵
编码生成矩阵与检错监督矩阵
217 0
编码生成矩阵与检错监督矩阵
|
存储 机器学习/深度学习 编解码
使用训练分类网络预处理多分辨率图像
说明如何准备用于读取和预处理可能不适合内存的多分辨率全玻片图像 (WSI) 的数据存储。肿瘤分类的深度学习方法依赖于数字病理学,其中整个组织切片被成像和数字化。生成的 WSI 具有高分辨率,大约为 200,000 x 100,000 像素。WSI 通常以多分辨率格式存储,以促进图像的高效显示、导航和处理。 读取和处理WSI数据。这些对象有助于使用多个分辨率级别,并且不需要将图像加载到核心内存中。此示例演示如何使用较低分辨率的图像数据从较精细的级别有效地准备数据。可以使用处理后的数据来训练分类深度学习网络。
325 0
|
机器学习/深度学习 数据采集 Python
独热编码(One-Hot Encoding)和 LabelEncoder标签编码 区别 数据预处理:(机器学习) sklearn
独热编码(One-Hot Encoding)和 LabelEncoder标签编码 区别 数据预处理:(机器学习) sklearn
746 0
独热编码(One-Hot Encoding)和 LabelEncoder标签编码 区别 数据预处理:(机器学习) sklearn