数据预处理,为后续的机器学习搭建数据基础,避免个别样本对结果产生大的误差
简述
数据预处理的过程: 输入数据 -> 模型 -> 输出数据
数据样本矩阵
年龄 |
学历 |
经验 |
性别 |
月薪 |
25 |
硕士 |
2 |
女 |
10000 |
20 |
本科 |
3 |
男 |
8000 |
… |
… |
… |
… |
… |
样本矩阵:一行一样本,一列一特征 |
|
|
|
|
输出向量:其中的每个元素与一个样本相对应 |
|
|
|
|
sci-kit learn
(又称sklearn)经典 机器学习框架
引入方式
1 2
| import sklearn.preprocessing as sp
|
均值移除
将样本矩阵中的各个列(特征)的平均值调整为0,标准差调整为1,以此均化不同的特征,使它们对模型预测结果的贡献度趋于近似一致。
标准差:又称均方差,标准偏差。方差的算术平方根。标准差能反映一个数据集的离散程度。
公式如下:
$\sigma=\sqrt{\frac{1}{N}\sum^{N}_{i=1}{(x_i-\overline{x})^2}}$
如何使样本矩阵中的每一列的平均值为0呢?
1 2 3 4 5 6
| 例如有一列特征值表示年龄: 17, 20, 23 mean = (17 + 20 + 23)/3 = 20 a' = -3 b' = 0 c' = 3 完成!
|
如何使样本矩阵中的每一列的标准差为1呢?
1 2 3 4 5
| a' = -3 b' = 0 c' = 3 s' = std(a', b', c') [a'/s', b'/s', c'/s']
|
均值移除API:
1 2 3 4
| import sklearn.preprocessing as sp
A = sp.scale(array)
|
案例:
1 2 3 4 5 6 7 8 9 10 11
| import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([ [17., 100., 4000], [20., 80., 5000], [23., 75., 5500]])
std_samples = sp.scale(raw_samples) print(std_samples) print(std_samples.mean(axis=0)) print(std_samples.std(axis=0))
|
范围缩放
将样本矩阵中的每一列的最小值和最大值设定为相同的区间,统一各列特征值的范围。一般情况下会把特征值缩放至[0, 1]区间。
举例说明
A班 数学平均成绩:90/150
B班 数学平均成绩:80/100
C班 数学平均成绩:5/5
从数据上面看,A班的数学成绩是最高的,但是看到总分150之后,发现才刚刚及格,所以这个分数我们要做范围处理
如何使一组特征值的最小值为0呢?
1 2
| 例如有一列特征值表示年龄: [17, 20, 23] 每个元素减去特征值数组所有元素的最小值即可:[0, 3, 6]
|
如何使一组特征值的最大值为1呢?
1 2
| [0, 3, 6] 把特征值数组的每个元素除以最大值即可:[0, 1/2, 1]
|
范围缩放API:
1 2 3 4
| mms = sp.MinMaxScaler(feature_range=(0, 1))
result = mms.fit_transform(原始样本矩阵)
|
案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([ [17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) print(raw_samples) mms_samples = raw_samples.copy() for col in mms_samples.T: col_min = col.min() col_max = col.max() a = np.array([ [col_min, 1], [col_max, 1]]) b = np.array([0, 1]) x = np.linalg.solve(a, b) col *= x[0] col += x[1] print(mms_samples)
mms = sp.MinMaxScaler(feature_range=(0, 1))
mms_samples = mms.fit_transform(raw_samples) print(mms_samples)
|
归一化
有些情况每个样本的每个特征值具体的值并不重要,但是每个样本特征值的占比更加重要。
|
Python |
Java |
PHP |
2017 |
10 |
20 |
5 |
2018 |
8 |
5 |
0 |
所以归一化即是用每个样本的每个特征值除以该样本各个特征值绝对值的总和。变换后的样本矩阵,每个样本的特征值绝对值之和为1。
归一化相关API:
1 2 3 4 5 6
|
sp.normalize(array, norm='l1')
|
案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([ [17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) print(raw_samples) nor_samples = raw_samples.copy() for row in nor_samples: row /= abs(row).sum() print(nor_samples) print(abs(nor_samples).sum(axis=1))
nor_samples = sp.normalize(raw_samples, norm='l1') print(nor_samples) print(abs(nor_samples).sum(axis=1))
|
二值化
有些业务并不需要分析矩阵的详细完整数据(比如图像边缘识别只需要分析出图像边缘即可),可以根据一个事先给定的阈值,用0和1表示特征值不高于或高于阈值。二值化后的数组中每个元素非0即1,达到简化数学模型的目的。
二值化相关API:
1 2 3 4
| bin = sp.Binarizer(threshold=阈值)
result = bin.transform(原始样本矩阵)
|
案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([ [17., 100., 4000], [20., 80., 5000], [23., 75., 5500]]) print(raw_samples) bin_samples = raw_samples.copy() bin_samples[bin_samples <= 80] = 0 bin_samples[bin_samples > 80] = 1 print(bin_samples)
bin = sp.Binarizer(threshold=80)
bin_samples = bin.transform(raw_samples) print(bin_samples)
|
独热编码
为样本特征的每个值建立一个由一个1和若干个0组成的序列,用该序列对所有的特征值进行编码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 两个数 三个数 四个数 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
|
独热编码相关API:
1 2 3 4 5 6
|
ohe = sp.OneHotEncoder(sparse=是否采用紧缩格式, dtype=数据类型)
result = ohe.fit_transform(原始样本矩阵)
|
1 2 3 4 5
| ohe = sp.OneHotEncoder(sparse=是否采用紧缩格式, dtype=数据类型)
encode_dict = ohe.fit(原始样本矩阵)
result = encode_dict.transform(原始样本矩阵)
|
案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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)
ohe_dict = ohe.fit(raw_samples) ohe_samples = ohe_dict.transform(raw_samples)
ohe_samples = ohe.fit_transform(raw_samples) print(ohe_samples)
|
标签编码
根据字符串形式的特征值在特征序列中的位置,为其指定一个数字标签,用于提供给基于数值算法的学习模型。
标签编码相关API:
1 2 3 4 5 6
| lbe = sp.LabelEncoder()
result = lbe.fit_transform(原始样本矩阵)
samples = lbe.inverse_transform(result)
|
案例:
1 2 3 4 5 6 7 8 9 10 11 12
| import numpy as np import sklearn.preprocessing as sp raw_samples = np.array([ 'audi', 'ford', 'audi', 'toyota', 'ford', 'bmw', 'toyota', 'ford', 'audi']) print(raw_samples) lbe = sp.LabelEncoder() lbe_samples = lbe.fit_transform(raw_samples) print(lbe_samples) inv_samples = lbe.inverse_transform(lbe_samples) print(inv_samples)
|