使用 exported/reloaded 模型进行 fastai 错误预测:"Input type and weight type should be the same"
fastai error predicting with exported/reloaded model: "Input type and weight type should be the same"
每当我导出一个 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: Input type (torch.cuda.FloatTensor) and weight type
(torch.cuda.HalfTensor) should be the same"
逐条执行代码,一切正常,直到最后一行 pred = ...
出现上面的 torch 错误。
相关软件版本:
Python 3.7.3
法泰 1.0.57
手电筒 1.2.0
火炬视觉 0.4.0
如果你有 .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) 如我的评论所述,在混合精度模式下训练(设置 conv_learner
to_fp16()
)导致 exported/reloaded 模型
出现错误
2) 要在混合精度模式下训练(比常规训练更快)并启用 export/reload 模型而不会出现错误,只需在导出前将模型设置回默认精度即可。
...在代码中,只需更改上面的示例:
# 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()
...现在上面的完整(可重现)代码示例运行时没有错误,包括模型重新加载后的预测。
每当我导出一个 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: Input type (torch.cuda.FloatTensor) and weight type (torch.cuda.HalfTensor) should be the same"
逐条执行代码,一切正常,直到最后一行 pred = ...
出现上面的 torch 错误。
相关软件版本:
Python 3.7.3
法泰 1.0.57
手电筒 1.2.0
火炬视觉 0.4.0
如果你有 .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) 如我的评论所述,在混合精度模式下训练(设置 conv_learner
to_fp16()
)导致 exported/reloaded 模型
2) 要在混合精度模式下训练(比常规训练更快)并启用 export/reload 模型而不会出现错误,只需在导出前将模型设置回默认精度即可。
...在代码中,只需更改上面的示例:
# 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()
...现在上面的完整(可重现)代码示例运行时没有错误,包括模型重新加载后的预测。