RuntimeError: mat1 and mat2 shapes cannot be multiplied (5760x6 and 128x4)

本文详细阐述了在使用PyTorch定义深度学习模型时遇到的卷积神经网络(CNN)层间形状不匹配问题,通过实例演示如何调整网络结构,包括添加Flatten层和额外全连接层,以确保网络正常运行并成功训练。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用pytorch框架定义子类网络结构时,有时可能会出现mat1和mat2的形状不匹配的这种问题。如下,定义了一个7层的cnn网络:

class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=1,
                out_channels=16,
                kernel_size=3,
                stride=1,
                padding=1
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(16,32,3,1,1),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(32,64,2,1,1),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.out = nn.Linear(128,4)
    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        output = self.out(x)
        return output

此时就会出现如下的错误 :

这种问题源于所定义的最后一层池化层输出的形状和全连接层输入的形状不一样。我们通过在前向传播函数中打印池化层的输出形状可知:

def forward(self,x):
    x = self.conv1(x)
    x = self.conv2(x)
    print(x.shape)
    output = self.out(x)
    return output


>> torch.Size([30, 32, 6, 6])  #池化层输出形状

([30, 32, 6, 6]) 其中的30是设置的batch_size,后三维才是其真正的形状,而全连接层的输入是一维特征,因此需要添加一个flatten层进行压平操作。压平后如下:

torch.Size([30, 1152])

鉴于pytorch框架的特点, 需要再添加一个全连接层来衔接压平层和最后一层全连接层,其输入形状为1152,输出为128。(即在以上代码conv3和out再封装一个层):

    def __init__(self):
        super(CNN,self).__init__()
      ...... 
         self.conv3 = nn.Sequential(
            nn.Conv2d(32,64,2,1,1),
            nn.ReLU(),    
            nn.MaxPool2d(2),
        )
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(1152,128),
            nn.Linear(128,4),
        )

    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        output = self.out(x)
        return output

代码不再报错,训练网络成功。 

 

### 解决方案 该错误通常发生在矩阵乘法操作期间,当两个张量的维度不兼容时会引发此问题。具体来说,在 PyTorch 中执行 `torch.matmul` 或类似的线性层计算时,如果输入张量和权重张量的形状不符合矩阵乘法规则,则会出现这种错误。 #### 错误分析 在 VGG16 模型应用于 CIFAR-10 数据集的情况下,可能的原因包括以下几个方面: 1. **图像尺寸与模型期望不符** VGG16 默认接受 224x224 大小的 RGB 图像作为输入[^1]。然而,CIFAR-10 的图像是 32x32 像素大小的小图片。这可能导致特征提取阶段输出的张量形状与后续全连接层的参数形状不匹配。 2. **自定义修改模型结构不当** 如果手动调整了预训练 VGG16 模型中的某些部分(例如更改全连接层),可能会引入新的形状冲突。特别是,VGG16 的最后几个全连接层假设特定的输入形状,而这些形状依赖于前面卷积层的输出。 3. **数据预处理不足** 输入到神经网络的数据未经过适当变换也可能引起此类问题。比如缺少必要的展平(Flatten)操作或将多维张量转换成一维向量的操作。 --- #### 修改方法 以下是几种常见的解决方案及其实现方式: ##### 方法一:调整输入图像分辨率至标准大小 可以通过插值技术将 CIFAR-10 图片缩放到适合 VGG16 的默认输入尺寸 224x224。可以利用 torchvision 提供的功能完成这一任务。 ```python from torchvision import transforms transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整图像大小为 224x224 transforms.ToTensor(), # 将 PIL Image 或 numpy.ndarray 转换为 Tensor ]) ``` 通过上述代码设置好 transform 后再加载数据即可避免因尺寸差异带来的潜在隐患。 ##### 方法二:替换或重置全连接层 由于原始 VGG16 是针对大规模自然场景设计的,其分类头并不适用于小型数据集如 CIFAR-10。因此建议重新构建最后一组 FC 层来适配新需求。 下面展示了一个简单的例子说明如何定制化改造这部分架构: ```python import torch.nn as nn class CustomVGG(nn.Module): def __init__(self, pretrained_model): super(CustomVGG, self).__init__() # 移除原版vgg里的fc layers features = list(pretrained_model.children())[:-1] self.features = nn.Sequential(*features) # 添加自己的fc layer适应cifar10类别数(10类) self.classifier = nn.Linear(in_features=512*7*7, out_features=10) def forward(self, x): batch_size = x.size(0) x = self.features(x) x = x.view(batch_size, -1) # Flatten tensor before passing it to fc-layer. x = self.classifier(x) return x ``` 注意这里假定 feature extractor 输出的是 `(batch_size, 512, 7, 7)` 形状的结果;实际应用中需依据具体情况验证并修正相应数值。 ##### 方法三:检查中间状态打印调试信息 为了更精确地定位问题所在位置,可以在程序运行过程中加入一些断点或者日志语句用于观察各步运算后的变量形态变化情况。 ```python print(f'Input shape: {input_tensor.shape}') output_of_conv_layers = model.conv_layer(input_tensor) print(f'Shape after convolutions: {output_of_conv_layers.shape}') flattened_output = output_of_conv_layers.view(output_of_conv_layers.size(0), -1) print(f'Shape after flattening: {flattened_output.shape}') final_result = model.fc(flattened_output) print(f'Resulting shape from fully connected layer: {final_result.shape}') ``` 借助以上片段能够清晰看到每一步骤产生的影响从而便于发现问题根源所在。 --- ### 总结 综上所述,“mat1 and mat2 shapes cannot be multiplied”的根本原因在于参与运算的对象之间存在不可调和的空间布局矛盾。通过对齐预期规格、优化内部逻辑以及增强监控手段三种途径可有效缓解乃至彻底消除这类异常状况的发生几率。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值