首页 > 技术文章 > 随机梯度下降、mini-batch梯度下降以及batch梯度下降

rezero 2020-07-11 21:22 原文

训练神经网络的时候,基本就是三个步骤:

  1. 正向计算网络输出;
  2. 计算Loss;
  3. 反向传播,计算Loss的梯度来更新参数(即梯度下降)。

在小的训练集上联系的时候,通常每次对所有样本计算Loss之后通过梯度下降的方式更新参数(批量梯度下降),但是在大的训练集时,这样每次计算所有样本的Loss再计算一次梯度更新参数的方式效率是很低的。因此就有了随机梯度下降和mini-batch梯度下降的方式。下面来具体讲讲。

批量梯度下降(Batch Gradient Descent)

上面说了,批量梯度下降就是每个epoch计算所有样本的Loss,进而计算梯度进行反向传播、参数更新:

其中,\(m\) 为训练集样本数,\(l\) 为损失函数,\(\epsilon\) 表示学习率。批量梯度下降的优缺点如下:

  • 优点
    每个epoch通过所有样本来计算Loss,这样计算出的Loss更能表示当前分类器在于整个训练集的表现,得到的梯度的方向也更能代表全局极小值点的方向。如果损失函数为凸函数,那么这种方式一定可以找到全局最优解。
  • 缺点
    每次都需要用所有样本来计算Loss,在样本数量非常大的时候即使也只能有限的并行计算,并且在每个epoch计算所有样本Loss后只更新一次参数,即只进行一次梯度下降操作,效率非常低。

随机梯度下降(Stochastic Gradient Descent)

先贴上随机梯度下降的伪代码

随机梯度下降每次迭代(iteration)计算单个样本的损失并进行梯度下降更新参数,这样在每轮epoch就能进行 \(m\) 次参数更新。看优缺点吧:

  • 优点
    参数更新速度大大加快,因为计算完每个样本的Loss都会进行一次参数更新
  • 缺点
    1.计算量大且无法并行。批量梯度下降能够利用矩阵运算和并行计算来计算Loss,但是SGD每遍历到一个样本就进行梯度计算和参数下降,无法进行有效的并行计算。
    2.容易陷入局部最优导致模型准确率下降。因为单个样本的Loss无法代替全局Loss,这样计算出来的梯度方向也会和全局最优的方向存在偏离。但是由于样本数量多,总体的Loss会保持降低,只不过Loss的变化曲线会存在较大的波动。像下图这样:

小批量梯度下降

似乎随机梯度下降和批量梯度下降走向了两个计算,那么将这两种方法中和一下呢?这就得到了min-Batch Gradient Descent。

小批量梯度下降将所有的训练样本划分到 \(batches\) 个min-batch中,每个mini-batch包含 \(batch_size\) 个训练样本。每个iteration计算一个mini-batch中的样本的Loss,进而进梯度下降和参数更新,这样兼顾了批量梯度下降的准确度和随机梯度下降的更新效率。
可以看到,当 \(batch\_size=m\) 时,小批量梯度下降就变成了批量梯度下降;当 \(batch\_size=1\) ,就退化为了SGD。一般来说 \(batch\_size\) 取2的整数次方的值。

注意,这里有个坑!

事实上,我们平时用梯度下降的时候说的最多的SGD指的是小批量梯度下降,各种论文里所说的SGD也大都指的mini-batch梯度下降这种方式。tensorflow中也是通过定义batch_size的方式在优化过程中使用小批量梯度下降的方式(当然,也取决于batch_size的设置)。

推荐阅读