在PyTorch tutorial中,构建的网络为
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
并用于处理尺寸为1x32x32
的图像。他们提到,网络不能用于其他尺寸的图像。
两个卷积层似乎允许任意数量的特征,因此线性层似乎与将32x32
纳入10
最终特征有关。
我不太了解如何在此处选择数字120
和84
,以及为什么结果与输入尺寸匹配。
当我尝试构建类似的网络时,实际上遇到了数据维度方面的问题。
例如,当我使用一个更简单的网络时:
Net(
(conv1): Conv2d(3, 8, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(8, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=3, bias=True)
)
对于大小为3x1200x800
的输入,我收到错误消息:
RuntimeError: size mismatch, m1: [1 x 936144], m2: [400 x 3] at /pytorch/aten/src/TH/generic/THTensorMath.cpp:940
数字936144
是从哪里来的,我该如何设计网络以使尺寸匹配?
答案 0 :(得分:4)
关键步骤在最后一个卷积和第一个Linear
块之间。 Conv2d
输出形状为[batch_size, n_features_conv, height, width]
的张量,而Linear
期望为[batch_size, n_features_lin]
。要使两个对齐,您需要将3个维度[n_features_conv, height, width]
“堆叠”成一个[n_features_lin]
。如下所示,必须是n_features_lin == n_features_conv * height * width
。在原始代码中,这种“堆叠”是通过
x = x.view(-1, self.num_flat_features(x))
,如果您检查num_flat_features
,它只会计算此n_features_conv * height * width
产品。换句话说,您的第一个转换必须具有num_flat_features(x)
个输入特征,其中x
是从先前的卷积中检索到的张量。但是我们需要提前计算该值,以便我们可以首先初始化网络...
通过逐个检查操作进行计算。
,这5x5就是为什么在本教程中看到self.fc1 = nn.Linear(16 * 5 * 5, 120)
的原因。从32x32图像开始时为n_features_conv * height * width
。如果要使用其他输入大小,则必须重新执行上述计算并相应地调整第一个Linear
层。
对于进一步的操作,这只是一串矩阵乘法(Linear
就是这样做的)。因此,唯一的规则是上一个n_features_out
的{{1}}与下一个Linear
匹配。值120和84完全是任意的,尽管它们可能是作者选择的,因此生成的网络运行良好。