踩坑:pytorch中eval模式下结果远差于train模式介绍

首先,eval模式和train模式得到不同的结果是正常的。我的模型中,eval模式和train模式不同之处在于Batch Normalization和Dropout。Dropout比较简单,在train时会丢弃一部分连接,在eval时则不会。Batch Normalization,在train时不仅使用了当前batch的均值和方差,也使用了历史batch统计上的均值和方差,并做一个加权平均(momentum参数)。在test时,由于此时batchsize不一定一致,因此不再使用当前batch的均值和方差,仅使用历史训练时的统计值。

我出bug的现象是,train模式下可以收敛,但一旦在测试中切换到了eval模式,结果就很差。如果在测试中仍沿用train模式,反而可以得到不错的结果。为了确保是程序bug而不是算法本身就不适合于预测,我在测试时再次使用了训练集,正常情况下此时应发生过拟合,正确率一定会很高,然而eval模式下正确率仍然很低。参照网上的一些说法(Performance highly degraded when eval() is activated in the test phase
),我调大了batchsize,降低了BN层的momentum,检查了是否存在不同层使用相同BN层的bug,均不见效。有一种方法说应在BN层设置track_running_stats为False,它虽然带来了好的效果,但实际上它只不过是不用eval模式,切回train模式罢了,所以也不对。

学习了在训练过程中,如何将BN层中统计的均值和方差输出。即在forward()中,

# bn是一个BN层,torch.nn.batch_normalization(...)
print(bn.running_mean)
print(bn.running_var)

同时学习了如何输出一个Tensor自身的均值和方差,即

