踩坑: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。

  • 31
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 36
    评论
PyTorch ,`eval()` 函数主要用于将模型设置为评估模式。在评估模式下,模型不会更新梯度,从而可以更快地进行前向传播。以下是 `eval()` 函数的一些常见用法: 1. 设置模型为评估模式 在训练模型时,通常使用 `model.train()` 将模型设置为训练模式,使用 `model.eval()` 将模型设置为评估模式。在评估模式下,模型的一些层(例如 Dropout)会被禁用,从而确保在评估时得到一致的结果。 例如,以下代码将模型设置为评估模式: ``` model.eval() ``` 2. 计算模型的验证损失 在训练过程,通常需要计算模型在验证集上的损失。在计算损失之前,需要将模型设置为评估模式,以确保在计算损失时不会更新梯度。 例如,以下代码计算模型在验证集上的损失: ``` model.eval() with torch.no_grad(): for batch_idx, (data, target) in enumerate(val_loader): output = model(data) loss = criterion(output, target) val_loss += loss.item() * data.size(0) val_loss /= len(val_loader.dataset) ``` 在上面的代码,使用 `with torch.no_grad()` 将所有计算操作都设置为不需要计算梯度,从而提高计算效率。 3. 部署模型 在将模型部署到生产环境时,通常需要将模型设置为评估模式,以确保模型的输出是确定性的,并且在不同的硬件和操作系统上的结果是一致的。 例如,以下代码加载模型并将其设置为评估模式: ``` model = MyModel() model.load_state_dict(torch.load('model.pt')) model.eval() ``` 在上面的代码,使用 `load_state_dict()` 函数加载模型的权重,然后使用 `eval()` 函数将模型设置为评估模式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值