PyTorch报错RuntimeError:预期Double却发现Float求解决
问题解决:RuntimeError: expected scalar type Double but found Float
问题代码
def encoder_block(inp, max_pool, in_channels): conv = torch.nn.Conv2d(in_channels=in_channels, out_channels=64, kernel_size=3, padding='same')(inp.double()) relu = torch.nn.ReLU()(conv) conv = torch.nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding='same')(relu) relu = torch.nn.ReLU()(conv) if max_pool: return torch.nn.MaxPool2d(2,2)(relu) return relu test_load = nib.load(fpath).get_fdata() test_numpy = test_load[:,:,0].reshape(1,1,256,256).astype(np.double) tens = torch.DoubleTensor(test_numpy) out = encoder_block(tens, True, 1)
这段代码读取本地NIfTI文件转为numpy数组后,对2D图像执行卷积操作做基础测试,但运行时第一个Conv2d处报错RuntimeError: expected scalar type Double but found Float。
问题原因
PyTorch中,torch.nn.Conv2d实例化时默认使用Float32类型的权重和偏置参数,但你把输入转成了Double64类型。框架要求输入张量的 dtype 必须和模型层参数的 dtype 完全一致,否则就会出现类型不匹配错误。另外,每次调用encoder_block都重新实例化卷积层,不仅浪费资源,也会导致参数类型始终和输入不匹配。
修复方案
有两种常用的修复方式,选其一即可:
方式一:将输入转为Float32(推荐,符合PyTorch默认训练习惯)
直接把输入张量转为Float类型,不需要修改层的参数类型:
def encoder_block(inp, max_pool, in_channels): # 提前实例化层,避免重复初始化 conv1 = torch.nn.Conv2d(in_channels=in_channels, out_channels=64, kernel_size=3, padding='same') conv2 = torch.nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding='same') max_pool_layer = torch.nn.MaxPool2d(2,2) conv = conv1(inp) relu = torch.nn.ReLU()(conv) conv = conv2(relu) relu = torch.nn.ReLU()(conv) if max_pool: return max_pool_layer(relu) return relu test_load = nib.load(fpath).get_fdata() # 转为float32类型 test_numpy = test_load[:,:,0].reshape(1,1,256,256).astype(np.float32) tens = torch.FloatTensor(test_numpy) out = encoder_block(tens, True, 1)
方式二:将卷积层参数转为Double64类型
如果必须使用Double类型输入,需要把所有卷积层的参数也转为Double:
def encoder_block(inp, max_pool, in_channels): conv1 = torch.nn.Conv2d(in_channels=in_channels, out_channels=64, kernel_size=3, padding='same').double() conv2 = torch.nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding='same').double() max_pool_layer = torch.nn.MaxPool2d(2,2) conv = conv1(inp) relu = torch.nn.ReLU()(conv) conv = conv2(relu) relu = torch.nn.ReLU()(conv) if max_pool: return max_pool_layer(relu) return relu test_load = nib.load(fpath).get_fdata() test_numpy = test_load[:,:,0].reshape(1,1,256,256).astype(np.double) tens = torch.DoubleTensor(test_numpy) out = encoder_block(tens, True, 1)
额外优化建议
更规范的做法是把编码器块定义为PyTorch的nn.Module子类,统一管理层的参数和类型,也方便后续扩展:
class EncoderBlock(torch.nn.Module): def __init__(self, in_channels, max_pool=True): super().__init__() self.max_pool = max_pool self.conv_layers = torch.nn.Sequential( torch.nn.Conv2d(in_channels, 64, kernel_size=3, padding='same'), torch.nn.ReLU(), torch.nn.Conv2d(64, 64, kernel_size=3, padding='same'), torch.nn.ReLU() ) if self.max_pool: self.pool = torch.nn.MaxPool2d(2,2) def forward(self, x): x = self.conv_layers(x) if self.max_pool: x = self.pool(x) return x # 使用示例 test_load = nib.load(fpath).get_fdata() test_numpy = test_load[:,:,0].reshape(1,1,256,256).astype(np.float32) tens = torch.FloatTensor(test_numpy) encoder = EncoderBlock(in_channels=1, max_pool=True) out = encoder(tens)
内容的提问来源于stack exchange,提问作者Ryan Marr
相关产品推荐
相关产品推荐

