【问题标题】:Understanding Feature Maps in Convolutional Layers (PyTorch)了解卷积层中的特征图 (PyTorch)
【发布时间】:2019-07-21 02:58:29
【问题描述】:

我在 MNIST 的鉴别器网络中有这段代码:

nn.Conv2d(1, 64, 4, 2, 1),

据我了解,有 1 个输入通道(MNIST 图像),然后我们以 2 步长将 4x4 内核应用于图像,以生成 64 个特征图。这是否意味着我们在这一层实际上有 64 个内核?因为为了获得 64 个不同的特征图,我们需要 64 个单独的内核来对图像进行卷积?

然后在一些 ReLu 之后,我们有另一个卷积:

nn.Conv2d(64, 128, 4, 2, 1),

我们如何从 64 到 128?根据我对第一个示例的理解,我们有 64 个单独的内核,可以生成 64 个单独的特征图。但是这里我们从 64 个特征图变成了 128 个特征图?这是否意味着我们只有两个内核?

希望有人能指点一下我的理解是否正确!

【问题讨论】:

  • 你对“组卷积”感到困惑

标签: neural-network pytorch


【解决方案1】:

您在第一个示例中的理解是正确的,您有 64 个不同的内核来生成 64 个不同的特征图。

在第二个例子的情况下,输入通道的数量不是一个,你仍然有与输出特征图的数量一样多的内核(所​​以 128),每个都在线性组合上训练输入特征图。因此,在您的情况下,这些内核中的每一个都将具有 4x4x64 的可训练权重。

【讨论】:

  • 感谢您的回复。我没有意识到内核在一个卷上进行了卷积。
【解决方案2】:

所有输入通道都通过过滤器(内核)卷积连接到每个输出通道(如果group = 1,默认情况下)——每个输出通道一个。虽然每个内核都有每个输入通道的子内核。

所以在第一层你有in_channels = 1out_channels = 64 意味着有64 个内核(和子内核)。在第二层有in_channels = 64out_channels = 128,这意味着有128 个内核,每个内核有64 * 128 个子内核。

下面是一个简单的例子,它取自cs231n 的一个卷积层,以便澄清:

还有我在 Pytorch 中的实现:

import torch
from torch import nn


cnn = nn.Conv2d(in_channels=3, out_channels=2, kernel_size=3,
                stride=2, padding=1, bias=True, groups=1)


w0 = torch.FloatTensor([[[-1, -1,  0],
                         [ 1,  1,  1],
                         [ 1,  1,  0]],

                        [[ 1,  1, -1],
                         [ 0,  0,  0],
                         [ 1,  1, -1]],

                        [[ 0, -1,  0],
                         [-1,  0, -1],
                         [ 1,  0,  1]]])

b0 = torch.FloatTensor([1])

w1 = torch.FloatTensor([[[-1,  0,  0],
                         [ 1,  1,  1],
                         [-1, -1,  0]],

                        [[ 1, -1, -1],
                         [-1,  1, -1],
                         [ 1, -1,  0]],

                        [[ 1, -1,  0],
                         [ 0,  1,  1],
                         [ 1,  0,  1]]])

b1 = torch.FloatTensor([0]) 


cnn.weight = torch.nn.Parameter(torch.stack((w0, w1), 0))
cnn.bias = torch.nn.Parameter(torch.cat((b0, b1), 0))

inpt = torch.FloatTensor([[[ 1, 2, 0, 1, 2],
                           [ 1, 0, 2, 2, 0],
                           [ 2, 0, 0, 2, 2],
                           [ 0, 0, 2, 2, 0],
                           [ 2, 2, 2, 1, 2]],

                          [[ 2, 0, 0, 1, 1],
                           [ 1, 0, 2, 1, 2],
                           [ 2, 0, 2, 2, 1],
                           [ 0, 2, 0, 0, 1],
                           [ 1, 2, 1, 2, 0]],

                          [[ 0, 0, 2, 1, 2],
                           [ 0, 1, 0, 2, 0],
                           [ 1, 1, 0, 0, 2],
                           [ 0, 0, 0, 1, 1],
                           [ 0, 1, 2, 0, 2]]])

cnn(inpt.unsqueeze(0))

输出:

tensor([[[[ 7.,  9., 10.],
          [ 0.,  6., 10.],
          [ 2.,  5.,  2.]],

         [[ 4.,  4.,  4.],
          [ 5.,  1.,  2.],
          [ 2.,  6.,  0.]]]])

【讨论】: