什么时候使用 torch.no_grad() 在前向传播中是安全的?为什么它会严重伤害我的模型?

When to use torch.no_grad() is safe in forward propagation? Why does it hurt my model badly?

我训练了一个 CNN 模型,它的前向传播是这样的:

*Part1*: learnable preprocess​
*Part2*: Mixup which does not need to calculate gradient
*Part3*: CNN backbone and classifier head

part1part3都需要计算梯度,在back-prop时需要更新权重,但是part2 只是一个简单的 mixup,不需要梯度,所以我尝试用 torch.no_grad() 包装这个 Mixup 以节省计算资源并加快训练速度,这确实加快了我的训练速度,但模型`的预测准确率下降很多。

我想知道 Mixup 是否不需要计算梯度,为什么用 torch.no_grad() 包裹它会如此伤害模型的能力,是因为 [=31 的学习权重丢失了吗? =]Part1,或者类似打破 Part1Part2?

之间的链的东西

编辑:

感谢@Ivan 的回复,听起来很有道理,我也有同样的想法,但不知道如何证明。

在我的实验中,当我在 Part2 上应用 torch.no_grad() 时,GPU 内存消耗下降了很多,训练速度更快,所以我猜这个 Part2 即使没有可学习的参数,仍然需要梯度。

那么我们是否可以得出结论,torch.no_grad() 不应应用于 2 个或更多可学习块之间,否则会降低此 no_grad() 部分之前的块的学习能力?

but part2 is just simple mixup and don't need gradient

确实如此!为了计算梯度流并成功反向传播到模型的 part1(根据您的说法,这是可学习的),您需要计算 part2[=29 上的梯度=] 还有。即使在您的模型的 part2 上没有可学习的参数。

当您在 part2 上应用 torch.no_grad() 时,我假设发生的情况是只有您的模型的 part3 能够在 part1 保持不变的情况下学习。


编辑

So can we conclude that torch.no_grad() should not be applied between 2 or more learnable blocks, otherwise it would drop the learning ability of blocks before this no_grad() part?

原因很简单:要计算第 1 部分的梯度,您需要计算中间结果的梯度,而不管您不会使用这些梯度来更新第 2 部分的张量。所以确实,你是对的。