IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    随机梯度下降(SGD)和Mini-batch梯度下降

    admin发表于 2024-12-15 02:27:45
    love 0

    Mini-batch Gradient Descent的主要想法

    在前面的实践中,使用“Gradient Descent”时,都是一次性把所有的数据集都考虑进去,一切似乎都没有什么问题。

    但是,在现实实践中,如果训练数据量非常大,这种方式就不适用了。试想,在前面的示例中,输入样本数据,即\( X \)(或者 \( A^{[0]}\)),其维度(或者说shape)则可能是\( 300 \times 10,000,000 \)。这会导致每一次的梯度计算量都非常大,一次迭代(epoch)的时间会很长。

    一种非常常见的、也是非常经典的梯度下降改进,就是 mini-batch gradient descent。首先,将样本分层若干小份,并单独对每个“小份”进行“Gradient Descent”,最后逐步完成所有样本的训练。完成一次所有样本的遍历,称之为一次迭代epoch。

    在神经网络的训练中,可以用下面步骤理解这个过程:

    for "a-small-batch-of-samples X^{t} " in "all-samples"
        forward  propagation on X^{t}
        backward propagation on X^{t}
        update W/b
            W^{[l]} = W^{[l]} - lr * dW^{[l]}
            b^{[l]} = b^{[l]} - lr * db^{[l]}

    相对于 mini-batch gradient descent ,前面介绍的一次把所有样本都用于训练的方法,也被称为“batch gradient descent”。

    Stochastic Gradient Descent

    在 mini-batch 中,如果每次批量的样本大小是 1 的话,那么,也称为Stochastic Gradient Descent(简称 SGD,随机梯度下降)。事实上,自开始使用 Backpropagation 算法以来,SGD就被用于提升神经网络的训练的效率。并且很快的,mini-batch gradient descent 就作为一种优化被使用。目前,mini-batch gradient descent 依旧是一种常用神经网络训练方法[1][2]。

    收敛稳定性预估

    不难想象,在“batch gradient descent”中,一次性把所有数据都用于梯度下降的算法,通常都能够获得更好的收敛速度。而在使用 mini-batch 的时候,由于不同的批次的样本在计算时,“计算梯度”都与“全局梯度”有一定的偏差,并且有时候偏差较大,有时候较小,所以,相比之下,收敛速度要慢一些。而,Stochastic Gradient Descent 则可能会更慢一些。

    可以这么理解, mini-batch 和 Stochastic Gradient Descent 都总是使用一个局部的梯度(部分样本的梯度)来预估整体的梯度方向,自然效果会差一些。

    这里我们改进了原来的神经网络实现 ssnn_bear.py,将其更新为使用 mini-batch 的 ssnn_cat.py。详细代码可以参考GitHub仓库:super simple neural network 。

    运行 ssnn_cat.py 并观察 mini-batch 的 cost 下降速度如下:

    mini-batch 迭代下cost总是在上下波动

    batch gd算法下cost下降非常稳定

    batch_size 大小的配置

    一些经验数值可能是64、128、256、512等。Mini-batch 需要在大数据量和向量化计算之间取得一个平衡,所以通常需要更具训练的设备选择合适的 batch 大小,使得每次迭代都充分利用硬件的资源。

    代码实现

    在前述的神经网络上(参考),再做了一些修改,实现了 Mini-Batch 或者随机梯度下降。

    新增 batch 大小参数

    首先,新增了 batch_size 参数表示,同时增加对应参数 batch_iteration 表示,在一次样本迭代中,总计需要循环多少次。所以,这两个参数有如下关系:

    batch_iteration = math.ceil(m/batch_size)
    对每批次样本做迭代
    batch_iteration = math.ceil(m/batch_size)
    ...
    for i in range(iteration_count):
        for i_batch in range(batch_iteration):
            ...
            # sample from i_batch*batch_size
            batch_from  = i_batch*batch_size
            batch_to    = min((i_batch+1)*batch_size,m)
            batch_count = batch_to - batch_from
            A0  = X[:,batch_from:batch_to] # column  [batch_from,batch_to)
            Y_L = Y[:,batch_from:batch_to] # Y_label [batch_from,batch_to)
            ...

    代码的其他地方,几乎不需要太大的改动。完整的代码参考:ssnn_cat.py

    参考

    • [1] Stochastic gradient descent
    • [2] https://github.com/orczhou/ssnn/blob/main/ssnn_cat.py
    • [3] https://github.com/orczhou/ssnn/blob/main/ssnn_bear.py
    • [4] https://github.com/orczhou/ssnn

    这是一个系列文章包含了,完整的文章还包括:

    • 二元函数的偏导数、方向导数、梯度
    • 99行代码构建极简的神经网络
    • 从零构建图片识别的神经网络
    • 浅层神经网络的超参数分析


沪ICP备19023445号-2号
友情链接