通俗理解深度学习梯度累加(Gradient Accumulation)的原理

首先你得明白什么是梯度,可以看我之前写的一篇博客 :

微分与梯度的概念理解

本质上,梯度是一种方向导数,是一个矢量,因此这里的梯度累加并不是简单的相加,而是类似于初高中物理学的力的合成,梯度作为一种方向导数(矢量)的其累加的效果就是将各个小的梯度合成为一个指向Loss function 最终优化方向的梯度。

这里结合代码理解一下:

正常训练的过程

for i, (images, labels) in enumerate(train_data):
    # 1. forwared 前向计算
    outputs = model(images)
    loss = criterion(outputs, labels)

    # 2. backward 反向传播计算梯度
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

梯度累加的训练过程

# 梯度累加参数
accumulation_steps = 4


for i, (images, labels) in enumerate(train_data):
    # 1. forwared 前向计算
    outputs = model(imgaes)
    loss = criterion(outputs, labels)

    # 2.1 loss regularization loss正则化
    loss += loss / accumulation_steps

    # 2.2 backward propagation 反向传播计算梯度
    loss.backward()

    # 3. update parameters of net
    if ((i+1) % accumulation)==0:
        # optimizer the net
        optimizer.step()
        optimizer.zero_grad() # reset grdient

以上代码来自:

https://www.zhihu.com/question/435093513/answer/2302992975

可以看出,梯度累加的训练过程中,每次反向传播都会计算出一个梯度,但是并不会使用optimizer.step() 更新参数,直到达到设定的累计次数后,才一次性的将参数依据累积的梯度进行更新。(殊途同归,每次计算出来的梯度可以看作是一个具有微弱方向变化的矢量,不断叠加,最终合成一个具有特定方向的矢量。每次变化一点点,和将每次一点点的变化累积起来形成一个最终的变化方向,这在效果上是没有太大差异的),梯度累积可以实现和使用大的Batch Size 接近的效果,但是消耗的GPU显存却不会显著增加,这在GPU显存有限的情况下,是一种较为不错的训练方法。

你可能感兴趣的:(深度学习,深度学习,人工智能,python)