跳到主要内容

卷积层输出大小计算

标准的计算公式

卷积层的输出大小是基于输入大小、卷积核大小、步长(stride)和填充(padding)来计算的。以下是计算卷积层输出大小的公式:

无填充,步长为1

如果没有使用填充(padding = 0)并且步长(stride)为1,输出大小(O)的计算公式为:

O=IK+1O = I - K + 1

其中:

  • II 是输入大小。
  • KK 是卷积核大小。

有填充,步长为1

如果使用了填充并且步长为1,输出大小的计算公式为:

O=IK+2P+1O = I - K + 2P + 1

其中:

  • PP 是填充大小。

有填充,步长大于1

如果使用了填充并且步长大于1,输出大小的计算公式为:

O=IK+2PS+1O = \frac{I - K + 2P}{S} + 1

其中:

  • SS 是步长。

注意:上述公式适用于输入、卷积核和输出都是正方形的情况。如果它们不是正方形,那么需要为宽度和高度分别应用这些公式。

长方形的输入、卷积核和输出

如果输入、卷积核或输出是长方形的,我们需要为宽度和高度分别应用计算公式。以下是如何计算长方形卷积层输出大小的步骤:

  1. 定义参数:

    • IwI_wIhI_h 分别是输入的宽度和高度。
    • KwK_wKhK_h 分别是卷积核的宽度和高度。
    • PwP_wPhP_h 分别是宽度和高度的填充大小。
    • SwS_wShS_h 分别是宽度和高度的步长。
  2. 计算输出宽度: Ow=IwKw+2PwSw+1O_w = \frac{I_w - K_w + 2P_w}{S_w} + 1

  3. 计算输出高度: Oh=IhKh+2PhSh+1O_h = \frac{I_h - K_h + 2P_h}{S_h} + 1

输出的大小为 Ow×OhO_w \times O_h

请注意,上述公式中的除法应向下取整,因为输出的大小必须是整数。

这就是如何为长方形的输入、卷积核和输出计算卷积层的输出大小。如果您有任何其他问题或需要进一步的解释,请告诉我。

实际的例子

首先,我们需要知道输入图像的大小和通道数。

transform = transforms.Compose([
transforms.Resize((128, 64)),
transforms.ToTensor(),
])

根据上面提供的 transform,输入图像的大小为 128×64128 \times 64(高 x 宽),并且由于使用了transforms.ToTensor(),所以我们知道输入图像是单通道的(灰度图像)。

接下来,我们将按照模型的结构,逐层计算输出的大小。

  1. 第一个卷积层:

    • 输入大小: 128×64128 \times 64
    • 卷积核大小: 11×1111 \times 11
    • 步长: 4
    • 填充: 2 使用公式计算: Ow=6411+2×24+1=15O_w = \frac{64 - 11 + 2 \times 2}{4} + 1 = 15 Oh=12811+2×24+1=31O_h = \frac{128 - 11 + 2 \times 2}{4} + 1 = 31 输出大小: 31×1531 \times 15
  2. 第一个池化层:

    • 输入大小: 31×1531 \times 15
    • 池化核大小: 3×33 \times 3
    • 步长: 2 使用公式计算: Ow=1532+1=7O_w = \frac{15 - 3}{2} + 1 = 7 Oh=3132+1=15O_h = \frac{31 - 3}{2} + 1 = 15 输出大小: 15×715 \times 7
  3. 第二个卷积层:

    • 输入大小: 15×715 \times 7
    • 卷积核大小: 5×55 \times 5
    • 步长: 1
    • 填充: 2 使用公式计算: Ow=75+2×2+1=7O_w = 7 - 5 + 2 \times 2 + 1 = 7 Oh=155+2×2+1=15O_h = 15 - 5 + 2 \times 2 + 1 = 15 输出大小: 15×715 \times 7
  4. 第二个池化层:

    • 输入大小: 15×715 \times 7
    • 池化核大小: 3×33 \times 3
    • 步长: 2 使用公式计算: Ow=732+1=3O_w = \frac{7 - 3}{2} + 1 = 3 Oh=1532+1=7O_h = \frac{15 - 3}{2} + 1 = 7 输出大小: 7×37 \times 3

接下来的三个卷积层都有相同的卷积核大小、步长和填充,所以输出大小不变,仍为 7×37 \times 3

  1. 第三个池化层:
    • 输入大小: 7×37 \times 3
    • 池化核大小: 3×33 \times 3
    • 步长: 2 使用公式计算: Ow=332+1=1O_w = \frac{3 - 3}{2} + 1 = 1 Oh=732+1=3O_h = \frac{7 - 3}{2} + 1 = 3 输出大小: 3×13 \times 1

最后,全连接层的输入是上一个池化层的输出大小乘以最后一个卷积层的通道数,即 256×3×1=768256 \times 3 \times 1 = 768

如下代码

import torch.nn as nn

# 定义模型
class CaptchaModel(nn.Module):
def __init__(self, num_classes=len(nums)):
super(CaptchaModel, self).__init__()

# 卷积层
self.features = nn.Sequential(
# 输入: 128x64x1
nn.Conv2d(1, 32, kernel_size=3, stride=1,
padding=1), # 输出: 128x64x32
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2), # 输出: 64x32x32

nn.Conv2d(32, 64, kernel_size=3, stride=1,
padding=1), # 输出: 64x32x64
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2), # 输出: 32x16x64

nn.Conv2d(64, 128, kernel_size=3, stride=1,
padding=1), # 输出: 32x16x128
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2), # 输出: 16x8x128
)

# 全连接层
self.classifier = nn.Sequential(
nn.Linear(16 * 8 * 128, 512),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(512, num_classes),
)

def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1) # 展平
x = self.classifier(x)
return x