【问题标题】:Translate Keras functional API to PyTorch nn.Module - Conv2d将 Keras 功能 API 转换为 PyTorch nn.Module - Conv2d
【发布时间】:2020-11-23 18:54:16
【问题描述】:

我正在尝试将以下 Inception 代码从 Keras 功能 API (link) 中的教程转换为 PyTorch nn.Module

    def conv_module(x, K, kX, kY, stride, chanDim, padding="same"):
        # define a CONV => BN => RELU pattern
        x = Conv2D(K, (kX, kY), strides=stride, padding=padding)(x)
        x = BatchNormalization(axis=chanDim)(x)
        x = Activation("relu")(x)
        # return the block
        return x


    def inception_module(x, numK1x1, numK3x3, chanDim):
        # define two CONV modules, then concatenate across the
        # channel dimension
        conv_1x1 = conv_module(x, numK1x1, 1, 1, (1, 1), chanDim)
        conv_3x3 = conv_module(x, numK3x3, 3, 3, (1, 1), chanDim)
        x = concatenate([conv_1x1, conv_3x3], axis=chanDim)
        # return the block
        return x

我在翻译 Conv2D 时遇到问题。如果我理解正确:

  1. Keras 中没有 in_features - 我应该如何在 PyTorch 中表示它?
  2. Keras filters 是 PyTorch out_features
  3. kernel_sizestridepadding 是相同的(可能padding 的一些选项的调用方式不同)

我理解正确吗?如果是这样,我应该如何处理in_features?到目前为止我的代码:

class BasicConv2d(nn.Module):
    def __init__(
            self,
            in_channels: int,
            out_channels: int,
            kernel_size: int,
            stride: int
    ) -> None:
        super().__init__()
        self.conv = nn.Conv2d(in_channels,
                              out_channels,
                              kernel_size=kernel_size,
                              stride=stride)
        self.bn = nn.BatchNorm2d(out_channels, eps=0.001)
        self.relu = nn.ReLU()

    def forward(self, x: Tensor) -> Tensor:
        x = self.conv(x)
        x = self.bn(x)
        x = self.relu(x)
        return x

class Inception(nn.Module):
    def __init__(
            self,
            in_channels: int,
            num_1x1_filters: int,
            num_3x3_filters: int,
    ) -> None:
        super().__init__()
        # how to fill this further?
        self.conv_1d = BasicConv2d(
            num_1x1_filters,
            )

【问题讨论】:

    标签: python tensorflow keras pytorch


    【解决方案1】:

    您在很大程度上是正确的。 Con2d 中的in_channels 参数对应编号。来自上一层的输出通道。如果Conv2d 是第一层,则in_channels 对应编号。图像中的通道数。灰度图像为 1,RGB 图像为 3。

    但我不确定如何连接两个 BasicConv2d 输出。

    将batch_size 固定为1,假设图像大小为256*256out_channelsconv1x1 为64。这将输出形状为torch.Size([1, 64, 256, 256]) 的张量。假设conv3x3 中的out_channels 为32,则该层将输出形状为torch.Size([1, 32, 254, 254]) 的张量。如果没有一些技巧,我们将无法连接这两个张量,例如单独使用conv3x3padding=1,因为这会产生形状为torch.Size([1, 32, 256, 256]) 的输出,因此我们将能够连接。

    【讨论】:

    • 您的意思是torch.size([1, 32, 256, 256])conv3x3 输出形状中吗?因为我需要在通道维度中从conv1x1[1, 32, 256, 256 中堆叠[1, 64, 256, 256],即来自arxiv.org/pdf/1611.03530.pdf 的“Concat in channels”(本教程在Keras 中实现了这篇论文,我想做它在 PyTorch 中)。我想我应该可以沿着dim=1这样堆叠它。
    • 另外,torch.cat() 的 PyTorch 文档指出“所有张量必须具有相同的形状(连接维度除外)”,这意味着这将适用于堆叠通道 AFAIK。
    • 我不是说torch.size([1, 32, 256, 256]),因为这不是3x3 convolution 的预期输出。
    • 哦,我现在明白了,这是有道理的。所以我就填这个,谢谢!
    【解决方案2】:

    BasicConv2d 的实现很好,这是 Inception 模块的代码。

    class Inception(nn.Module):
    def __init__(
            self,
            in_channels: int,
            num_1x1_filters: int,
            num_3x3_filters: int,
    ) -> None:
        super().__init__()
        # how to fill this further?
        self.conv1 = BasicConv2d(in_channels, num_1x1_filters, 1,1)
        self.conv3 = BasicConv2d(in_channels, num_3x3_filters, 3,1)
    def forward(self,x):
        conv1_out = self.conv1(x)
        conv3_out = self.conv3(x)
        x = torch.cat([conv1_out, conv3_out],)
        return x
    

    您需要定义两个基本的卷积层,并在前向通道中分别使用相同的输入。 正如@planet_pluto 指出的那样,您不能连接两个具有不同大小的特征图。您可以选择更好的stridepadding 来构建两个大小相同的特征图,或者在连接它们之前进行上采样或下采样。

    【讨论】:

      猜你喜欢
      • 2022-10-18
      • 2021-07-10
      • 2021-05-23
      • 2020-09-02
      • 1970-01-01
      • 2019-10-15
      • 2021-04-27
      • 1970-01-01
      • 2020-07-22
      相关资源
      最近更新 更多