验证系列-机器学习中,为什么要进行数据标准化或者归一化?

时间:2024-10-23 07:36:50

机器学习中,为什么要进行数据标准化或者归一化?

  • 应用条件
  • 原理分析
  • 实例佐证

应用条件

我们在翻阅各种资料时,在数据预处理步骤,经常会看到对数据进行标准化或者归一化,那么这么做的好处是什么?

1、这样处理后加快了梯度下降求最优解的速度;
2、有可能提高精度;

但是,理解这句话后,你会发现,这是有应用条件的,即:
1、适用于用梯度下降法求参数的算法;
2、适用于基于距离的算法;

比如树模型这种基于概率的,是没有作用的。

原理分析

1、为什么这样处理后加快了梯度下降求最优解的速度?
原因很简单,比如我们有这样一个2元线性回归方程:

h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 h_\theta(x) = \theta_0 + \theta_1x_1 + \theta_2x_2 hθ(x)=θ0+θ1x1+θ2x2
斯坦福机器学习视频做了很好的解释:/ml-003/lecture/21

如下图所示,蓝色的圈圈图代表的是两个特征的等高线。其中左图两个特征X1和X2的区间相差非常大,X1区间是[0,2000],X2区间是[1,5],其所形成的等高线非常尖。当使用梯度下降法寻求最优解时,很有可能走“之字型”路线(垂直等高线走),从而导致需要迭代很多次才能收敛;

而右图对两个原始特征进行了归一化,其对应的等高线显得很圆,在梯度下降进行求解时能较快的收敛。
因此如果机器学习模型使用梯度下降法求最优解时,归一化往往非常有必要,否则很难收敛甚至不能收敛。
在这里插入图片描述

2、为什么有可能提高精度?

一些机器学习算法需要计算样本之间的距离(如欧氏距离),例如 KNN、K-means 等。如果一个特征值域范围非常大,那么距离计算就主要取决于这个特征,其他特征的影响就会很低,但是假如这时实际情况是值域范围小的特征更重要,那么最终模型的效果就会变差。

实例佐证

sklearn里面生成的数据集本身量纲就差不多,效果不明显,这里上秦秉丰机器学习里的数据集:


import numpy as np
x = ([[-1.7612000e-02,  1.4053064e+01],
       [-1.3956340e+00,  4.6625410e+00],
       [-7.5215700e-01,  6.5386200e+00],
       [-1.3223710e+00,  7.1528530e+00],
       [ 4.2336300e-01,  1.1054677e+01],
       [ 4.0670400e-01,  7.0673350e+00],
       [ 6.6739400e-01,  1.2741452e+01],
       [-2.4601500e+00,  6.8668050e+00],
       [ 5.6941100e-01,  9.5487550e+00],
       [-2.6632000e-02,  1.0427743e+01],
       [ 8.5043300e-01,  6.9203340e+00],
       [ 1.3471830e+00,  1.3175500e+01],
       [ 1.1768130e+00,  3.1670200e+00],
       [-1.7818710e+00,  9.0979530e+00],
       [-5.6660600e-01,  5.7490030e+00],
       [ 9.3163500e-01,  1.5895050e+00],
       [-2.4205000e-02,  6.1518230e+00],
       [-3.6453000e-02,  2.6909880e+00],
       [-1.9694900e-01,  4.4416500e-01],
       [ 1.0144590e+00,  5.7543990e+00],
       [ 1.9852980e+00,  3.2306190e+00],
       [-1.6934530e+00, -5.5754000e-01],
       [-5.7652500e-01,  1.1778922e+01],
       [-3.4681100e-01, -1.6787300e+00],
       [-2.1244840e+00,  2.6724710e+00],
       [ 1.2179160e+00,  9.5970150e+00],
       [-7.3392800e-01,  9.0986870e+00],
       [-3.6420010e+00, -1.6180870e+00],
       [ 3.1598500e-01,  3.5239530e+00],
       [ 1.4166140e+00,  9.6192320e+00],
       [-3.8632300e-01,  3.9892860e+00],
       [ 5.5692100e-01,  8.2949840e+00],
       [ 1.2248630e+00,  1.1587360e+01],
       [-1.3478030e+00, -2.4060510e+00],
       [ 1.1966040e+00,  4.9518510e+00],
       [ 2.7522100e-01,  9.5436470e+00],
       [ 4.7057500e-01,  9.3324880e+00],
       [-1.8895670e+00,  9.5426620e+00],
       [-1.5278930e+00,  1.2150579e+01],
       [-1.1852470e+00,  1.1309318e+01],
       [-4.4567800e-01,  3.2973030e+00],
       [ 1.0422220e+00,  6.1051550e+00],
       [-6.1878700e-01,  1.0320986e+01],
       [ 1.1520830e+00,  5.4846700e-01],
       [ 8.2853400e-01,  2.6760450e+00],
       [-1.2377280e+00,  1.0549033e+01],
       [-6.8356500e-01, -2.1661250e+00],
       [ 2.2945600e-01,  5.9219380e+00],
       [-9.5988500e-01,  1.1555336e+01],
       [ 4.9291100e-01,  1.0993324e+01],
       [ 1.8499200e-01,  8.7214880e+00],
       [-3.5571500e-01,  1.0325976e+01],
       [-3.9782200e-01,  8.0583970e+00],
       [ 8.2483900e-01,  1.3730343e+01],
       [ 1.5072780e+00,  5.0278660e+00],
       [ 9.9671000e-02,  6.8358390e+00],
       [-3.4400800e-01,  1.0717485e+01],
       [ 1.7859280e+00,  7.7186450e+00],
       [-9.1880100e-01,  1.1560217e+01],
       [-3.6400900e-01,  4.7473000e+00],
       [-8.4172200e-01,  4.1190830e+00],
       [ 4.9042600e-01,  1.9605390e+00],
       [-7.1940000e-03,  9.0757920e+00],
       [ 3.5610700e-01,  1.2447863e+01],
       [ 3.4257800e-01,  1.2281162e+01],
       [-8.1082300e-01, -1.4660180e+00],
       [ 2.5307770e+00,  6.4768010e+00],
       [ 1.2966830e+00,  1.1607559e+01],
       [ 4.7548700e-01,  1.2040035e+01],
       [-7.8327700e-01,  1.1009725e+01],
       [ 7.4798000e-02,  1.1023650e+01],
       [-1.3374720e+00,  4.6833900e-01],
       [-1.0278100e-01,  1.3763651e+01],
       [-1.4732400e-01,  2.8748460e+00],
       [ 5.1838900e-01,  9.8870350e+00],
       [ 1.0153990e+00,  7.5718820e+00],
       [-1.6580860e+00, -2.7255000e-02],
       [ 1.3199440e+00,  2.1712280e+00],
       [ 2.0562160e+00,  5.0199810e+00],
       [-8.5163300e-01,  4.3756910e+00],
       [-1.5100470e+00,  6.0619920e+00],
       [-1.0766370e+00, -3.1818880e+00],
       [ 1.8210960e+00,  1.0283990e+01],
       [ 3.0101500e+00,  8.4017660e+00],
       [-1.0994580e+00,  1.6882740e+00],
       [-8.3487200e-01, -1.7338690e+00],
       [-8.4663700e-01,  3.8490750e+00],
       [ 1.4001020e+00,  1.2628781e+01],
       [ 1.7528420e+00,  5.4681660e+00],
       [ 7.8557000e-02,  5.9736000e-02],
       [ 8.9392000e-02, -7.1530000e-01],
       [ 1.8256620e+00,  1.2693808e+01],
       [ 1.9744500e-01,  9.7446380e+00],
       [ 1.2611700e-01,  9.2231100e-01],
       [-6.7979700e-01,  1.2205300e+00],
       [ 6.7798300e-01,  2.5566660e+00],
       [ 7.6134900e-01,  1.0693862e+01],
       [-2.1687910e+00,  1.4363200e-01],
       [ 1.3886100e+00,  9.3419970e+00],
       [ 3.1702900e-01,  1.4739025e+01]])


