数据归一化 Feature Scaling
首先我们开看一下为什么要进行数据归一化。
我们使用前边说道的肿瘤的例子:
-- | 肿瘤大小( 厘米) | 发现时间(天) |
---|---|---|
样本1 | 1 | 200 |
样本2 | 5 | 100 |
那么这两个样本的距离是多少呢?如果使用欧拉距离的话,就是
在这种情况下,我们发现显然样本间的距离被发现时间所主导,因为时间间隔比较大,导致最终距离衡量的是时间。如果我们发现时间调整成以年为单位,此时肿瘤的距离有一下子又取决于肿瘤大小这个特征。很显然,如果不进行数据的基本处理,直接计算样本间的距离是有很大偏差的,不能反映每个样本特征的重要程度,所以要进行数据归一化处理。
-- | 肿瘤大小( 厘米) | 发现时间(天) |
---|---|---|
样本1 | 1 | 200=0.55年 |
样本2 | 5 | 100=0.27年 |
数据归一化
,所谓的数据归一化处理就是将所有的数据映射到同一尺度。通常最简单的方式叫作最值归一化(normalization)
: 把所有的数据映射到0-1之间。适用于有明确的边界,如学生的成绩。
最值归一化适用于分布有明显边界的情况
;缺点:受outliner影响较大,例如每个人的收入,没有明显的边界,假如大部分人的收入是1万,有一个人收入是100万,那么大部分人的映射在0-0.01左右,而收入高的人映射值接近1,因为这样偏差比较大,改进的方法是均值方差归一化(standardization)
。
均值方差归一化
:把所有数据归一到均值为0方差为1的分布中。适用于数据分布没有明显的边界;有可能存在极端数据值的情况。计算方法:
x:特征值
表示特征值均值
S:表示方差
下面我们来实现这两种归一化过程
import numpy as np
import matplotlib.pyplot as plt
# 最值归一化 Normalization
# 处理向量
x = np.random.randint(0, 100, size=100)
(x - np.min(x)) / (np.max(x)-np.min(x))
array([0.12121212, 0.24242424, 0.43434343, 0.49494949, 0.91919192,
0.54545455, 0.16161616, 0.53535354, 0.8989899 , 0.11111111,
0.49494949, 0.33333333, 0.72727273, 0.85858586, 0.27272727,
0.4040404 , 0.53535354, 0.56565657, 0.63636364, 0.58585859,
0.74747475, 0.8989899 , 0.54545455, 0.85858586, 0.25252525,
0.55555556, 0.77777778, 0.39393939, 0.43434343, 0.37373737,
0.4040404 , 0.15151515, 0.29292929, 0.31313131, 0.6969697 ,
0.93939394, 0.61616162, 0.78787879, 0.3030303 , 0.26262626,
0.17171717, 0.05050505, 0.56565657, 0.52525253, 0.13131313,
0.63636364, 0.7979798 , 0.4040404 , 0.49494949, 1. ,
0.52525253, 0.51515152, 0.85858586, 0.49494949, 0.25252525,
0.36363636, 0. , 0.51515152, 0.87878788, 0.42424242,
0.5959596 , 0.44444444, 0.1010101 , 0.03030303, 0.33333333,
0.07070707, 0.7979798 , 0.35353535, 0.34343434, 0.11111111,
0.45454545, 0.95959596, 0.83838384, 0.4040404 , 0.45454545,
0.45454545, 0.31313131, 0.39393939, 0.58585859, 0.02020202,
0.19191919, 0.60606061, 0.05050505, 0.25252525, 0.61616162,
0.73737374, 0.52525253, 0.6969697 , 0.35353535, 0.95959596,
0.98989899, 0.3030303 , 0.47474747, 0.85858586, 0. ,
0.12121212, 0.74747475, 0.18181818, 0.92929293, 0.3030303 ])
# 处理矩阵
X = np.random.randint(0, 100, (50, 2))
# 由于最值归一化得到的是浮点数,所以进行一下类型转换
X = np.array(X, dtype=float)
# 查看是否吧变成浮点数
X[:10]
array([[85., 65.],
[17., 55.],
[16., 67.],
[45., 77.],
[90., 71.],
[31., 89.],
[42., 92.],
[53., 56.],
[80., 25.],
[75., 45.]])
# 对第0列数据,就是这谢数据的第一个特征值,进行最值归一化
X[:, 0] = (X[:,0] - np.min(X[:,0])) / (np.max(X[:,0]) - np.min(X[:,0]))
# 对第1列数据,就是这谢数据的第二个特征值,进行最值归一化
X[:, 1] = (X[:,1] - np.min(X[:,1])) / (np.max(X[:,1]) - np.min(X[:,1]))
# 我们取出前十行看一下对应的数据结果
X[:10,:]
array([[0.89361702, 0.64948454],
[0.17021277, 0.54639175],
[0.15957447, 0.67010309],
[0.46808511, 0.77319588],
[0.94680851, 0.71134021],
[0.31914894, 0.89690722],
[0.43617021, 0.92783505],
[0.55319149, 0.55670103],
[0.84042553, 0.2371134 ],
[0.78723404, 0.44329897]])
# 简单的绘制我们的样本
plt.scatter(X[:,0],X[:,1])
plt.show()
# 查看X中第0列对应的均值
np.mean(X[:,0])
0.5546808510638298
# 查看X中第0列对应的方差
np.std(X[:,0])
0.28191296667346266
# 查看X中第1列对应的均值
np.mean(X[:,1])
0.49711340206185567
# 查看X中第1列对应的方差
np.std(X[:,1])
0.2898010576098996
下面我们来看均值方差归一化
X2 = np.random.randint(0, 100, (50, 2))
X2 = np.array(X, dtype=float)
X2[:,0] = (X2[:,0] - np.mean(X2[:,0])) / np.std(X2[:,0])
X2[:,1] = (X2[:,1] - np.mean(X2[:,1])) / np.std(X2[:,1])
# 简单的绘制我们的样本
plt.scatter(X2[:,0],X2[:,1])
plt.show()
对于这组数据,我们不能确定得到的结果是在0-1之间的,下面我们来看一下均值和方差
np.mean(X2[:,0])
-2.2204460492503132e-17
np.std(X2[:,0])
1.0
np.mean(X2[:,1])
4.440892098500626e-18
np.std(X2[:,1])
0.9999999999999999
由此可见,我们可以看出均值接近于0,方差接近1