酸菜鱼的梯度下降法学习

2019年3月26日:梯度下降法求解多元线性模型

实验目标

探讨使用梯度下降法(随机梯度下降法)的多变量线性回归模型,损失函数、梯度下降法的收敛、过拟合问题和学习率等之间的关系。

实验背景

请在文件夹“作业2”中下载文件名为“dataForTraining.txt”的文件。该文件包含广东省广州市海珠区的房价信息,里面包含50个训练样本数据。文件有三列,第一列对应房的面积(单位:平方米),第二列对应房子距离双鸭山职业技术学院的距离(单位:千米),第三列对应房子的销售价格(单位:万元)。

每一行对应一个训练样本。请使用提供的50个训练样本来训练多变量回归模型以便进行房价预测,请用(随机)梯度下降法多变量线性回归模型进行建模。为了评估训练效果,请文件夹中下载测试数据集“dataForTesting.txt” (该测试文件里的数据跟训练样本具有相同的格式,即第一列对应房子面积,第二列对应距离,第三列对应房子总价)。

实验原理

梯度下降法(GD,Gradient Descent)

梯度下降法(批量梯度下降法)的计算过程就是沿梯度下降的方向求解极小值或沿梯度上升方向求解极大值。由于GD在每次计算梯度时都需要遍历所有样本,因此一定保证每次迭代都能沿着极小值的方向迈进,比较稳定,缺点在于每一次迭代的计算量都一样且比较大。

随机梯度下降法(SGD,Stochastic Gradient Descent)

随机梯度下降法的计算过程与梯度下降法相仿,区别在于SGD每次计算梯度时,只随机的选取一个样本来计算梯度,这样就大大的减小了计算的复杂度。问题在于由于只选择一个样本进行每次的迭代,因此收敛不稳定,且有可能出现朝着反方向迭代的情况,即某一次迭代中出现了负优化。

小批量梯度下降法(mini-batch)

在每次迭代的时候选取一部分样本,与随机梯度下降法相比,增强了方向的稳定性。与批量梯度下降法相比,运算量大大减少,运行速度也更快。

多变量线性回归

即具有多个自变量且可用线性方程式表达的模型,形如:

h(x)=theta0+theta1x1+theta2x2+theta3*x3

同时,我们可以认为函数的常数项是相当于系数(该常数)始终乘以一个(X0 == 1),此时这个函数就可以表达成两个一维矩阵之间的相乘,即

hθ(x) = θTX

其中θ为参数矩阵,X为系数矩阵

均方误差

均方误差(英语:mean-square error、MSE)是对于无法观察的参数 θ 的一个估计函数T;其定义为:

$$MSE(T) = E((T-θ²)) = \frac{1}{2N}\sum_{t=1}^{N}(Yestimate - Y)²$$

模型训练流程

训练流程如下:

  1. 先定义训练的迭代次数、学习率、样本数目等训练过程中使用到的参数,在每一次的训练中,根据选择的梯度下降方法(GD/SGD/mini-batch GD)进行训练。

  2. 进入迭代过程,每一次的训练中,先将模型更新,计算出预测值,根据预测值可以计算出当前模型预测的损失情况,然后再回退到原来前进前的情况,并记录下损失值,由最后的输出可知随着模型的训练损失值下降。然后重新将模型更新,然后得到同样的预测值,然后使用这个预测值与之前定义好的训练集作比较,计算出当前模型判断的准确率(误差),由最后的输出可知这个准确率在训练的过程中逐步上升。这就完成了一次迭代。

  3. 重复进行n次训练(在上面的代码中训练次数为400次),得到最终的模型。

  4. 使用测试集对最终的模型进行测试,最后得到这个模型识别测试集的准确率,通过准确率判断训练出来的模型的质量。

实验过程

