2.1 Mini-batch梯度下降法
下面将学习一些优化算法能让你的神经网络运行得更快;机器学习的应用是一个高度依赖经验的过程,伴随大量迭代过程,你要训练诸多模型才能找到合适的那一个;所以,优化算法可以帮你快速地训练模型;其中一个难点是深度学习没有在大数据领域发挥最大的效果,我们可以利用一个巨大的数据集来训练神经网络,而在巨大的数据集基础上进行训练速度很慢,所以使用快速的优化算法能大大提高团队效率;
之前所学的向量化能够让你有效地对所有m个样本进行计算,允许你训练整个训练集而无需某个明确的公式,这就是为何要构造巨大的矩阵:
问题在于,当m很大时,比如mm=5,000,000时,这样进行向量化处理速度依旧很慢,因为在对整个训练集进行梯度下降时,你要做的是你必须处理整个训练集,然后才能进行一次梯度下降法,然后再重新处理500万个训练样本,再进行下一次梯度下降……
你完全可以得到一个更快的算法,如果你在处理完整个500万样本的训练集之前,先让梯度下降法处理其中的一部分,你的算法速度会更快;更具体地说,你可以将训练集分割为小一点的一些子训练集,这些子集被取名为mini-batch,假设每一个子集中都是只有1000个样本,那么就是将抽出来当作第一个样本,将抽出来当作第二个样本,……并将它记为带花括号的形式:
因此,当总共的样本数m=500万,而每个子集的样本数是1000,意味着将会有5000个mini-batch,相应地,对也进行拆分:
一般地,我们将mini-batch用输入和输出对来表示,并且总结一下符号规定:
即圆括号表示第个样本的输入、输出;
即方括号表示神经网络第层的量;
即花括号表示第个mini-batch;
并且上例中,的维度是,的维度是;
以前讲的梯度下降法向量化后叫,即同时处理整个训练集;
而指的是每次同时处理的是单个的;
mini-batch gradient descent的原理:
for循环中基本要做的是:对执行一步梯度下降法,这很像之前向量化处理m个样本的公式,只是而已,也就是说for循环里执行的本质仍然是向量化,这些代码执行一次就处理了1000个样本;
首先,对进行前向传播,即:
接下来要计算成本函数:
值得注意的是,这个式子里的是来自mini-batch的,并且表示的是中的第一个样本,比如,如果for loop运行到了,那么求和公式中实际是指所有样本中的,如果觉得这个表达并不严谨,那就改下上下标:
而这个式子后半项指的是正则项;所有上述在for loop中所做的正如之前对进行梯度下降一样,只是变成了对进行梯度下降;
最后执行反向传播计算的梯度,仍然用的是,更新权重参数:
对神经网络的第层而言:
然后要一层一层地传递将整个神经网络的参数都更新;
上述三步实现了对一个mini-batch的训练,也叫一代训练;
然后接着对下一个mini-batch进行训练,……,直到对所有mini-batch都训练完成;
epoch这个词意味着:
遍历一次训练集,在batch中仅仅意味着你做了一次梯度下降,而在mini-batch中却做了5000次梯度下降;
而如果想要多次遍历训练集,应该在for loop的外面再加一个for loop循环;
2.2 理解mini-batch梯度下降法
Batch gradient descent中一次迭代就只做一次梯度下降,一次性遍历整个训练集,因此可以预期每次迭代成本函数都会下降;
但对于mini-batch gradient descent而言,如果你作出成本函数在整个过程中的图,则并不是每次迭代都是下降的,因为一次迭代,也就是一次梯度下降只是遍历了可能1000个样本,只是遍历了子集,只是针对的处理,每次迭代都会使用不同的训练子集;
而遍历一遍完整的、全部的训练集,意味着已经做了可能5000次梯度下降,也就是5000次迭代,所以如果按进行梯度下降的次数和顺序作为横轴的正轴画图,画出,当然这不严谨,它只是代表成本函数和即mini-batch有关,将是以下的图像:总体走向朝下,但是有很多的噪声;
噪声产生的原因是什么?
也许是比较容易训练的mini-batch,所以成本函数的值会低一些,但也许由于偶然,是比较难训练的mini-batch,或许里面有一些残缺样本或出错的标签,因此成本函数的值会高一些,总之,与计算的时候使用的那个批次的有关,才会让成本函数出现上下摆动类似噪声的样子;
一个重要的事情是你要定义mini-batch的大小
一个极端情况是,此时就只有一个子集,效果和batch gradient descent一样:
另一个极端情况是,这时把它叫做“随机梯度下降”,此时每一个样本都是一个独立的mini-batch:
这两个极端情况在优化成本函数的时候有何不同?
假设下图是你想要最小化的成本函数的轮廓(等高线图),最小值在中心处,batch gradient descent从某点处开始,相对的噪声低一些幅度也大一些,不断向最小值靠近,如蓝线所属;而stochastic gradient decent从某点开始,每次迭代只对一个样本进行梯度下降,大部分时候你朝着全局最小值前进,有时却会远离最小值,可能因为那个样本给你指的方向不对,所以会有很多噪声,如紫线所示;
从平均来看,随机梯度下降最终会靠近最小值,不过有时也会方向错误,且随机梯度下降法永远不会收敛,而是会一直在最小值附近波动,不会停留在最小值处或者某个固定的位置;
实际上选择的mini-batch size应该介于1和m之间,为什么?
因为如果使用mini-batch size=1即batch gradient descent,那么在处理训练样本数量特别大的情况时,会使单次迭代过程所花的时间过长,而如果训练样本数量并不是很大比如100或1000左右,那么使用batch gradient descent也是效果很好的;
如果使用mini-batch size即stochastic gradient descent,针对每一个样本都进行一次梯度下降,并选择较小的学习率可以减小噪声,但一个巨大的缺点就是失去了所有向量化带给你的加速运算的机会,一次迭代(一次梯度下降)只能处理一个样本,导致效率比较低;
所以实际中,选择不大不小的mini-batch size,能使训练达到最快;并且好处是:
(1)可以利用向量化进行加速;
(2)不需要等待整个训练集都被处理完就可以开始进行后续的梯度下降工作,前例中,每代训练集允许我们采取5000个梯度下降步骤,并且相比于随机梯度下降,它的噪声更小,更持续地往靠近最小值的方向前进,也不一定会在小范围内波动,可以通过减小学习率来解决波动问题使他收敛到最小值处,如绿线所示。
如何选择这个中间的mini-batch size呢?
(1)如果训练集较小,一般是,采用batch gradient descent;
(2)如果训练集很大,要选用经典的值:64,128,256,512,1024(少用),这是因为计算机内存的布局和访问方式,所以将它设置为2的幂次,你的代码会运行得更快一些;
(3)确保mini-batch设置得能让你所有的可以放进你的CPU/GPU当中,这当然也和你的配置以及一个训练样本的大小有关,但如果你设置的mini-batch超过了CPU/GPU的容量,不管怎么做结果都会很糟糕;
当然,mini-batch size也是一个超参数,可能要做一个快速搜索去确定哪一个值可以让成本函数下降得最快,尝试几个2的幂次看看能否找到合适的那个值;