You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch训练共享分类器的VGG组合模型时报4维输入预期错误如何解决?

报错原因分析

该报错的核心是卷积层需要输入4维张量(格式为[批次大小, 通道数, 高度, 宽度]),但实际传入的是2维张量[128, 2048],具体触发点来自你代码里的3处致命错误:

  • VGG16Classifier初始化逻辑错误:你定义的VGG16Classifier的__init__参数为(num_classes=1,classifier = None,batch_norm=False),但实例化时传入了3个VGG16模型,导致参数对应完全错位,类内部依然会新建3个VGG16分支,你外部定义的model1/model2/model_star完全没有被用到。
  • 自定义损失函数逻辑错误:
    1. 损失函数里调用了未定义的self.loss_combo属性,属于笔误,应该是self.loss_star
    2. 直接调用model_star.weight、model1.weight是非法操作:VGG16类没有weight这个属性,模型权重分散在各个子模块中,直接取值会导致计算图异常,反向传播时出现路径错乱,把本该输入分类器的2维展平特征传回了卷积层,触发维度报错。
  • 训练函数变量名错误:你解压得到的数据集加载器变量是loaders_star,但代码里多处写成loaders_s,同时epoch_accuracy["val"]也属于未定义变量,都会引发运行异常。
修复步骤
  1. 修正VGG16Classifier初始化逻辑,支持传入外部VGG16分支:
class VGG16Classifier(nn.Module):
  # 调整参数列表,接收三个外部VGG分支
  def __init__(self, vgg_a, vgg_b, vgg_star, num_classes=1, classifier = None, batch_norm=False):
    super(VGG16Classifier, self).__init__()
    self._vgg_a = vgg_a
    self._vgg_b = vgg_b
    self._vgg_star = vgg_star
    self.classifier = classifier

    if (self.classifier is None):
        self.classifier = nn.Sequential(
          nn.Linear(2048, 2048),
          nn.ReLU(True),
          nn.Dropout(p=0.5),
          nn.Linear(2048, 512),
          nn.ReLU(True),
          nn.Dropout(p=0.5),
          nn.Linear(512, num_classes)
        )

  def forward(self, x1,x2,x3):
      op1 = self._vgg_a(x1)
      op1 = torch.flatten(op1,1)
      op2 = self._vgg_b(x2)
      op2 = torch.flatten(op2,1)
      op3 = self._vgg_star(x3) 
      op3 = torch.flatten(op3,1)
      
      x1 = self.classifier(op1)
      x2 = self.classifier(op2)
      x3 = self.classifier(op3)

      return x1,x2,x3

实例化代码调整为:

model1 = VGG16((1,32,32),batch_norm=True)
model2 = VGG16((1,32,32),batch_norm=True)
model_star = VGG16((1,32,32),batch_norm=True)
model_combo = VGG16Classifier(model1,model2,model_star, num_classes=1)
  1. 修正自定义损失函数的逻辑错误:
class CombinedLoss(nn.Module):
    # 新增三个VGG分支的入参,避免调用全局变量
    def __init__(self, loss_a, loss_b, loss_star, vgg1, vgg2, vgg_star, _lambda=1.0):
        super().__init__()
        self.loss_a = loss_a
        self.loss_b = loss_b
        self.loss_star = loss_star
        self.vgg1 = vgg1
        self.vgg2 = vgg2
        self.vgg_star = vgg_star
        self.register_buffer('_lambda',torch.tensor(float(_lambda),dtype=torch.float32))
    
    # 工具方法:把模型所有参数展平为1维向量
    def _flatten_params(self, model):
        return torch.cat([p.flatten() for p in model.parameters()])

    def forward(self,y_hat,y):
        loss_cls = self.loss_a(y_hat[0],y[0]) + self.loss_b(y_hat[1],y[1]) + self.loss_star(y_hat[2],y[2])
        # 计算参数正则项,修正原来的cdist用法错误
        p1 = self._flatten_params(self.vgg1)
        p2 = self._flatten_params(self.vgg2)
        p_star = self._flatten_params(self.vgg_star)
        reg = self._lambda * torch.norm(p_star - (p1 + p2), p=2) ** 2
        return loss_cls + reg

实例化损失函数时传入对应的模型:

# 示例用二分类交叉熵,可根据任务替换损失类型
criterion = CombinedLoss(
    loss_a=nn.BCEWithLogitsLoss(),
    loss_b=nn.BCEWithLogitsLoss(),
    loss_star=nn.BCEWithLogitsLoss(),
    vgg1=model1,
    vgg2=model2,
    vgg_star=model_star,
    _lambda=1.0
)
  1. 修正训练函数里的变量名:把所有loaders_s替换为loaders_star,把未定义的epoch_accuracy["val"]替换为实际的验证精度变量,比如epoch_accuracy_star_val。

内容的提问来源于stack exchange,提问作者CasellaJr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 03:15:03