机器学习——数据预处理
数据预处理
数据预处理的过程: 输入数据 -> 模型 -> 输出数据
如下图所示为数据样本矩阵,则一行一样本,一列一特征。机器学习中有一个数据预处理的库,是一个解决机器学习问题的科学计算工具包 sklearn.preprocessing。
年龄 | 学历 | 经验 | 性别 | 月薪 |
---|---|---|---|---|
25 | 硕士 | 2 | 女 | 10000 |
20 | 本科 | 3 | 男 | 8000 |
... | ... | ... | ... | ... |
均值移除(标准化)
由于一个样本的不同特征值差异较大,不利于使用现有机器学习算法进行样本处理。均值移除可以让样本矩阵中的每一列的平均值为0,标准差为1。
例如有一列特征值表示年龄: 17, 20, 23,在不使用库的情况下,如何使样本矩阵中的每一列的平均值为0呢?
mean = (17 + 20 + 23)/3 = 20 a' = 17 - 20 = -3 b' = 20 - 20 = 0 c' = 23 - 20 = 3
如何使样本矩阵中的每一列的标准差为1呢?
s = std(a', b', c') [a'/s, b'/s, c'/s]
我们可以使用sklearn.processing.scale均值移除函数一步实现,均值移除API:
raw_samples = np.array([ [17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) std_samples = sp.scale(raw_samples) # [[-1.22474487 1.38873015 -1.33630621] # [ 0. -0.46291005 0.26726124] # [ 1.22474487 -0.9258201 1.06904497]] print(std_samples.mean(axis=0)) # [ 0.00000000e+00 -3.70074342e-17 5.18104078e-16] print(std_samples.std(axis=0)) # [ 0.00000000e+00 -3.70074342e-17 5.18104078e-16]
范围缩放
将样本矩阵中的每一列的最小值和最大值设定为相同的区间,统一各列特征值的范围。一般情况下会把特征值缩放至[0, 1]区间。
例如有一列特征值表示年龄: [17, 20, 23],每个元素减去特征值数组所有元素的最小值,即可使一组特征值的最小值为0
$$[17-17, 20-17, 23-17]-->[0, 3, 6]$$
把特征值数组的每个元素除以最大值即可使一组特征值的最大值为1
$$[\frac{0}{6}, \frac{3}{6}, \frac{6}{6}]-->[0, \frac{1}{2}, 1]$$
sklearn.preprocessing.MinMaxScaler范围缩放API:
# 创建MinMax缩放器 mms = sp.MinMaxScaler(feature_range=(0, 1)) # 调用mms对象的方法执行缩放操作, 返回缩放过后的结果 result = mms.fit_transform(原始样本矩阵)
案例:
import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([[17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) # 根据给定范围创建一个范围缩放器 mms = sp.MinMaxScaler(feature_range=(0, 1)) # 用范围缩放器实现特征值的范围缩放 mms_samples = mms.fit_transform(raw_samples) # [[0. 1. 0. ] # [0.5 0.2 0.66666667] # [1. 0. 1. ]]
归一化
把需要处理的数据经过处理后(通过某种算法)限制在一定范围内。首先归一化是为了后面数据处理的方便,其次是保正程序运行时收敛加快。同时有些情况每个样本的每个特征值 具体的值并不重要,但是每个样本特征值的占比更加重要。归一化一般来说有两种做法:
第一种做法将输入转化到范围 [0, 1] 之间:
$$y=\frac{x-x_{min}}{x_{max}-x_{min}}$$
公式中$x_{max}$表示输入值的最大值,$x_{min}$表示输入值的最小值,这种方法还是会保持输入大于等于0。这种归一化一般用于图像处理。
第一种做法将输入转化到范围 [-1, 1] 之间:
$$y=\frac{x-x_{avg}}{x_{max}-x_{min}}$$
公式中$x_{avg}$表示输入值的平均值,那么经过这种归一化之后,输入会产生负值。这种归一化一般用于音频处理。
我们先来讲解第一种归一化方法
python | Java | PHP | |
2017 | 10 | 20 | 5 |
2018 | 8 | 5 | 0 |
变换后的样本矩阵,每个样本的特征值绝对值之和为1。
sklearn.preprocessing.normalize(array, norm='l1')
参数:
- array 原始样本矩阵
- norm 范数:
- l1:l1范数,向量中个元素绝对值之和;
- l2:l2范数,向量中个元素平方之和
返回归一化预处理后的样本矩阵
import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([[17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) # 归一化预处理 nor_samples = sp.normalize(raw_samples, norm='l1') # [[0.00412922 0.02428953 0.97158125] # [0.00392157 0.01568627 0.98039216] # [0.00410861 0.01339764 0.98249375]] print(abs(nor_samples).sum(axis=1)) # [1. 1. 1.]
标准化
对原始数据进行缩放处理,限制在一定的范围内。一般指正态化,即均值为0,方差为1。即使数据不符合正态分布,也可以采用这种方式方法,标准化后的数据有正有负。
二值化
有些业务并不需要分析矩阵的详细完整数据(比如图像边缘识别只需要分析出图像边缘即可),可以根据一个事先给定的阈值,用0和1表示特征值不高于或高于阈值。二值化后的数组中每个元素非0即1,达到简化数学模型,较少后面数据计算量的目的。
bin = sklearn.preprocessing.Binarizer(threshold=阈值) 给出阈值, 获取二值化器
- 调用transform方法对原始样本矩阵进行二值化预处理操作
result = bin.transform(原始样本矩阵)
import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([[17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) bin = sp.Binarizer(threshold=80) # 根据给定的阈值创建一个二值化器 bin_samples = bin.transform(raw_samples) # 通过二值化器进行二值化预处理 # [[0. 1. 1.] # [0. 0. 1.] # [0. 0. 1.]]
独热编码
独热编码独热编码(one-hot encoding)为样本特征的每个值建立一个由一个1和若干个0组成的序列,用该序列对所有的特征值进行编码。
也可以理解为将一个值转化为概率分布的向量,一般用于分类问题。
samples = np.array([[1., 3., 2], [7., 5., 4], [1., 8., 6], [7., 8., 9.]])
两种数 | 三种数 | 四种数 |
1 | 3 | 2 |
7 | 5 | 4 |
1 | 8 | 6 |
7 | 3 | 9 |
为每一个数字进行独热编码:
1-10 3-100 2-1000
7-01 5-010 4-0100
8-001 6-0010
9-0001
编码完毕后得到最终经过独热编码后的样本矩阵
101001000
010100100
100010010
011000001
ohe = sklearn.preprocessing.OneHotEncoder(sparse=是否采用紧缩格式, dtype=数据类型) 创建一个独热编码器
参数:
- sparse: 是否使用紧缩格式(稀疏矩阵)
- dtyle: 数据类型
方法:
- result = ohe.fit_transform(原始样本矩阵) 对原始样本矩阵进行处理,返回独热编码后的样本矩阵。
- encode_dict = ohe.fit(原始样本矩阵) 对原始样本矩阵进行训练,得到编码字典
- result = encode_dict.transform(原始样本矩阵) 调用encode_dict字典的transform方法 对数据样本矩阵进行独热编码
import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([[17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) ohe = sp.OneHotEncoder(sparse=False, dtype=int) # 创建独热编码器 # 方法1 ohe_dict = ohe.fit(raw_samples) result1 = ohe_dict.transform(raw_samples) print(result1) # 方法2 result2 = ohe.fit_transform(raw_samples) print(result2) # [[1 0 0 0 0 1 1 0 0] # [0 1 0 0 1 0 0 1 0] # [0 0 1 1 0 0 0 0 1]]
标签编码
根据字符串形式的特征值在特征序列中的位置,为其指定一个数字标签,用于提供给基于数值算法的学习模型。
lbe = sklearn.preprocessing.LabelEncoder() 获取标签编码器
方法:
- result = lbe.fit_transform(原始样本矩阵) 训练并且为原始样本矩阵进行标签编码
- samples = lbe.inverse_transform(result) 根据标签编码的结果矩阵反查字典 得到原始数据矩阵
import numpy as np import sklearn.preprocessing as sp raw_samples = np.array(['audi', 'ford', 'audi', 'toyota', 'ford', 'bmw', 'toyota', 'ford', 'audi']) lbe = sp.LabelEncoder() lbe_samples = lbe.fit_transform(raw_samples) # [0 2 0 3 2 1 3 2 0] inv_samples = lbe.inverse_transform(lbe_samples) # ['audi' 'ford' 'audi' 'toyota' 'ford' 'bmw' 'toyota' 'ford' 'audi']