为什么我们在 PyTorch 中将学习率乘以梯度累积步骤?

问题描述 投票:0回答:1

pytorch 中的损失函数使用“平均”减少。因此,这意味着在给定任何批量大小的情况下,模型梯度将具有大致相同的大小。当你增加批次大小时,你想扩大学习率是有道理的,因为你的梯度不会随着你增加批次大小而变大。

对于 PyTorch 中的梯度累积,它将“求和”梯度 N 次,其中 N 是您在调用

backward()
之前调用
step()
的次数。我的直觉是这会增加梯度的幅度,你应该降低学习率,或者至少不要增加它。

但是我看到有人在this repo中写了乘法到梯度累加步骤:

if args.scale_lr:
    args.learning_rate = (
        args.learning_rate * args.gradient_accumulation_steps * args.train_batch_size * accelerator.num_processes
    )

我在this repo中也看到了类似的代码:

model.learning_rate = accumulate_grad_batches * ngpu * bs * base_lr

我明白你为什么要通过批量大小来增加学习率。但我不明白为什么他们试图通过累积步骤的数量来提高学习率。

  1. 他们是否将损失除以 N 以减小梯度的大小?否则他们为什么要将学习率乘以累积步骤?
  2. 不同GPU的梯度是如何累加的?它是使用均值还是总和?如果是总和,为什么他们要将学习率乘以 nGPU?
python deep-learning pytorch gradient-descent learning-rate
1个回答
1
投票

我发现他们确实将loss除以N(梯度累加步数)。您可以在此处查看

accelerate
包中的示例代码:https://huggingface.co/docs/accelerate/usage_guides/gradient_accumulation

注意上面指南中的以下代码行:

loss = loss / gradient_accumulation_steps

这解释了为什么你需要将学习率乘以梯度累积步骤。

我假设 PyTorch Lightning 中也会发生相同的过程。我在这里的 github 讨论中问了一个相关的 Lightning 问题:https://github.com/Lightning-AI/lightning/discussions/17035

希望后面有人回答,

Trainer
在Lightning中也是一样的除法过程。 来自加速包的证据让我认为来自不同 GPU 的梯度也是平均的,而不是求和。如果要将它们相加,每个 GPU 上的损失必须除以 GPU 的数量。

这导致了对大多数 PyTorch 训练工作流程中的梯度的简单直觉:无论批次大小,梯度始终具有大致相同的大小。如果您在 step() 调用之前检查梯度的大小,即使您改变批量大小、梯度累积步数、GPU 数量,甚至计算机数量,它也应该大致保持不变。

© www.soinside.com 2019 - 2024. All rights reserved.