CNN人群计数模型中ConvTranspose2d引发输入与权重张量类型不匹配问题排查
问题原因与解决方案
这个错误的核心原因很明确:你的输入张量(真实数据)已经被放到GPU上了(类型是torch.cuda.FloatTensor),但你在forward方法里临时创建的ConvTranspose2d层的权重还停留在CPU上(类型是torch.FloatTensor),两者设备不匹配导致了类型冲突。
为什么虚拟张量测试没问题?
你测试用的虚拟张量大概率是在CPU上生成的,这时候临时创建的upsample层默认也在CPU,输入和权重的设备一致,所以不会报错。但真实数据处理时,你应该是把整个模型和输入数据都移到了GPU(比如用model.cuda()或model.to('cuda')),但这个临时创建的上采样层并没有同步移过去,就出现了类型不匹配。
修复方案
有两种简单的解决方式,推荐第一种更规范的写法:
方案1:将上采样层移到模型初始化阶段
把ConvTranspose2d的创建放到模型的__init__方法里,这样它会和其他层一起被移到GPU,避免每次forward都重新创建:
修改你的模型初始化代码:
class YourCrowdCountModel(nn.Module): def __init__(self, bn=True): super().__init__() # 原有的所有层定义... self.base = nn.Sequential(Conv2d(1, 64 ,3, same_padding=True, bn=bn), ...) self.layer1_1 = nn.Sequential(nn.MaxPool2d(2), ...) # ...其他层定义... # 添加这行,把上采样层作为模型的一部分 self.upsample = nn.ConvTranspose2d(256, 256, 3, stride=2, padding=1)
然后修改forward方法里的对应代码:
def forward(self, im_data): # 原有的前向传播逻辑... fuse_l3 = self.fuse_layer3(l3_1.add(l3_2).add(l3_3)) # 使用模型初始化好的上采样层 fuse_l3 = self.upsample(fuse_l3, output_size = fuse_l2.size()) # ...后续拼接与返回逻辑...
方案2:临时创建后手动同步设备
如果一定要在forward里动态创建上采样层,那需要在创建后马上把它移到输入张量所在的设备上:
def forward(self, im_data): # 原有的前向传播逻辑... fuse_l3 = self.fuse_layer3(l3_1.add(l3_2).add(l3_3)) upsample = nn.ConvTranspose2d(256, 256, 3, stride=2, padding=1) # 同步到fuse_l3所在的设备(和im_data设备一致) upsample = upsample.to(fuse_l3.device) fuse_l3 = upsample(fuse_l3, output_size = fuse_l2.size()) # ...后续拼接与返回逻辑...
额外提示
尽量不要在forward方法里频繁创建层,这样不仅会导致设备同步问题,还会增加不必要的开销,影响训练/推理效率。把所有固定结构的层都放到__init__里是PyTorch模型的标准写法。
内容的提问来源于stack exchange,提问作者eloreah
相关产品推荐
相关产品推荐

