PyTorch模型AvgPool2d尺寸不兼容导致输出过小错误求助
修复AntispoofModel中AvgPool2d导致的RuntimeError及节点特征匹配问题
问题根源分析
- AvgPool2d尺寸不兼容:你使用的ResNet18截取了
children()[:-1],包含了最后的全局平均池化层(AdaptiveAvgPool2d(1)),输出特征图尺寸为[batch_size, 512, 1, 1]。此时用kernel_size=8的AvgPool2d计算,输出尺寸计算公式为floor((input_size - kernel_size)/stride + 1),代入后得到floor((1-8)/8 +1)=floor(1/8)=0,直接导致输出尺寸为512x0x0,触发RuntimeError。 - 节点特征与邻接矩阵不匹配:你的邻接矩阵
adj是7x7网格生成的49个节点,但当前ResNet输出是1x1的特征,无法对应49个节点,后续GAT层的输入也不符合设计预期(kwargs中nheads=49、nfeat=512明显对应49个节点的设置)。
修复方案
方案一:移除多余AvgPool2d并修正ResNet截取范围(推荐)
这是最合理的方案,因为你的目标是用ResNet提取7x7的特征图对应49个节点,所以需要去掉ResNet的全局平均池化层,同时删除无意义的AvgPool2d:
class AntispoofModel(nn.Module): def __init__(self, device="cpu", **kwargs): super().__init__() resnet = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True) # 截取到layer4,去掉最后的AvgPool2d和全连接层,输出尺寸为[batch,512,7,7] self.resnet = nn.Sequential(*[i for i in list(resnet.children())[:-2]]).to(device) for ch in self.resnet.children(): for param in ch.parameters(): param.requires_grad = False self.gat = GAT(**kwargs).to(device) self.device = device self.adj = torch.tensor(grid_to_graph(7, 7, return_as=np.ndarray)).to(device) # 移除原有的AvgPool2d层 def forward(self, x): x = self.resnet(x.to(self.device)) # shape: [batch, 512, 7, 7] # 将7x7特征图转换为49个节点的特征矩阵:[batch, 49, 512] x = x.flatten(2).transpose(1, 2) x = self.gat(x, self.adj) return torch.sigmoid(x)
方案二:仅修复AvgPool2d(不推荐,仅解决报错,不解决逻辑问题)
如果只是临时解决报错,可调整AvgPool2d参数使其输出尺寸合法,但这种方式无法解决节点特征与邻接矩阵不匹配的问题:
# 修改AvgPool2d参数为kernel_size=1,保持输出尺寸不变 self.avg_pool = nn.AvgPool2d(kernel_size=1, stride=1, padding=0, ceil_mode=False, count_include_pad=False)
或者开启ceil_mode=True,让输出尺寸向上取整为1x1:
self.avg_pool = nn.AvgPool2d(kernel_size=8, stride=8, padding=0, ceil_mode=True, count_include_pad=False)
补充说明
- 确认GAT层的输入格式:上述方案中转换后的特征矩阵
[batch, 49, 512]对应49个节点、每个节点512维特征,与你设置的nfeat=512、邻接矩阵的49节点完全匹配,符合GAT的输入要求。 - 若GAT层需要其他格式的输入,可根据实际情况调整
x的形状转换方式(如view或reshape)。
内容的提问来源于stack exchange,提问作者12345
相关产品推荐
相关产品推荐

