归一化和标准化的区别?

一.为什么会用到归一化和标准化?

通俗理解:

主要是为了调整样本数据每个维度的量纲,让每个维度数据量纲相同或接近。为什么要调整量纲?目的是什么?

1.什么是量纲不一样?

现在有一个2分类任务,预测一批零件是合格品还是残次品。每个零件有两个维度特征,一个是半径,合格品为0.1 m,另一个是长度,合格品为100m。我们可以看到长度的数值比较大,半径的数值比较小。一个特征0.1m左右 ,另一个特征100m左右,这个就叫量纲不一样。0.1m左右的特征,上差下差也是几cm的差距,而100m的特征上差下差可能差出10cm多或者更多,这就是量纲不一样!

2.量纲不一样会造成什么样的后果?

会误导模型学习过程。比如我们用kNN算法来预测零件是合格品或残次品,当计算点到点距离或者点到超面距离的时候,比如当前零件的半径为0.2m,那么半径带来的差的平方为(0.2-0.1)^2=0.01;当前零件的长度为101m, 长度带来的差的平方为(101-100)^2=1,与半径相比长度的量级较大,因此模型只学习到了长度特征,而get不到半径细小的差距,将学习不到半径这一特征。模型也不明白到底因为什么合格,因为什么不合格。
实际一般做机器学习应用的时候大部分时间是花费在特征处理上,所以我们需要对特征进行预处理。通过一些转换函数将特征数据转换成更加适合算法模型的特征数据的过程。

3.怎么解决这个问题?

把每个维度特征的量纲调整到一样或者相近。目前,最常用的两个方法是:归一化和标准化。

高阶理解:

其中维基百科给出的归一化的解释如下:
1)归一化后加快了梯度下降求最优解的速度;
2)归一化有可能提高精度。下面我简单扩展解释下这两点。

1)归一化后加快了梯度下降求最优解的速度。

如下图所示,左图表示未经归一化操作的寻最优解过程,右图表示经过归一化后的寻最优解过程。

在这里插入图片描述

当使用梯度下降法寻求最优解时,很有可能走“之字形”路线(垂直等高线走),从而导致需要迭代很多次才能收敛;而右图对两个原始特征进行了归一化,其对应的等高线显得很圆,在梯度下降进行求解时能较快的收敛。我们通过如下两个图可以清晰的看到(左侧未归一化)没有进行归一化操作的数据收敛的没有右侧的好,经过归一化的数据寻优更快,更平滑。
因此如果机器学习模型使用梯度下降法求最优解时,归一化往往非常有必要,否则很难收敛甚至不能收敛。

2)归一化有可能提高精度。

一些分类器需要计算样本之间的距离(如欧氏距离),例如KNN。如果一个特征的值域范围非常大,那么距离计算的值也会非常大,最后的得到的结论就主要取决于这个特征,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要)。
总的来说,特征的单位或者大小相差很大,或者某特征的方差相比其他特征的方差要大几个数量级,容易影响目标结果,使得一些算法无法学习到其他的特征。

二.归一化和标准化的方法?

1.归一化

在这里插入图片描述这种方法有个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。另外,最大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景。

2.标准化

在这里插入图片描述通过对原始数据进行变换把数据变换到均值为0,方差为1的范围内,处理后的特征是符合正态分布的。

三.什么时候用归一化?什么时候用标准化?

对输出结果范围有要求的,数据较为稳定,不存在极端的最大最小值,用归一化
存在异常值和较多噪音,用标准化

四.应用举例

1.归一化举例

sklearn归一化API:
sklearn.preprocessing.MinMaxScaler(feature_range=(0,1)…)每个特征缩放到给定范围(默认[0,1])
MinMaxScalar.fit_transform(X) X:numpy array格式的数据[n_samples,n_features]
返回值:转换后的形状相同的array

def minmax_demo():
    """
    归一化:使不同规格的数据转化成同一规格
    x' = (x-min)/(max-min)
    x'' = x' * (mx - mi) + mi
    max:一列最大值;min:一列最小值
    x'':最终结果;mx mi分别为指定区间值默认mx = 1 mi = 0
    """
    # 1.获取数据
    data = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
    print("data:\n", data)
    # 2.实例化一个转换器类
    transfer = MinMaxScaler(feature_range=[0,1]) #归一化范围,也可修改为2-3
    # 3.调用fit_transform
    data_new = transfer.fit_transform(data)
    print("data_new:\n", data_new)
    return None

结果:
data:
[[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
data_new:
[[1. 0. 0. 0. ]
[0. 1. 1. 0.83333333]
[0.5 0.5 0.6 1. ]]

2.标准化举例

sklearn特征化API: scikit-learn.preprocessing.StandardScaler
StandardScaler语法 :
在这里插入图片描述

def stand_demo():
    """
    标准化预处理:处理之后,对每列来说,所有数据都聚集在均值为0,标准差为1附近
    """
    # 1.获取数据
    data = [[ 1., -1., 3.],[ 2., 4., 2.],[ 4., 6., -1.]]
    print("data:\n", data)
    # 2.转换器类
    transfer = StandardScaler()  # 改变范围
    # 3.调用fit_transform
    data_new = transfer.fit_transform(data)
    print("data_new:\n", data_new)
    return None

结果:
data:
[[1.0, -1.0, 3.0], [2.0, 4.0, 2.0], [4.0, 6.0, -1.0]]
data_new:
[[-1.06904497 -1.35873244 0.98058068]
[-0.26726124 0.33968311 0.39223227]
[ 1.33630621 1.01904933 -1.37281295]]

猜你喜欢

转载自blog.csdn.net/m0_45283671/article/details/109472806