【问题标题】:Evaluating pytorch models: `with torch.no_grad` vs `model.eval()`评估 pytorch 模型:`with torch.no_grad` vs `model.eval()`
【发布时间】:2019-09-01 19:28:06
【问题描述】:

当我想在验证集上评估我的模型的性能时,是首选使用with torch.no_grad: 还是model.eval()?

【问题讨论】:

标签: python machine-learning deep-learning pytorch autograd


【解决方案1】:

TL;DR:

Use both。他们做的事情不同,范围也不同。

  • with torch.no_grad - 在autograd 中禁用渐变跟踪。
  • model.eval() 更改了调用它的模块的 forward() 行为
  • 例如,它禁用 dropout 并使用整个人口统计数据进行批量标准化

with torch.no_grad

torch.autograd.no_grad documentation 说:

禁用 [原文如此] 梯度计算的上下文管理器。

当您确定不会调用Tensor.backward() 时,禁用梯度计算对推理很有用。它将减少原本具有requires_grad=True 的计算的内存消耗。在这种模式下,每次计算的结果都会有requires_grad=False,即使输入有requires_grad=True。

model.eval()

nn.Module.eval documentation 说:

将模块设置为评估模式。

这仅对某些模块有任何影响。如果它们受到影响,请参阅特定模块的文档以了解其在训练/评估模式下的行为的详细信息,例如Dropout、BatchNorm等


The creator of pytorch said the documentation should be updated to suggest the usage of both,我提出了pull request。

【讨论】:

    【解决方案2】:

    with torch.no_grad: 禁用 backward 通道的梯度计算。由于这些计算在推理过程中是不必要的,并且会增加非平凡的计算开销,因此在评估模型的速度时使用此上下文是必不可少的。但不会影响结果。

    model.eval() 确保 certain modules 在 forward 推理过程中正确定义训练与推理中的不同行为(例如 Dropout 和 BatchNorm)。因此,如果您的模型包含此类模块,则必须启用此功能。

    由于上述原因,在推理过程中同时使用两者是一种很好的做法。

    【讨论】:

      【解决方案3】:

      如果您阅读这篇文章是因为您遇到了RuntimeError: CUDA out of memory,那么with torch.no grad(): 可能有助于节省内存。仅使用 model.eval() 不太可能有助于解决 OOM 错误。

      原因是torch.no grad() 完全禁用了 autograd(您不能再反向传播),从而减少内存消耗并加快计算速度。

      但是,您仍然可以在使用model.eval() 时呼叫警卫。就个人而言,我觉得这个设计决定很有趣。那么,.eval() 的目的是什么?它的主要功能似乎是在评估期间停用 Dropout。

      总而言之,如果您使用 torch.no grad(),则不会保存任何中间张量,并且您可以在推理中增加批量大小。

      【讨论】:

        猜你喜欢
        • 2021-12-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-05
        • 2020-12-26
        • 2020-08-18
        • 2019-09-29
        • 2021-06-06
        • 2017-03-24
        相关资源
        最近更新 更多