y= ([0., 1., 0., 0., 0., 1., 0., 1., 0., 0., 1., 0., 1., 0., 1., 1., 1.,
       1., 1., 1., 1., 1., 0., 1., 1., 0., 0., 1., 1., 0., 1., 1., 0., 1.,
       1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 1., 0., 1., 1., 0., 0., 0.,
       0., 0., 0., 1., 1., 0., 1., 0., 1., 1., 1., 0., 0., 0., 1., 1., 0.,
       0., 0., 0., 1., 0., 1., 0., 0., 1., 1., 1., 1., 0., 1., 0., 1., 1.,
       1., 1., 0., 1., 1., 1., 0., 0., 1., 1., 1., 0., 1., 0., 0.])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

再用我们写好的逻辑回归类:
链接: 手写算法-python代码实现逻辑回归(带L1、L2正则项)

class LogisticRegression:
    
    #默认没有正则化,正则项参数默认为1,学习率默认为0.001,迭代次数为10001次
    def __init__(self,penalty = None,Lambda = 1,a = 0.001,epochs = 10001):
         = None
         = penalty
         = Lambda
         = a
         =epochs
         = lambda x:1/(1 + (-x))
        
    def loss(self,x,y):
        m=[0]
        y_pred = (x * )
        return (-1/m) * (((y, (y_pred)) + ((1-y),(1-y_pred))))
    
    def fit(self,x,y):
        lossList = []
        #计算总数据量
        m = [0]
        #给x添加偏置项
        X = ((((m,1)),x),axis = 1)
        #计算总特征数
        n = [1]
        #初始化W的值,要变成矩阵形式
         = (((n,1)))
        #X转为矩阵形式
        xMat = (X)
        #y转为矩阵形式,这步非常重要,且要是m x 1的维度格式
        yMat = ((-1,1))
        #循环epochs次
        for i in range():
            #预测值
            h = (xMat * )
            gradient =  * (h - yMat)/m
            
            
            #加入l1和l2正则项,和之前的线性回归正则化一样
            if  == 'l2':
                gradient = gradient +  * 
            elif  == 'l1':
                gradient = gradient +  * ()
          
             =  * gradient
            if i % 50 == 0:
                ((xMat,yMat))
        #返回系数,和损失列表
        return ,lossList

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

没有做标准化前:


lr = LogisticRegression()
w,lossList = (x,y)
#这里感觉其实处理x,y不应该放在封装好的类里面处理,应该拿出来,作为全局变量使用,优化点
m=[0]
X = ((((m,1)),x),axis=1)
xMat = (X)
y_pred = [1 if x>=0.5 else 0 for x in (xMat*w)]

from  import classification_report
print(classification_report(y,y_pred))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

做标准化之后:

from sklearn import preprocessing 
x_1 = (x)

lr = LogisticRegression()
w,lossList = (x_1,y)
#这里感觉其实处理x,y不应该放在封装好的类里面处理,应该拿出来,作为全局变量使用,优化点
m=x_1.shape[0]
X = ((((m,1)),x_1),axis=1)
xMat = (X)
y_pred = [1 if x>=0.5 else 0 for x in (xMat*w)]

from  import classification_report
print(classification_report(y,y_pred))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

性能确实有了提高。