【问题标题】:Calculating input and output size for Conv2d in PyTorch for image classification在 PyTorch 中计算 Conv2d 的输入和输出大小以进行图像分类
【发布时间】:2018-04-18 02:10:32
【问题描述】:

我正在尝试在此处运行有关 CIFAR10 图像分类的 PyTorch 教程 - http://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py

我做了一个小改动,我正在使用不同的数据集。我有来自 Wikiart 数据集的图像,我想按艺术家(标签 = 艺术家姓名)进行分类。

这是网络的代码 -

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16*5*5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

然后是我开始训练网络的这部分代码。

for epoch in range(2):
     running_loss = 0.0

     for i, data in enumerate(wiki_train_dataloader, 0):
        inputs, labels = data['image'], data['class']
        print(inputs.shape)
        inputs, labels = Variable(inputs), Variable(labels)

        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.data[0]
        if i % 2000 == 1999:  # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
              (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

这一行print(inputs.shape) 给了我torch.Size([4, 32, 32, 3]) 和我的Wikiart 数据集,而在CIFAR10 的原始示例中,它打印torch.Size([4, 3, 32, 32])

现在,我不确定如何更改我网络中的 Conv2d 以与 torch.Size([4, 32, 32, 3]) 兼容。

我得到这个错误:

RuntimeError: Given input size: (3 x 32 x 3). Calculated output size: (6 x 28 x -1). Output size is too small at /opt/conda/conda-bld/pytorch_1503965122592/work/torch/lib/THNN/generic/SpatialConvolutionMM.c:45

在阅读 Wikiart 数据集的图像时,我将它们的大小调整为 (32, 32),这些是 3 通道图像。

我尝试过的事情:

1) CIFAR10 教程使用了我没有使用的转换。我无法将其合并到我的代码中。

2) 将 self.conv2 = nn.Conv2d(6, 16, 5) 更改为 self.conv2 = nn.Conv2d(3, 6, 5)。这给了我与上面相同的错误。我只是更改它以查看错误消息是否更改。

非常感谢任何有关如何在 PyTorch 中计算输入和输出大小或自动重塑张量的资源。我刚开始学习 Torch,发现尺寸计算很复杂。

【问题讨论】:

    标签: python image convolution pytorch tensor


    【解决方案1】:

    您必须将输入调整为这种格式(批次、通道数、高度、宽度)。 目前您有格式 (B,H,W,C) (4, 32, 32, 3),因此您需要交换第 4 轴和第 2 轴以使用 (B,C,H,W) 来塑造您的数据。 你可以这样做:

    inputs, labels = Variable(inputs), Variable(labels)
    inputs = inputs.transpose(1,3)
    ... the rest
    

    【讨论】:

      【解决方案2】:

      我终于使用

      将输入更改为新形状

      inputs = inputs.view(4, 3, 32, 32),就在下面

      inputs, labels = data['image'], data['class']

      【讨论】:

        【解决方案3】:

        您可以使用 torch.nn.AdaptiveMaxPool2d 来设置特定的输出。

        例如,如果我设置 nn.AdaptiveMaxPool2d((5,7)) 我将强制图像为 5X7。然后你可以将它乘以你之前的 Conv2d 层的 out_channels。

        https://pytorch.org/docs/stable/nn.html#torch.nn.AdaptiveMaxPool2d

        class Net(nn.Module):
            def __init__(self):
                super(Net, self).__init__()
                self.conv1 = nn.Conv2d(3, 6, 5)
                self.pool = nn.MaxPool2d(2, 2)
                self.conv2 = nn.Conv2d(6, 16, 5)
                self.adapt = nn.AdaptiveMaxPool2d((5,7))
                self.fc1 = nn.Linear(16*5*7, 120)
                self.fc2 = nn.Linear(120, 84)
                self.fc3 = nn.Linear(84, 10)
        
            def forward(self, x):
                x = self.pool(F.relu(self.conv1(x)))
                x = self.adapt(F.relu(self.conv2(x)))
                x = x.view(-1, 16*5*7)
                x = F.relu(self.fc1(x))
                x = F.relu(self.fc2(x))
                x = self.fc3(x)
                return x
        

        【讨论】:

          【解决方案4】:

          我知道这是一个老问题,但在使用非标准内核大小、膨胀等时,我再次偶然发现了这个问题。 这是我想出的一个函数,它为我计算并检查给定的输出形状:

          def find_settings(shape_in, shape_out, kernel_sizes, dilation_sizes, padding_sizes, stride_sizes, transpose=False):
              from itertools import product
          
              import torch
              from torch import nn
          
              import numpy as np
          
              # Fake input
              x_in = torch.tensor(np.random.randn(4, 1, shape_in, shape_in), dtype=torch.float)
          
              # Grid search through all combinations
              for kernel, dilation, padding, stride in product(kernel_sizes, dilation_sizes, padding_sizes, stride_sizes):
                  # Define a layer
                  if transpose:
                      layer = nn.ConvTranspose2d
                  else:
                      layer = nn.Conv2d
                  layer = layer(
                          1, 1,
                          (4, kernel),
                          stride=(2, stride),
                          padding=(2, padding),
                          dilation=(2, dilation)
                      )
          
                  # Check if layer is valid for given input shape
                  try:
                      x_out = layer(x_in)
                  except Exception:
                      continue
          
                  # Check for shape of out tensor
                  result = x_out.shape[-1]
          
                  if shape_out == result:
                      print('Correct shape for:\n ker: {}\n dil: {}\n pad: {}\n str: {}\n'.format(kernel, dilation, padding, stride))
          

          下面是它的一个示例用法:

          transpose = True
          shape_in = 128
          shape_out = 1024
          
          
          kernel_sizes = [3, 4, 5, 7, 9, 11]
          dilation_sizes = list(range(1, 20))
          padding_sizes = list(range(15))
          stride_sizes = list(range(4, 16))
          find_settings(shape_in, shape_out, kernel_sizes, dilation_sizes, padding_sizes, stride_sizes, transpose)
          

          我希望它可以在未来帮助人们解决这个问题。请注意,它不是并行化的,如果有很多选择,它可以运行一段时间。

          【讨论】:

            【解决方案5】:

            在预处理时应用transforms.ToTensor(),它将重塑图像尺寸。见thispytorch 文档。

            【讨论】:

            • 链接失效
            猜你喜欢
            • 2021-06-25
            • 2017-10-26
            • 2020-06-20
            • 2021-07-25
            • 2022-11-22
            • 2019-06-22
            • 2021-07-04
            • 2020-06-18
            • 2021-11-02
            相关资源
            最近更新 更多