【炼丹随记】梯度累加

相关介绍

当显卡资源不够用时,除了使用混合精度训练,还可以使用梯度累加。具体介绍如下

  • 计算过程:
    把一个大的batch分成 N 个小的batch计算梯度,每次梯度除以累计次数,然后进行梯度累加,这样 N 次累加后的梯度就近似为 大batch 计算出来的梯度。
  • 存在问题:
    这种模拟是近似的,其中 BN 层仍然按照实际的 小batch 计算更新的。
  • 实际使用:
    尽量保证 小batchsize 大于等于16,让BN的参数得到较好的性能(可以了解batch的设置对应的BN的性能,在batchsize=8时,性能已经开始下降了)。
    【炼丹随记】梯度累加_第1张图片
    在分类任务中, 梯度累计经常使用,是因为分类任务中划分小batch时,batchsize 也比较大(一般大于32),对BN 影响较小。
    在目标检测任务,总的batchsize就比较小,划分小batch会影响 BN 的误差,所以在目标检测中较少使用梯度累加。但如果电脑性能ok,或使用了分布式训练DDP时,也会使用 torch.nn.SyncBatchNorm.convert_sync_batchnorm(model),变相的增加了BN 的计算的batchsize,也可以在目标检测中使用梯度累计。

pytorch 的代码实现

获取数据标签、计算网络输出、计算loss 、loss/累加次数、loss反向传播计算梯度、累加 N 次后 梯度更新、梯度清零

inputs, labels = inputs.cuda(), labels.cuda()
outputs = model(inputs) 
loss = criterion(outputs, labels) 
loss = loss / args.accumulation_steps  #把一个大的batch分成 N 个小的batch计算梯度,每次梯度除以累计次数
loss.backward()             # 进行反向传播,并不立即进行梯度更新,以及不立即梯度清零。也就是进行梯度累加

if iter_index % args.accumulation_steps == 0:
    optimizer.step()           # 累加N次后,进行梯度更新
    optimizer.zero_grad()

你可能感兴趣的:(深度学习)