PyTorch中封装预训练DenseNet为nn.Sequential后输出张量异常如何解决
问题原因
你得到的[1, 1024, 7, 7]是DenseNet主干网络输出的特征图,属于正常现象,问题出在你提取模型结构的逻辑遗漏了原DenseNet的必要后处理步骤,和DenseNet的层间全连接特性无关:
原DenseNet的完整推理逻辑为:
- 经过
features主干输出4维特征图 - 过ReLU激活
- 经过自适应全局平均池化压缩为
[1, 1024, 1, 1]的张量 - 展平为
[1, 1024]的一维特征向量 - 经过最后一层全连接层
classifier输出[1, 1000]的分类结果
你用list(base_model.children())[:-1]只提取了第一步的features主干,缺少后续的激活、池化、展平步骤,因此输出为4维特征图。
正确实现方案
方案1:单独提取特征提取器,输出1024维一维特征
适合需要拿到DenseNet输出的通用特征,后续接自定义逻辑的场景:
初始化代码
import torch from torch import nn base_model = torch.hub.load('pytorch/vision:v0.10.0', 'densenet121', pretrained=True) # 可选:冻结主干参数,仅做特征提取不微调 for param in base_model.parameters(): param.requires_grad = False # 补齐缺失的后处理步骤 self.base_model = nn.Sequential( *list(base_model.children())[:-1], nn.ReLU(inplace=True), nn.AdaptiveAvgPool2d((1, 1)), nn.Flatten(start_dim=1) )
前向调用
x = self.base_model(x) # 输出尺寸为[1, 1024],符合特征向量预期
方案2:直接替换最后一层分类头
适合基于预训练DenseNet做自定义分类任务的场景,写法更简洁:
初始化代码
base_model = torch.hub.load('pytorch/vision:v0.10.0', 'densenet121', pretrained=True) # 可选:冻结主干参数,仅微调分类头 for param in base_model.parameters(): param.requires_grad = False # 替换原1000类的分类头为自定义类别数,示例为10分类 in_features = base_model.classifier.in_features base_model.classifier = nn.Linear(in_features, 10) self.base_model = base_model
前向调用
x = self.base_model(x) # 输出尺寸为[1, 10],符合自定义分类预期
注意事项
你提到的输入尺寸[1,3,244,244]属于常见笔误,官方预训练权重基于224x224输入训练,建议使用224x224的输入以获得最优精度;若使用其他尺寸输入,自适应平均池化层会自动适配,最终输出的特征向量维度仍为1024,不会影响后续逻辑。
内容的提问来源于stack exchange,提问作者itisyeetimetoday
相关产品推荐
相关产品推荐

