【Pytorch】model.eval() vs torch.no_grad()

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【Pytorch】model.eval() vs torch.no_grad()相关的知识,希望对你有一定的参考价值。

参考技术A Date: 2020/10/12

Coder: CW

Foreword:

在将模型用于推断时,我们通常都会将 model.eval() 和 torch.no_grad() 一起使用,那么这两者可否单独使用?它们的区别又在哪里?你清楚吗?之前 CW 对这块也有些迷糊,于是自己做了实验,最终得到了结论,实验过程就不在本文叙述了,仅抛出结论作为参考。

Pytorch 的模型都继承自 torch.nn.Module ,这个类有个 training 属性,而这个方法会将这个属性值设置为False,从而影响一些模型在前向反馈过程中的操作,比如 BN 和 Dropout 层。在这种情况下,BN层不会统计每个批次数据的均值和方差,而是直接使用在基于训练时得到的均值和方差;Dropout层则会让所有的激活单元都通过。

同时, 梯度的计算不受影响 ,计算流依然会存储和计算梯度, 反向传播后仍然能够更新模型的对应的权重 (比如BN层的weight和bias依然能够被更新)。

通常是通过上下文的形式使用:

这种情况将停止autograd模块的工作,即 不会自动计算和存储梯度 ,因此 能够起到加速计算过程和节省显存的作用 ,同时也说明了 不能够进行反向传播以更新模型权重 。

由上可知,在推断时将 model.eval() 与 torch.no_grad() 搭配使用,主要是出于以下几点考虑:

i). 模型中使用了诸如 BN 和 Dropout 这样的网络层,需要使用 model.eval() 来改变它们在前向过程中的操作;

ii). 为了加速计算过程和节省显存,使用torch.no_grad()

pytorch踩坑之model.eval()和model.train()输出差距很大

参考技术A 问题描述:
本人使用pytorch1.5版本,构建EfficientNet网络,在训练之前使用model.train()设置为训练模式。每次训练结束后进行验证集的推理测试;对于含有dropout和batchnorm层的神经网络在推理前需要用model.eval()设置dropout和batchnorm的冻结。但是对于推理结果,不同的输入,具有相同的输出;错误率很高,并且loss值也于训练时差距巨大。
解决方法:
这个错误可能是由于在batchnorm中的动量(momentum)设置而导致。在进行推理时,设置较大的动量值可以解决这个问题。如下:
nn.BatchNorm2d(out_planes, eps=1e-3, momentum=1))

参考:
[1] https://www.kaggle.com/c/recursion-cellular-image-classification/discussion/101997
[2] https://github.com/pytorch/pytorch/issues/4741
[3] https://discuss.pytorch.org/t/model-eval-gives-incorrect-loss-for-model-with-batchnorm-layers/7561/22

以上是关于【Pytorch】model.eval() vs torch.no_grad()的主要内容,如果未能解决你的问题,请参考以下文章

pytorch踩坑之model.eval()和model.train()输出差距很大

pytorch掉坑记录:model.eval的作用

使用 pytorch 训练和测试 CNN。有和没有 model.eval()

pytorch 笔记:validation ,model.eval V.S torch.no_grad

pytorch中model.eval()和torch.no_grad()的区别

pytorch中model.eval()和torch.no_grad()的区别