模型训练的核心在于两个函数,一个是代价函数,另一个是梯度下降函数。

  • 代价函数(MSE):计算模型迭代完成后的均方误差作为误差

    def costFunc(X,Y,theta):
        inner = np.power((X*theta.T)-Y,2)  
        return np.sum(inner)/(len(X))  
    
  • 梯度函数:定义了整个迭代的训练过程,输入参数包括(训练样本,初始误差,学习率(步长),迭代次数,使用参数进行训练并迭代,通过代价函数求出当前的误差并记录,完成给定次数的迭代后输出最终的模型参数,训练样本误差,测试样本误差等信息。

    def gradientDescent(X,Y,theta,lr,iters):
        #初始化
        temp = np.mat(np.zeros(theta.shape))
        trainCost = []
        testCost = []
        index = []
        thetaNums = int(theta.shape[1]) #系数的个数
        #迭代过程
        for i in range(iters):
            error = (X*theta.T-Y) #计算误差
            for j in range(thetaNums): #三个系数
                #np.multiply:数组和矩阵对应位置相乘,输出与相乘数组/矩阵的大小一致
                derivativeInner = np.multiply(error,X[:,j]) #求导数
                #得到当前的参数
                temp[0,j] = theta[0,j] - (lr*np.sum(derivativeInner)/len(X))
            theta = temp #将参数更新
            if(i % 100000 == 0):
                index.append(i);
                trainCost.append(costFunc(X,Y,theta))
                testCost.append(costFunc(Xtest,Ytest,theta))
    
        return theta,trainCost,testCost,index
    

-

其余如文件读写,作图等功能可见源码注释。


exercise1:

你需要用多少个参数来训练该线性回归模型?请使用梯度下降方法训练。训练时,请把迭代次数设成1500000,学习率设成0.00015,参数都设成0.0。在训练的过程中,每迭代100000步,计算训练样本对应的误差,和使用当前的参数得到的测试样本对应的误差。请画图显示迭代到达100000步、200000步、… … 1500000时对应的训练样本的误差和测试样本对应的误差(图可以手画,或者用工具画图)。从画出的图中,你发现什么?请简单分析。

ANS1:

我定义的梯度下降模型使用了5个参数来训练这个线性模型(实际函数中有7个参数是因为我为了方便处理,将训练集和测试集的X和Y分开输入了),分别是:

  • 训练集(X,Y)
  • 测试集(Xtest,Ytest)
  • 初始系数(theta,都设为0)
  • 学习率(lr,learning rate)
  • 迭代次数(iters)

同时,训练后的模型输出四个参数,分别是:

  • 最终系数(resultTheta)
  • 一组训练集误差(trainCost)
  • 一组测试集误差(testCost)
  • 下标(按照题目要求用于记录误差所在的迭代次数,每十万次)

按照给定的要求进行150W次的迭代,每10W次迭代对两种误差都进行一次记录,得到结果如下图(为了图显示的美观,因此将float格式的误差转换成了int的格式,即去掉了小数部分):

AU4ryn.png

AU4wWQ.png

其中,第一张图是使用训练集计算出的误差,第二张图是使用测试集中训练得到的误差。通过数值可以看出,由于一开始设置的初始参数为【0,0,0】,因此得到的误差与其他误差相比十分大,导致整体图的结构看不出正确误差的走向,因此去掉第一个点重新作图,得到图像如下:

AU40zj.png
AU4aFS.png

可以看到,对于训练集,其误差在每10W次迭代中是下降且趋于收敛,在50W次迭代的时候达到极小值3,而且之后迭代中一直保持这个误差不变,此时由图看到的训练效果较好,可以认为梯度下降法达到了收敛。同时,参考测试集,误差是在20W次迭代的时候达到一个低值(119),然后继续迭代后误差反而上升了,最后稳定在133左右。基于此,我认为以题目给定的数值作为参数输入,最后得到的模型是过拟合的,具体体现在训练集的表现很好,但测试集的表现一般


Exercise 2:

现在,你改变学习率,比如把学习率改成0.0002(此时,你可以保持相同的迭代次数也可以改变迭代次数),然后训练该回归模型。你有什么发现?请简单分析。

ANS2:

改变学习率为0.0002后初始化模型并重新训练,得到的参数基本都是无意义的(除了第一个误差参数为10W+外,其余的均为NAN),显示运算的溢出。而修改学习率为更低的参数,效果不太明显,只能勉强看出学习率会影响训练的进度,对结果影响不大。后面经过讨论得知,这是由于训练过程中,参数没有进行正则化的原因,优化后得到更好的效果,可以看出,针对SD而言,当学习率上升时,模型训练速度提高。

同时,我使用了另外一门课《人工神经网络》中的作业作为例子,使用控制变量法对学习率进行了进一步的测试,得到结果如下图所示:(其中loss是损失函数,即误差;acc值则为得到的结果的准确率,计算方法相当于用模型得到的结果 Ycal 除以正确结果Ycorrect

可以看出,学习率会影响梯度下降法的性能,学习率数值大时可以使得模型迅速往理想模型移动,即误差值的收敛速率较快,系数在比较少的迭代次数中就会到达较好的数值,但同时过大的学习率会导致学习的不稳定,即两种数值都会出现较大幅度的波动,即学习的方式比较激进;即而学习率过小则导致训练需要的时间过长,即两种数值虽然往好的方向变化,但变化得很慢。

学习率设置为100(过高)

AU4WYF.pngAU4goT.png

学习率设置为e-10(过低)

AU46e0.pngAU4RFU.png

学习率设置为e-1

AU4DQs.pngAU4dJg.png

学习率设置为e-2

AU4cwV.pngAU4sLq.png

学习率的变化对loss值和accuracy值的影响都主要体现在这两种数值下降的加速度(幅度)以及出现波动的幅度与频率。以上面的训练为例子:

  1. 当学习率过高时(100),loss的图像呈现了较大幅度上下震荡的现象,loss值方差较大,但此时loss值的单个数值和均值都较小,最高点在300左右而最低点在50左右;accuracy值则很快到达了接近0.9的高值,但同时出现大幅度震荡,数值的方差较大,且在趋于稳定的过程中仍然时常出现波动到数值为0.4这样的情况。导致这种现象的原因是因为学习率过高导致了学习的不稳定性,有时候会往错误方向快速前进,导致了极端情况的出现。

  2. 当学习率过低(1e-10)时,loss图像视觉上有较大幅度的震荡,但实际上震荡范围很小(1030-1060,方差小),而数值均值很大,在1145左右;accuracy值则一直没有变化。这种现象出现的原因是学习率过低导致模型的学习效率很低,往正确模型前进的速度过慢,模型识别能力没有明显提升,因此正确率没有提升,错误率一直很高。

  3. 当学习率适中(1e-1,1e-2,1e-3)时,学习率的上升会加快训练的进程,体现在两种曲线梯度的上升,更快地趋向稳定和理想,但偶尔会出现震荡的情况。根据参数调试,我认为1e-2是比较理想的学习率。同时,上面训练函数的定义部分注释掉了一个动态调整学习率的过程,具体表现为每经过一百次训练,学习率就变为原来的1/10,这有助于后期模型训练得到的结果趋于稳定。


Exercise 3:

现在,我们使用其他方法来获得最优的参数。你是否可以用随机梯度下降法获得最优的参数?请使用随机梯度下降法画出迭代次数(每K次,这里的K你自己设定)与训练样本和测试样本对应的误差的图。比较Exercise 1中的实验图,请总结你的发现。

ANS3:

使用随机梯度下降法,即每次迭代只使用训练集中的一组数据作为输入参数来进行梯度的计算,得到的图像如下:

迭代次数为15W,每1W求一次误差

AU44SJ.png

AU4fW4.png

迭代次数为150W,每10W求一次误差

AU45l9.png

AU4IyR.png

由图可得,使用随机梯度下降法(即每次只抽取一个样本),可以很快接近最优的参数(通过数值判定),但在接近最优解的同时,依然可能出现较大的波动,这是由于其“冒进”的特性决定的;由于只取一个值,因此随机性更大,很可能出现向着反方向前进的情况,此时误差值反而会上升。所以我认为,用随机梯度下降法可以很快获得接近最优的参数,但很可能是一个局部最优解,需要通过大量的迭代才能确定确切的全局最优解

通过对比,我们不难看出不同的batchSize(每次迭代的取样个数)实际上对应着三种不同的梯度下降法,分别是:

  • SD(梯度下降法,batchSize = 样本个数
  • 小批量梯度下降法(mini-batch, batchSize in [1,max))
  • SGD(随机梯度下降法,batchSize = 1)

这三种方法按照上面的顺序,对模型训练的影响分别为:训练速度递增,训练稳定性递减(即出现波动的可能性递增)。

  1. 当batchSize上升时,计算复杂度上升,运行速度下降,运行稳定性很好;当batchSize的值取的是样本长度时,模型在运算过程中持续向最优解接近,几乎没有出现错误的前进时刻,但优化的速度较慢,而且可能出现停滞;这是因为SD(批量梯度下降法)一定能够沿着最小值的方向迈进,比较稳定,但每一次计算梯度都需要遍历所有的样本,计算量比较大。

  2. 当batchSize下降时,计算复杂度下降,运行速度上升,运行随机性增长;当batchSize的值取1时,模型在迭代的训练中快速接近理想状态,但在到达较优解时会出现较大幅度的波动;这是因为SGD(随机梯度下降法)虽然具有运算速度较快的优点,但有可能跳出局部最优解,每次迈向的方向不稳定,甚至有可能向反方向迈进。

  3. 基于这个变化特性,每次计算梯度的时候选取一部分样本来进行计算,在保证方向的基本稳定的同时又减少了计算量,提升了运行速度,也就是采用mini-batch GD是一个更优的选择。

一些补充

批归一化(BN,Batch Normalization)

原文在这

BN是由Google于2015年提出,这是一个深度神经网络训练的技巧,它不仅可以加快了模型的收敛速度,而且更重要的是在一定程度缓解了深层网络中“梯度弥散”的问题,从而使得训练深层网络模型更加容易和稳定。

what

BN就是对每一批数据进行归一化(把数据映射到0~1范围之内处理),就是对训练的每一批数据先进行标准的归一化(减均值除方差)得到0-1分布,然后再进行尺度变换和偏移,使得样本效果更好。

when

我们可以在网络中任意一层进行归一化处理

how

BN步骤主要分为4步:

  1. 求每一个训练批次数据的均值
  2. 求每一个训练批次数据的方差
  3. 使用求得的均值和方差对该批次的训练数据做归一化,获得0-1分布。其中ε是为了避免除数为0时所使用的微小正数。
  4. 尺度变换和偏移:将xi乘以γ调整数值大小,再加上β增加偏移后得到yi,这里的γ是尺度因子,β是平移因子。这一步是BN的精髓,由于归一化后的xi基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,我们引入两个新的参数:γ,β。 γ和β是在训练时网络自己学习得到的。

why


  • 标准的归一化操作将可能处于梯度很小的区域的数据移动到梯度更大的区域中,可以对抗梯度消失的现象。对每一层数据都进行这样的操作,那么数据总是分布在变化敏感的区域,使得训练效率提升。
  • 由于归一化操作得到的分布是正态分布,对某些训练样本的特征分布表现不好,即削弱了网络的性能;因此此加入BN中第四步的尺度变换和偏移,利用优化变一下方差大小和均值位置,使得新的分布更切合数据的真实分布,保证模型的非线性表达能力。

CNN中的BN

注意前面写的都是对于一般情况,对于卷积神经网络有些许不同。因为卷积神经网络的特征是对应到一整张特征响应图上的,所以做BN时也应以响应图为单位而不是按照各个维度。比如在某一层,batch大小为m,响应图大小为w×h,则做BN的数据量为m×w×h。

BN在深层神经网络的作用非常明显:若神经网络训练时遇到收敛速度较慢,或者“梯度爆炸”等无法训练的情况发生时都可以尝试用BN来解决。同时,常规使用情况下同样可以加入BN来加速模型训练,甚至提升模型精度

(GN,Group normalization)

BN的一些问题:

  • BN全名是Batch Normalization,见名知意,其是一种归一化方式,而且是以batch的维度做归一化,那么问题就来了,此归一化方式对batch是independent的,过小的batch size会导致其性能下降,一般来说每GPU上batch设为32最合适,但是对于一些其他深度学习任务batch size往往只有1-2,比如目标检测,图像分割,视频分类上,输入的图像数据很大,较大的batchsize显存吃不消。
  • 另外,Batch Normalization是在batch这个维度上Normalization,但是这个维度并不是固定不变的,比如训练和测试时一般不一样,一般都是训练的时候在训练集上通过滑动平均预先计算好平均-mean,和方差-variance参数,在测试的时候,不在计算这些值,而是直接调用这些预计算好的来用,但是,当训练数据和测试数据分布有差别是时,训练机上预计算好的数据并不能代表测试数据,这就导致在训练,验证,测试这三个阶段存在inconsistency。

GN将所有channel进行分组,如下图就是将6个channel分成了2个group,1个group有3个channel。

从左到右一次是BN,LN,IN,GN
众所周知,深度网络中的数据维度一般是[N, C, H, W]或者[N, H, W,C]格式,N是batch size,H/W是feature的高/宽,C是feature的channel,压缩H/W至一个维度,其三维的表示如上图,假设单个方格的长度是1,那么其表示的是[6, 6,, ]

  • BN在batch的维度上norm,归一化维度为[N,H,W],对batch中对应的channel归一化;
  • LN避开了batch维度,归一化的维度为[C,H,W];
  • IN 归一化的维度为[H,W];
  • 而GN介于LN和IN之间,其首先将channel分为许多组(group),对每一组做归一化,及先将feature的维度由[N, C, H, W]reshape为[N, G,C//G , H, W],归一化的维度为[C//G , H, W]

主要优点

  • 卷积提取的特征本身分类,并不是完全独立的,某些特征具有相同的分布,因此可以使用group分割样本。
  • GN对batch size的鲁棒性更强,GN的归一化方式避开了batch size对模型的影响。

解读原文

归一化、正则化、标准化

很混乱,关于三者的参考链接

某个学习笔记

某个话题

  • 归一化:一般就是将数据映射到指定的范围,如将数据全部映射到[0,1]区间。对数据的数值范围进行特定缩放,但不改变其数据分布的一种线性特征变换。
    • 英文称呼
      • Rescaling
      • min-max normalization
      • mean normalization
    • 作用:使得特征之间的不同数值不会影响权重
    • 做法:最简单的是将一组数据分别除以他们的和
    • 例子:
      • Min-max归一化
      • mean normalization

  • 标准化:对数据的分布的进行转换,使其符合某种分布(比如正态分布)的一种非线性特征变换。

    • 英文:
      • Normalization
      • standardization
      • Z-score normalization
    • 标准化后的数据更容易得出最优参数,计算出目标函数的最小值,加速收敛
    • 做法:将数据减去均值再除以标准差
    • 例子:
      • Standardization(Z-score normalization)

  • 正则化:不太懂
    • 英文:regularization
    • 作用:避免过拟合的产生和减少网络误差。选择经验风险与模型复杂度同时较小的模型。
    • 做法:
      • 其中,第 1 项是经验风险,第 2 项是正则项, λ≥0 为调整两者之间关系的系数。
文章目录
  1. 1. 2019年3月26日:梯度下降法求解多元线性模型
  2. 2. 实验目标
  3. 3. 实验背景
  4. 4. 实验原理
    1. 4.1. 梯度下降法(GD,Gradient Descent)
    2. 4.2. 随机梯度下降法(SGD,Stochastic Gradient Descent)
    3. 4.3. 小批量梯度下降法(mini-batch)
    4. 4.4. 多变量线性回归
    5. 4.5. 均方误差
  5. 5. 模型训练流程
  6. 6. 实验过程
    1. 6.1. exercise1:
    2. 6.2. ANS1:
    3. 6.3. Exercise 2:
    4. 6.4. ANS2:
    5. 6.5. Exercise 3:
    6. 6.6. ANS3:
  7. 7. 一些补充
    1. 7.1. 批归一化(BN,Batch Normalization)
      1. 7.1.1. what
      2. 7.1.2. when
      3. 7.1.3. how
      4. 7.1.4. why
      5. 7.1.5. CNN中的BN
    2. 7.2. (GN,Group normalization)
      1. 7.2.1. BN的一些问题:
    3. 7.3. 归一化、正则化、标准化