为什么要进行归一化?
机器学习模型被互联网行业广泛应用,一般做机器学习应用的时候大部分时间是花费在特征处理上,其中很关键的一步就是对特征数据进行归一化,为什么要归一化呢?维基百科给出的解释:
- 归一化后加快了梯度下降求最优解的速度;
如果机器学习模型使用梯度下降法求最优解时,归一化往往非常有必要,否则很难收敛甚至不能收敛。
- 归一化有可能提高精度;
一些分类器需要计算样本之间的距离(如欧氏距离),例如knn。如果一个特征值域范围非常大,那么距离计算就主要取决于这个特征,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要)。
哪些机器学习算法不需要(需要)做归一化?
概率模型(树形模型)不需要归一化,因为它们不关心变量的值,而是关心变量的分布和变量之间的条件概率,如决策树、rf。而像adaboost、svm、lr、knn、kmeans之类的最优化问题就需要归一化。
standardscaler原理
作用:去均值和方差归一化。且是针对每一个特征维度来做的,而不是针对样本。
标准差标准化(standardscale)使得经过处理的数据符合标准正态分布,即均值为0,标准差为1,其转化函数为:
其中μ为所有样本数据的均值,σ为所有样本数据的标准差。
- 下面使用numpy来实现一个矩阵的标准差标准化
import numpy as np
x_np = np.array([[1.5, -1., 2.],
[2., 0., 0.]])
mean = np.mean(x_np, axis=0)
std = np.std(x_np, axis=0)
print('矩阵初值为:{}'.format(x_np))
print('该矩阵的均值为:{}\n 该矩阵的标准差为:{}'.format(mean,std))
another_trans_data = x_np - mean
another_trans_data = another_trans_data / std
print('标准差标准化的矩阵为:{}'.format(another_trans_data))
矩阵初值为:[[ 1.5 -1. 2. ]
[ 2. 0. 0. ]]
该矩阵的均值为: [ 1.75 -0.5 1. ]
该矩阵的标准差为:[0.25 0.5 1. ]
标准差标准化的矩阵为:[[-1. -1. 1.]
[ 1. 1. -1.]]
经结果验证,新值符合 --->(旧值-均值)/ 标准差 .
- 下面使用sklearn提供的standardscaler方法
from sklearn.preprocessing import standardscaler # 标准化工具
import numpy as np
x_np = np.array([[1.5, -1., 2.],
[2., 0., 0.]])
scaler = standardscaler()
x_train = scaler.fit_transform(x_np)
print('矩阵初值为:{}'.format(x_np))
print('该矩阵的均值为:{}\n 该矩阵的标准差为:{}'.format(scaler.mean_,np.sqrt(scaler.var_)))
print('标准差标准化的矩阵为:{}'.format(x_train))
矩阵初值为:[[ 1.5 -1. 2. ]
[ 2. 0. 0. ]]
该矩阵的均值为: [ 1.75 -0.5 1. ]
该矩阵的标准差为:[0.25 0.5 1. ]
标准差标准化的矩阵为:[[-1. -1. 1.]
[ 1. 1. -1.]]
可以发现,sklearn的标准化工具实例化后会有两个属性,一个是mean_(均值),一个var_(方差)。最后的结果和使用numpy是一样的。
其他的归一化类型
- 线性归一化
这种归一化方法比较适用在数值比较集中的情况。这种方法有个缺陷,如果max和min不稳定,很容易使得归一化结果不稳定,使得后续使用效果也不稳定。实际使用中可以用经验常量值来替代max和min。
- 非线性归一化
经常用在数据分化比较大的场景,有些数值很大,有些很小。通过一些数学函数,将原始值进行映射。该方法包括 log、指数,正切等。需要根据数据分布的情况,决定非线性函数的曲线,比如log(v, 2)还是log(v, 10)等。