使用导出/重新加载的模型预测fastai错误:“输入类型和权重类型应该相同”

时间:2019-08-23 00:38:41

标签: python deep-learning pytorch fast-ai

每当我导出fastai模型并重新加载它时,当我尝试使用重新加载的模型在新的测试集上生成预测时,都会遇到此错误(或非常类似的错误):

RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.cuda.HalfTensor) should be the same

下面的最小可复制代码示例,您只需要将FILES_DIR变量更新为MNIST数据在系统上的存放位置即可。

from fastai import *
from fastai.vision import *

# download data for reproduceable example
untar_data(URLs.MNIST_SAMPLE)
FILES_DIR = '/home/mepstein/.fastai/data/mnist_sample'  # this is where command above deposits the MNIST data for me


# Create FastAI databunch for model training
tfms = get_transforms()
tr_val_databunch = ImageDataBunch.from_folder(path=FILES_DIR,  # location of downloaded data shown in log of prev command
                                train = 'train',
                                valid_pct = 0.2,
                                ds_tfms = tfms).normalize()

# Create Model
conv_learner = cnn_learner(tr_val_databunch, 
                           models.resnet34, 
                           metrics=[error_rate]).to_fp16()

# Train Model
conv_learner.fit_one_cycle(4)

# Export Model
conv_learner.export()  # saves model as 'export.pkl' in path associated with the learner

# Reload Model and use it for inference on new hold-out set
reloaded_model = load_learner(path = FILES_DIR,
                              test = ImageList.from_folder(path = f'{FILES_DIR}/valid'))

preds = reloaded_model.get_preds(ds_type=DatasetType.Test)

输出:

  

“ RuntimeError:输入类型(torch.cuda.FloatTensor)和权重类型   (torch.cuda.HalfTensor)应该相同”

逐步执行代码语句,直到最后一行pred = ...为止,一切正常,直到出现上面的割炬错误。任何帮助将不胜感激!

相关软件版本:

Python 3.7.3 fastai 1.0.57
火炬1.2.0
火炬视觉0.4.0

2 个答案:

答案 0 :(得分:2)

如果您有.to_fp16,则模型的精度为半精度,如果在PyTorch中为model.half(),则精度是相同的。

实际上,如果您跟踪代码.to_fp16,则会调用model.half() 但有一个问题。如果将批处理标准层也转换为半精度,则可能会出现收敛问题。

这就是为什么您通常会在PyTorch中这样做:

model.half()  # convert to half precision
for layer in model.modules():
  if isinstance(module, torch.nn.modules.batchnorm._BatchNorm):      
    layer.float()

这会将除批处理规范外的任何层转换为半精度。

请注意,来自PyTorch forum的代码也可以,但仅适用于nn.BatchNorm2d

然后使用to()来确保输入的精度是一半:

import torch
t = torch.tensor(10.)
print(t)
print(t.dtype)
t=t.to(dtype=torch.float16)
print(t)
print(t.dtype)
# tensor(10.)
# torch.float32
# tensor(10., dtype=torch.float16)
# torch.float16

答案 1 :(得分:1)

因此,答案很简单:

1)如我的评论所述,在混合精度模式下进行的训练(设置conv_learner to_fp16())导致导出/重新加载的模型出现错误

2)要以混合精度模式进行训练(比常规训练更快)并启用没有错误的模型导出/重新加载,只需在导出之前将模型设置回默认精度即可。

...在代码中,只需更改上面的示例:

# Export Model
conv_learner.export()

收件人:

# Export Model (after converting back to default precision for safe export/reload
conv_learner = conv_learner.to_fp32()
conv_learner.export()

...现在,上面的完整(可重现)代码示例运行无误,包括重新加载模型后的预测。