mini-batch Gradient Descent

                                                                                                                                  点击此处返回总目录

前面已经讲过梯度下降法家族中的批量梯度下降法(BGD)和随机梯度下降法(SGD),今天说一下mini-batch Gradient Descent(MBGD)。

  • 批量梯度下降法(Batch Gradient Descent,BGD)              //一般说的梯度下降法就是指BGD。      
  • 随机梯度下降法(Stochastic Gradient Descent, SGD)
  • 小批量梯度下降法(Mini-batch Gradient Descent, MBGD)

-----------------------------------------------------------------------------------------------------------------------

首先说一个秘密,我们其实在做Gradient descent的时候,我们并不会真的去minimize total loss(即不会用BGD),而是使用mini-batch。

                                   mini-batch Gradient Descent

我们是怎么做的呢?我们会把training data分成一个一个的batch。比如说有1万张图片,每次随机选100张进来作为一个batch,一共有100个batch。每个batch要随机的分,如果batch没有随机的分,比如说某一个batch里面统统都是1,另一个batch里面统统都是数字2,这样会对performance会有不小的影响。

                                                   mini-batch Gradient Descent

接下来再怎么做呢?

首先随机初始化参数。接下来,我们随机选一个batch出来,比如说选了第一个batch 出来。然后我们计算对第一个batch里面的element的total loss。注意不是全部training data(1万张图片)的total loss,而是这个batch的图片(100张)的total loss。L' = l 1+ l31+...。然后我们根据L'去更新参数,也就是计算参数对L'的偏微分,然后更新参数。

接下来,再随机选一个batch,比如选的是第二个batch。然后计算第二个batch里面的examples的total loss L''。L'' = l2 + l16+...。再计算参数对L''的偏微分,更新参数。

反复执行上面的过程,直到把所有的batch通通选过一次。因为共有100个batch,所以要执行100次。参数要更新100次。

把所有的batch都看过一次,叫做一个epoch。我们要重复多个epch。我们在train一个网络的时候,会需要好几十个epoch,而不是只有一个epoch。

                                           mini-batch Gradient Descent

在上一节,用keras写手写数字识别的例子中,有以下语句:

                         mini-batch Gradient Descent

 

batch_size = 100,就是告诉Keras我们的一个batch有多大,我们要把100个example放在一个batch里面。Keras会帮你随机的放,所以这里不需要自己写。nb_epoch = 20就是说一共有20个epoch,也就是蓝色框框要重复20次,也就是每一个batch被看过20次。在一个epoch里面,我们会更新很多次参数,每看一个batch就会更新一次参数。假设共有100个batch,那么在一个epoch里面会更新100次参数,20个epoch就会更新20*100次参数。并不是设置20个epoch就更新20次参数。

-----------------------------------------------------------------------------------------------------------------------

假设我们把batch size设为1的话,就是每一个元素更新一次参数。这就是我们之前讲过随机梯度下降(SGD)。

                             mini-batch Gradient Descent

我们之前讲过随机梯度下降法的好处,它的好处就是相较于批量梯度下降法,它的速度比较快。因为原来的gradient descent(没有说那种梯度下降法,一般是指批量梯度下降)更新一次参数的时候,随机梯度下降法可能已经更新100次参数了(假设有100笔training data的话),虽然说每次更新参数的方向是不稳定的,但是还是比较强的。

那你可能会问,既然随机梯度下降法比较强的话,为什么还要用mini-batch呢?是因为一些实做上的问题,让我们必须要用mini-batch。要用mini-batch的主要理由其实是实做上的需求。

我们知道,batch size 越小,在一个epoch中更新的参数的次数越多。比如,我们有5万个examples。如果我们的batch size设为1,也就是SGD的话,一个epoch中可以更新5万次参数。如果我们的batch size设为10,那在一个epoch中,我们可以更新5000次参数。这样看起来,好像是SGD比较快,因为batch size为10,在一个epoch里面才更新5000次参数;但是SGD可以更新5万次参数,SGD的速度好像是另一个的十倍。

                        mini-batch Gradient Descent

但是,实际上,当你的batch size设的不一样的时候,一个epoch需要的时间是不一样的。大家可能觉得,training data都是5万笔,设batch size为1还是10,运算量都是一个epoch,都是要把5万个example过一遍,不是一样多的么?但是在实际上,在实做上,当batch size设的不一样时,虽然是同样多的example,但是它运算的时间是不一样的。等一下会解释为什么。我们先来实际上的例子。

                    mini-batch Gradient Descent

