最近在做低氧舱滞后时间模拟的项目中遇到了输入数据量纲不同的情况,使用归一化和直接学习对比的情况发现训练结果大有不同。因此记录一下。
归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量。 在多种计算中都经常用到这种方法。
以上是百度给的定义。。。。。。
个人理解归一化可以反应不同量纲数据中,对同一个结果的影响程度。
举例说明:
在二元气体扩散系数的计算中,一共有6个参数,量纲分别为K(温度),Pa(压强),Ma(气体A的分子质量),va(气体a的扩散体积)。以温度和压强来看,温度每变化1度对结果的影响程度和压强每变化1pa对结果的影响程度是不一样的。然而,温度的数量级在200~300之间,压强的数量级在100000 ~ 150000之间,所以没办法只通过变化量就认为温度对最终结果的影响更大。通过一种转换方法把两个量的单位都转换成 0 ~ 1之间的量。形象化点讲,就是在一个维度(量纲)对数据进行拉伸或者压缩。
对比网上的各种资料我认为归一化的作用主要如下:
1)归一化后加快了梯度下降求最优解的速度(也可以理解为收敛速度变快);
2)归一化有可能提高精度(如KNN);
3)去量纲化,如上边的例子所示,将温度和压强两个不同维度的量拉到同一个训练框架中一起训练。
实际使用中,针对上面的例子如果不进行归一化,会出现以下情况:
由于温度数量级只有200~300,而压强数量级则为数十万,因此,当学习率大于0.001(亲测),温度的百数量级就会几乎被训练网络忽略掉,导致模型无法收敛,最后经过几百轮训练不是权重参数都变成0抑或是发散到几十万而导致最后和实际结果的偏差越来越远
1、最大最小标准化(离差标准化)
适用于数据分布较为集中的情况,例如:
a = [[700],
[800],
[600],
[200],
[900],
]
这样的数据标准化后:
A = [[0.714],
[0.857],
[0.571],
[0],
[1],
]
而数据不够集中,或者最大最小值之间差较大
如下:
a = [[7000],
[800],
[600],
[200],
[900],
]
缺点: 数据标准化后就会出现其中一个值等于1,其他的值都非常小,当数量级超过一定量时会出现所有值接近于0的情况。
2、z-score规范化(零-均值规范化)
该方法,很明显和概率论中正态分布的标准化很接近,没错!!!该方法更适合与符合正态分布的量纲值,其分布越接近正态分布,效果越好。
例如:
通过测量生理指标预测运动员的表现,训练队提供的不同种的生理指标如红细胞,血红蛋白均符合正态分布,使用该方法进行归一化效果更好。
这类的数据经过归一化符合标准正态分布(零均值,标准差为1)。
缺点: 对原始数据的分布有要求。完全不符合正态分布或类正态分布的数据效果会很差!!!很差!!!
3、非线性的归一化
该方法包括 log,正切等非线性函数。
主要用于数据规模较大,且最大最小值之间差值很大的情况下使用。
1、使用sk-learn实现归一化
1) 最大最小标准化
from sklearn import preprocessing
import numpy as np
a = [[100,0.2,3,4,50],[200,0.4,6,7,90],[150,0.6,3,5,100],[700,0.5,8,1,70],[550,0.3,1,4,80]]
a_maxmin = preprocessing.MinMaxScaler()
a1 = np.array(a)
min_max_scaler = preprocessing.MinMaxScaler()#默认为范围0~1,拷贝操作
a_minmax = min_max_scaler.fit_transform(a)
print('x_minmax = ',a_minmax)
print('x = ',a)
# 新的测试数据进来,同样的转换
# 在线标准化
a_scale = preprocessing.scale(a)
# 沿着某个轴标准化数据集,以均值为中心,以分量为单位方差
print('a_scale = ',a_scale)
结果:
x_minmax =
[[0. 0. 0.28571429 0.5 0. ]
[0.16666667 0.5 0.71428571 1. 0.8 ]
[0.08333333 1. 0.28571429 0.66666667 1. ]
[1. 0.75 1. 0. 0.4 ]
[0.75 0.25 0. 0.5 0.6 ]]
x =
[[100, 0.2, 3, 4, 50], [200, 0.4, 6, 7, 90], [150, 0.6, 3, 5, 100], [700, 0.5, 8, 1, 70], [550, 0.3, 1, 4, 80]]
a_scale =
[[-1.00174065 -1.41421356 -0.48349378 -0.10314212 -1.62746694]
[-0.58434871 0. 0.72524067 1.44398974 0.69748583]
[-0.79304468 1.41421356 -0.48349378 0.4125685 1.27872403]
[ 1.50261097 0.70710678 1.53106363 -1.65027399 -0.46499055]
[ 0.87652306 -0.70710678 -1.28931674 -0.10314212 0.11624764]]
Process finished with exit code 0
2) z-score规范化
strandard_scaler = preprocessing.StandardScaler()
a_scaler = strandard_scaler.fit_transform(a)
print('x = ',a)
print('x_minmax = ',a_scaler)
结果:
x = [[100, 0.2, 3, 4, 50], [200, 0.4, 6, 7, 90], [150, 0.6, 3, 5, 100], [700, 0.5, 8, 1, 70], [550, 0.3, 1, 4, 80]]
x_minmax =
[[-1.00174065 -1.41421356 -0.48349378 -0.10314212 -1.62746694]
[-0.58434871 0. 0.72524067 1.44398974 0.69748583]
[-0.79304468 1.41421356 -0.48349378 0.4125685 1.27872403]
[ 1.50261097 0.70710678 1.53106363 -1.65027399 -0.46499055]
[ 0.87652306 -0.70710678 -1.28931674 -0.10314212 0.11624764]]
1、在机器学习打算使用梯度下降法求解时
在使用梯度下降法求解的时候,如果不进行归一化,训练结果会收敛很慢甚至可能无法收敛
2、当一组训练数据中不同参数来自于不同对象或不同指标时(单位不同,状态不同)
例如上面所说的温度和压强,分别来自于同一对象的不同指标。
在实际训练过程中面对不同量纲的数据,机器无法很好的区分,这些数据在计算机看来都只是单纯的数字,没有实际物理意义。因此,归一化可以消除数据之间的差异性。
3、需要提高机器学习训练精度的时候
一些分类器需要计算样本之间的距离,例如KNN。如果一个特征值域范围非常大,那么距离计算就主要取决于这个特征,从而与实际情况相悖。
4、什么样的模型不需要归一化
树形模型不需要归一化,它们不关心变量的值,只是关心变量的分布和变量之间的条件概率,如决策树、随机森林。
常见的如感抗,容抗这类的物理量通过标准化其复数部分也可以转换成纯的数字方便机器学习使用。