PyTorch网络报错:mat1与mat2无法相乘,求解决方法
解决PyTorch中mat1和mat2形状不匹配的问题
问题原因
报错Runtime Error: mat1 and mat2 shapes cannot be multiplied (16x756900 and 3048516x30)是因为全连接层fc1的输入特征数设置错误,和实际经过卷积、池化后得到的特征图展平后的维度不匹配:
- 代码中
fc1的in_features写的是36*291*291=3048516,但实际输入经过两次卷积+池化后,展平后的特征数是36*145*145=756900(对应报错里的16x756900,16是batch size)。
正确的特征尺寸计算步骤
输入形状为[3,600,600],一步步计算各层输出尺寸:
- conv1 + pool:
- conv1:
kernel=11, padding=0,输出尺寸 =(600 - 11)/1 + 1 = 590,形状变为[8,590,590] - MaxPool2d(2,2):输出尺寸 =
(590 - 2)/2 + 1 = 295,形状变为[8,295,295]
- conv1:
- conv2 + pool:
- conv2:
kernel=5, padding=0,输出尺寸 =(295 -5)/1 +1 =291,形状变为[36,291,291] - MaxPool2d(2,2):输出尺寸 =
floor((291 -2)/2 +1) =145,形状变为[36,145,145]
- conv2:
- 展平后特征数:
36 *145 *145 =756900
修复后的代码
方法一:直接修正fc1的in_features为正确值:
import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super().__init__() self.conv1 = nn.Conv2d(3,8,11, padding=0) self.pool = nn.MaxPool2d(2,2) self.conv2 = nn.Conv2d(8, 36, 5, padding=0) self.fc1 = nn.Linear(36*145*145, 30) # 修正输入特征数 self.fc2 = nn.Linear(30, 20) self.fc3 = nn.Linear(20, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = torch.flatten(x, 1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x # 测试代码 if __name__ == "__main__": input_tensor = torch.randn(16,3,600,600) net = Net() output = net(input_tensor) print(output.shape) # 预期输出 torch.Size([16,10])
方法二:动态计算全连接层输入特征数(适合输入尺寸可能变化的场景):
import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super().__init__() self.conv1 = nn.Conv2d(3,8,11, padding=0) self.pool = nn.MaxPool2d(2,2) self.conv2 = nn.Conv2d(8, 36, 5, padding=0) # 先不定义fc1,第一次前向传播时动态初始化 self.fc2 = nn.Linear(30, 20) self.fc3 = nn.Linear(20, 10) self._fc_initialized = False def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = torch.flatten(x, 1) if not self._fc_initialized: # 根据实际展平后的特征数初始化fc1 self.fc1 = nn.Linear(x.shape[1], 30).to(x.device) self._fc_initialized = True x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x # 测试代码 if __name__ == "__main__": input_tensor = torch.randn(16,3,600,600) net = Net() output = net(input_tensor) print(output.shape)
注意事项
- 计算卷积/池化层输出尺寸时,默认padding=0、stride=1的情况下,公式为:
输出尺寸 = floor((输入尺寸 - kernel_size)/stride) + 1 - 动态初始化全连接层时,需注意模型保存和加载的兼容性,因为
fc1是第一次前向传播后才创建的。
内容的提问来源于stack exchange,提问作者overtherainbow
相关产品推荐
相关产品推荐