表格是在GTX980上跑在MNIST数据集5万个training examples上面,当设不同的batch size的时候,一个epoch所需要的时间。如果batch size为1,也就是SGD,一个epoch要166秒,也就是接近3分钟。如果batch size设10的话,一个epoch是17秒。当设为100,1000,10000时,时间越来越小。我们会发现,过了166秒,上面的才算一个epoch;而下面166秒已经差不多算了10个epoch了。所以这样比较起来,batch设1跟设10,在166秒内更新参数的次数几乎是一样的。这种情况下,我们其实会想要选batch size = 10,因为选batch size等于10,会比较稳定。我们之前之所以从gradient descent换成SGD,原因就是SGDtrain得比较快,update次数比较多。可是现在用SGD,也不会更快。那为什么不选一个比较稳定,而且次数也比较多的呢?所以,我们会选择batch size 等于10.

                                      mini-batch Gradient Descent

接下来,我们的问题就是,为什么batch size设的比较大的时候,速度会比较快。这个就是因为,我们使用了并行运算,使用了GPU。因为使用了GPU,所以batch size等于10 的这个10个example,是会同时运算的。所以算10个example的时间,跟算1个example的时间,其实几乎是一样的。(这个一会再讲为什么。)

那既然batch size越大会越稳定,而且batch size变大,还是可以并行运算。那为什么不把batch size开的超级大呢?这有两个原因。

  • 一个原因是如果你把batch size开到很大,最终GPU会没有办法并行运算。GPU终究是有它的极限的。也就是同时考虑10个example和同时考虑1个example,时间是一样的。但是它同时考虑1万个example的时候,时间就不会跟1个example一样。所以,考虑到硬件的限制的话,batch size不能无穷尽的增长。
  • 另外一个batch size不能设太大的理由是,如果把batch size设置很大,在做deep learning的时候,跑两下,网络就卡住了,就陷到局部极小值或者saddle point(鞍点)去了。因为在neural network的error surface上面,它不是一个凸优化问题,而是有很多坑坑洞洞,如果用原来的gradient descent(即batch size = examples 数 ),你就会完全顺着total loss的方向走,没走两步就卡住了,就没有办法再train了。这时候performace 就会很差。但是用SGD的好处,就是如果你有随机性,每一次你走的方向会是随机的,所以如果今天走某一步陷到一个local minimum或者鞍点,如果这个局部最小值不是一个很深的局部最小值,或者那个鞍点不是一个特别麻烦的鞍点,你只要下一步再加一点random,就可以挑出那个gradient是0的区域了。所以,你没有这个随机性的话,神经网络其实是会有问题的,才update没几次就会卡住。所以这个mini-batch是需要的。

-----------------------------------------------------------------------------------------------------------------------

接下我们要解释,当有batch的时候,GPU是如何平行的加速。在深度学习介绍中说,整个网络可以看成是一连串的矩阵运算的结果,不管是Forward pass还是backward pass。forward pass 就是图上这样,backward pass 也相似。

                 mini-batch Gradient Descent

我们可以比较SGD与mini-batch的区别,即batch size=1与batch=10的差别。

如果batch size = 1,即SGD时。会读入一个example x,然后进行一些列矩阵运算,最后更新一次参数。我们只展示第一个Layer,会进行以下运算:

                                      mini-batch Gradient Descent           (1)

当更新完一次参数后,会读第二个example x,再进行一些列矩阵运算,最后更新第二次参数。同样展示一下,第一个Layer的运算:

                                      mini-batch Gradient Descent              (2)

但是在mini-batch的时候,会把同一个batch的input统统集合起来,每一个input是一个向量。如下图,会把黄色的x,和绿色的x拼起来,成为一个矩阵。再用这个矩阵乘W1,就可以直接得到z1和z2。

                  mini-batch Gradient Descent          (3)

在理论上,先算(1)再算(2)的总时间跟算(3)的时间理论上,运算量是一样的。但是就实做上,做(3)的速度是比较快的。因为让GPU做(1)运算,和做(3)运算,时间其实是一样的。对GPU来说,矩阵相乘里面的每一个element x都是可以并行运算的。所以(1)+(2)的运算时间反而会变成(3)运算的时间的两倍。

这就是为什么我们用mini-batch,再加上GPU的时候,是可以加速的。但是如果只有GPU,但是没有用mini-batch的话,其实就加速不了太多。所以有的人买来GPU,但是他不知道用mini-batch,导致装了GPU也没变快。