# x是一个Tensor,dims是需要计算的维度
print(x.cpu().detach().numpy().mean(dims)
print(x.cpu().detach().numpy().var(dims)

观察每一层的输出结果,发现出现了很大的方差,才猛然意识到自己的输入数据没有做归一化(事后想想也确实如此,毕竟模型和训练方法都是github上参考别人的,出错概率很小;反而是自己写的DataSet部分,其实是最容易出错的)。给模型加上归一化后,eval和train的结果就没有问题了。

再次验证了我的观点:越是玄学的问题,越是傻逼的bug。

补充知识:Pytorch中的train和eval用法注意点

1.介绍

一般情况,model.train()是在训练的时候用到,model.eval()是在测试的时候用到

2.用法

如果模型中没有类似于BN这样的归一化或者Dropout,model.train()和model.eval()可以不要(建议写一下,比较安全),并且model.train()和model.eval()得到的效果是一样

如果模型中有类似于BN这样的归一化或者Dropout,并且程序需要边训练和边测试,最好就是用model.eval()测试完之后,后面补一个model.train()。

其中model.train()是保证BN用每一批数据的均值和方差,而model.eval()是保证BN用全部训练数据的均值和方差;而对于Dropout,model.train()是随机取一部分网络连接来训练更新参数,而model.eval()是利用到了所有网络连接(结果是取了平均)

以上这篇踩坑:pytorch中eval模式下结果远差于train模式介绍就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Keras - GPU ID 和显存占用设定步骤

    初步尝试 Keras (基于 Tensorflow 后端)深度框架时, 发现其对于 GPU 的使用比较神奇, 默认竟然是全部占满显存, 1080Ti 跑个小分类问题, 就一下子满了. 而且是服务器上的两张 1080Ti. 服务器上的多张 GPU 都占满, 有点浪费性能. 因此, 需要类似于 Caffe 等框架的可以设定 GPU ID 和显存自动按需分配. 实际中发现, Keras 还可以限制 GPU 显存占用量. 这里涉及到的内容有: GPU ID 设定 GPU 显存占用按需分配 GPU 显存占

  • 解决Keras使用GPU资源耗尽的问题

    我们在使用GPU资源进行训练的时候,可能会发生资源耗尽的情况,那么在在这种情况,我们需要对GPU的资源进行合理的安排,具体使用办法如下: 框架:Tensorflow和Keras 方法 import tensorflow as tf import keras.backend.tensorflow_backend as KTF config = tf.ConfigProto() config.gpu_options.allow_growth=True #不全部占满显存, 按需分配 sess = tf

  • keras的load_model实现加载含有参数的自定义模型

    网上的教程大多数是教大家如何加载自定义模型和函数,如下图 这个SelfAttention层是在训练过程自己定义的一个class,但如果要加载这个自定义层,需要在load_model里添加custom_objects字典,这个自定义的类,不要用import ,最好是直接复制进再训练的模型中,这些是基本教程. ------------------分割线讲重点------------------ 如果直接运行上面的代码,会出现一个init初始化错误,如下图, 再来看看 这个SelfAttention

  • keras CNN卷积核可视化,热度图教程

    卷积核可视化 import matplotlib.pyplot as plt import numpy as np from keras import backend as K from keras.models import load_model # 将浮点图像转换成有效图像 def deprocess_image(x): # 对张量进行规范化 x -= x.mean() x /= (x.std() + 1e-5) x *= 0.1 x += 0.5 x = np.clip(x, 0, 1)

  • pytorch 模型的train模式与eval模式实例

    原因 对于一些含有batch normalization或者是Dropout层的模型来说,训练时的froward和验证时的forward有计算上是不同的,因此在前向传递过程中需要指定模型是在训练还是在验证. 源代码 [docs] def train(self, mode=True): r"""Sets the module in training mode. This has any effect only on certain modules. See documentat

  • 踩坑:pytorch中eval模式下结果远差于train模式介绍

    首先,eval模式和train模式得到不同的结果是正常的.我的模型中,eval模式和train模式不同之处在于Batch Normalization和Dropout.Dropout比较简单,在train时会丢弃一部分连接,在eval时则不会.Batch Normalization,在train时不仅使用了当前batch的均值和方差,也使用了历史batch统计上的均值和方差,并做一个加权平均(momentum参数).在test时,由于此时batchsize不一定一致,因此不再使用当前batch的均

  • 聊聊PyTorch中eval和no_grad的关系

    首先这两者有着本质上区别 model.eval()是用来告知model内的各个layer采取eval模式工作.这个操作主要是应对诸如dropout和batchnorm这些在训练模式下需要采取不同操作的特殊layer.训练和测试的时候都可以开启. torch.no_grad()则是告知自动求导引擎不要进行求导操作.这个操作的意义在于加速计算.节约内存.但是由于没有gradient,也就没有办法进行backward.所以只能在测试的时候开启. 所以在evaluate的时候,需要同时使用两者. mod

  • Pytorch 中net.train 和 net.eval的使用说明

    在训练模型时会在前面加上: model.train() 在测试模型时在前面使用: model.eval() 同时发现,如果不写这两个程序也可以运行,这是因为这两个方法是针对在网络训练和测试时采用不同方式的情况,比如Batch Normalization 和 Dropout. 训练时是正对每个min-batch的,但是在测试中往往是针对单张图片,即不存在min-batch的概念. 由于网络训练完毕后参数都是固定的,因此每个批次的均值和方差都是不变的,因此直接结算所有batch的均值和方差. 所有B

  • Pytorch中关于model.eval()的作用及分析

    目录 model.eval()的作用及分析 结论 Pytorch踩坑之model.eval()问题 比较常见的有两方面的原因 1) data 2)model.state_dict() model.eval()   vs   torch.no_grad() 总结 model.eval()的作用及分析 model.eval() 作用等同于 self.train(False) 简而言之,就是评估模式.而非训练模式. 在评估模式下,batchNorm层,dropout层等用于优化训练而添加的网络层会被关

  • JavaWeb踩坑记录之项目访问不到html文件

    踩坑问题和原因 踩坑问题 由于博主的JavaWeb是速成所以对一些知识点掌握的不是很熟,所以也就出现了今天这个问题——Tomcat访问不到html文件. 在运行是总是会出现404.每次出现这个就很烦,让人摸不着头脑.虽然这个问题其实对一些项目没有很大的影响,但是他会让我的项目目录会很杂乱.总的来说该问题就是不解决它,就会出现一堆静态资源都在一个文件夹.这可能会导致后期找一些项目的文件就得找半天. 踩坑原因 由于粗心的我把一些html文件都放在WEB-INF下面.因为WEB-INF下的资源不能直接

  • Vue插槽slot详细介绍(对比版本变化,避免踩坑)

    目录 插槽是什么? 怎么使用插槽? 基本用法 后备(默认)内容 具名插槽 作用域插槽 插槽版本变化 总结 Vue中的插槽(slot)在项目中用的也是比较多的,今天就来介绍一下插槽的基本使用以及Vue版本更新之后的插槽用法变化. 插槽是什么? 插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML.组件等,填充的内容会替换子组件的<slot></slot>标签.简单理解就是子组

  • pytorch中图像的数据格式实例

    计算机视觉方面朋友都需要跟图像打交道,在pytorch中图像与我们平时在matlab中见到的图像数据格式有所不同.matlab中我们通常使用函数imread()来轻松地读入一张图像,我们在变量空间中可看到数据的存储方式是H x W x C的顺序(其中H.W.C分别表示图像的高.宽和通道数,通道数一般为RGB三通道),另外,其中的每一个数据都是[0,255]的整数. 在使用pytorch的时候,我们通常要使用pytorch中torchvision包下面的datasets模块和transforms模

  • 深入浅析Pytorch中stack()方法

    目录 1. 概念 2. 参数 3. 举例 3.1 四个shape为[3, 3]的张量 3.1.1 dim=0的情况下,直接来看结果. 3.1.2 dim=1的情况下 3.1.2 dim=2的情况下 3.1.3 总结 3.2 7个shape为[5, 7, 4, 2]的张量 4. 理解 Torch.stack() 1. 概念 在一个新的维度上连接一个张量序列 2. 参数 tensors (sequence)需要连接的张量序列 dim (int)在第dim个维度上连接 注意输入的张量shape要完全一

  • pytorch中dataloader 的sampler 参数详解

    目录 1. dataloader() 初始化函数 2. shuffle 与sample 之间的关系 3. sample 的定义方法 3.1 sampler 参数的使用 4. batch 生成过程 1. dataloader() 初始化函数 def __init__(self, dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_mem

  • 浅谈一下Python中5种下划线的含义

    目录 1.单前导下划线:_var 2.单末尾下划线 var_ 3. 双前导下划线 __var 4.双前导和双末尾下划线 _var_ 5.单下划线 _ 1.单前导下划线:_var 当涉及到变量和方法名称时,单个下划线前缀有一个约定俗成的含义. 它是对程序员的一个提示 - 意味着Python社区一致认为它应该是什么意思,但程序的行为不受影响. 下划线前缀的含义是告知其他程序员:以单个下划线开头的变量或方法仅供内部使用. 该约定在PEP 8中有定义. 这不是Python强制规定的. Python不像J

随机推荐