为什么每个通道的计算填充输入大小小于内核大小?

2024-06-02 05:04:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我有下面的模型,但它返回了一个错误。不知道为什么。我试过谷歌搜索,但到目前为止没有找到任何东西。我的输入是一个6乘6的numpy数组

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=(3,3), stride=1, padding=0)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=(3,3), stride=1, padding=0)
        self.conv3 = nn.Conv2d(32, 64, kernel_size=(3,3), stride=1, padding=0)

        self.fc1 = nn.Linear(64*4*4, 320)
        self.fc2 = nn.Linear(320, 160)
        self.out = nn.Linear(160, 2)


    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=2, stride=2)

        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=2, stride=2)

        x = self.conv3(x)
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=2, stride=2)

        x = x.reshape(-1, 64*4*4)
        #x = torch.flatten(x)

        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.out(x)
        return F.softmax(x, dim=1)

我的输入是一个6x6 numpy数组,我得到以下错误,知道为什么吗

RuntimeError: Calculated padded input size per channel: (2 x 2). Kernel size: (3 x 3). Kernel size can't be greater than actual input size

Tags: selfnumpysizedef错误nn数组kernel
2条回答

每次使用3的内核大小进行卷积时,图像的大小在每个维度上都会缩小1

因此,在第一次卷积之后,没有任何填充,您将得到4 x 4图像和2 x 2第二次卷积之后。而大小为3 x 3的内核显然无法遍历2 x 2映像,因此会收到错误

如果不希望缩小表示,请添加padding=1

您可以在PyTorchs文档(here)中看到有关Conv2d参数的形状如何变化的更多信息,具体请参见“形状”一节

下面是您可以做的,我使用了Szymon Maszke提出的padding=1。此填充被添加到卷积和maxpooling中

import numpy
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(1, 16, kernel_size=(3,3), stride=1, padding=1)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=(3,3), stride=1, padding=1)
        self.conv3 = nn.Conv2d(32, 64, kernel_size=(3,3), stride=1, padding=1)

        self.fc1 = nn.Linear(64*4*4, 320)
        self.fc2 = nn.Linear(320, 160)
        self.out = nn.Linear(160, 2)


    def forward(self, x): 
        x = self.conv1(x) 
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=2, stride=2)
        x = self.conv2(x)        
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1) 
        x = self.conv3(x)
        x = F.relu(x)
        x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1)
        x = x.reshape(-1, 64*4*4)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.out(x)
        return F.softmax(x, dim=1)

a = numpy.random.rand(6,6)
print(a)
data = torch.tensor(a).float()
print(data.shape)
# data.unsqueeze_(0).unsqueeze_(0)
data= data.expand(16, 1 ,-1,-1)
print(data.shape)

n=Net()
print("Start")
o = n(data)
print(o)

输出:

[[0.89695967 0.09447725 0.0905144  0.52694105 0.66000333 0.10537102]
 [0.32854697 0.86046884 0.29804184 0.62988374 0.5965067  0.54139821]
 [0.41561266 0.95484358 0.82919364 0.75556819 0.77373267 0.52209278]
 [0.46406436 0.6553954  0.60010151 0.86314529 0.70020608 0.16471554]
 [0.72863547 0.83846636 0.95122373 0.84322402 0.32264676 0.1233866 ]
 [0.75767067 0.56546123 0.7765021  0.35303595 0.3254407  0.84033049]]
torch.Size([6, 6])
torch.Size([16, 1, 6, 6])
Start
tensor([[0.5134, 0.4866]], grad_fn=<SoftmaxBackward>)

默认情况下,在PyTorch padding=0中,因此需要在需要时显式设置padding=1

相关问题 更多 >