使用 pytorch 训练和测试 CNN。有和没有 model.eval()
Posted
技术标签:
【中文标题】使用 pytorch 训练和测试 CNN。有和没有 model.eval()【英文标题】:Training and testing CNN with pytorch. With and without model.eval() 【发布时间】:2019-09-20 17:53:38 【问题描述】:我有两个问题:-
我正在尝试训练一个用一些预先训练的权重初始化的卷积神经网络(Netwrok 也包含批量归一化层)(参考here)。在训练之前,我想使用loss_fn = torch.nn.MSELoss().cuda()
计算验证错误。
在参考文献中,作者在计算验证错误之前使用了model.eval()
。但是有了这个结果,CNN 模型偏离了它应该是的状态,但是当我注释掉 model.eval()
时,输出很好(预训练的权重应该是什么)。这背后的原因是什么,正如我在许多帖子中看到的那样,在测试模型之前应该使用model.eval
,在训练模型之前应该使用model.train()
。
在使用预先训练的权重和上述损失函数计算验证误差时,批量大小应该是多少。它不应该是 1,因为我想在每个输入上输出,用基本事实计算误差,最后取所有结果的平均值。如果我使用更高的批量大小错误会增加。所以问题是我可以使用更高的批量大小,如果是的话应该是正确的方法。在给定的代码中,我给出了err = float(loss_local) / num_samples
,但我观察到没有平均,即err = float(loss_local)
。不同批次大小的误差是不同的。我现在在没有model.eval
的情况下这样做。
batch_size = 1
data_path = 'path_to_data'
dtype = torch.FloatTensor
weight_file = 'path_to_weight_file'
val_loader = torch.utils.data.DataLoader(NyuDepthLoader(data_path, val_lists),batch_size=batch_size, shuffle=True, drop_last=True)
model = Model(batch_size)
model.load_state_dict(load_weights(model, weight_file, dtype))
loss_fn = torch.nn.MSELoss().cuda()
# model.eval()
with torch.no_grad():
for input, depth in val_loader:
input_var = Variable(input.type(dtype))
depth_var = Variable(depth.type(dtype))
output = model(input_var)
input_rgb_image = input_var[0].data.permute(1, 2, 0).cpu().numpy().astype(np.uint8)
input_gt_depth_image = depth_var[0][0].data.cpu().numpy().astype(np.float32)
pred_depth_image = output[0].data.squeeze().cpu().numpy().astype(np.float32)
print (format(type(depth_var)))
pred_depth_image_resize = cv2.resize(pred_depth_image, dsize=(608, 456), interpolation=cv2.INTER_LINEAR)
target_depth_transform = transforms.Compose([flow_transforms.ArrayToTensor()])
pred_depth_image_tensor = target_depth_transform(pred_depth_image_resize)
#both inputs to loss_fn are 'torch.Tensor'
loss_local += loss_fn(pred_depth_image_tensor, depth_var)
num_samples += 1
print ('num_samples '.format(num_samples))
err = float(loss_local) / num_samples
print('val_error before train:', err)
【问题讨论】:
请为问题单独发帖以缩小范围,并与How to Ask保持一致。此外,对于您的第一个问题,PyTorch 参考资料对此主题进行了大量讨论。 【参考方案1】:这可能是什么原因,正如我在许多帖子中所读到的那样,在测试模型之前应该使用 model.eval,在训练之前应该使用 model.train()。
注意:测试模型称为推理。
如官方documentation解释:
请记住,在运行推理之前,您必须调用
model.eval()
将 dropout 和批量归一化层设置为评估模式。不这样做会产生不一致的推理结果。
因此,一旦您从文件加载模型并进行推理,此代码必须存在。
# Model class must be defined somewhere
model = torch.load(PATH)
model.eval()
这是因为 dropout 在训练过程中用作防止过拟合的正则化,推理不需要它。批次规范也是如此。
当您使用eval()
时,这只会将模块序列标签设置为False
,并且仅影响某些类型的模块,尤其是Dropout
和BatchNorm
。
【讨论】:
以上是关于使用 pytorch 训练和测试 CNN。有和没有 model.eval()的主要内容,如果未能解决你的问题,请参考以下文章
AI常用框架和工具丨13. PyTorch实现基于CNN的手写数字识别
AI常用框架和工具丨13. PyTorch实现基于CNN的手写数字识别
AI常用框架和工具丨13. PyTorch实现基于CNN的手写数字识别
PyTorch从头搭建并训练一个神经网络模型(图像分类CNN)