线性层的火炬尺寸如何计算?

时间:2018-12-14 18:21:22

标签: pytorch

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最终特征有关。

我不太了解如何在此处选择数字12084,以及为什么结果与输入尺寸匹配。

当我尝试构建类似的网络时,实际上遇到了数据维度方面的问题。

例如,当我使用一个更简单的网络时:

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是从哪里来的,我该如何设计网络以使尺寸匹配?

1 个答案:

答案 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是从先前的卷积中检索到的张量。但是我们需要提前计算该值,以便我们可以首先初始化网络...

通过逐个检查操作进行计算。

  1. 输入为32x32
  2. 我们进行了5x5的卷积而没有填充,因此我们在每侧损失了2个像素,下降到28x28
  3. 我们使用2x2的接收场进行最大池化,将每个尺寸减少一半,降至14x14
  4. 我们再进行一次5x5卷积而不填充,我们降到10x10
  5. 我们再进行一次最大池化,我们降至5x5

,这5x5就是为什么在本教程中看到self.fc1 = nn.Linear(16 * 5 * 5, 120)的原因。从32x32图像开始时为n_features_conv * height * width。如果要使用其他输入大小,则必须重新执行上述计算并相应地调整第一个Linear层。

对于进一步的操作,这只是一串矩阵乘法(Linear就是这样做的)。因此,唯一的规则是上一个n_features_out的{​​{1}}与下一个Linear匹配。值120和84完全是任意的,尽管它们可能是作者选择的,因此生成的网络运行良好。