在 Pytorch 中实现 SeparableConv2D

Jin*_*les 5 python convolution conv-neural-network tensorflow pytorch

主要目标

PyTorch 等效于 SeparableConv2D padding = 'same'

from tensorflow.keras.layers import SeparableConv2D
x = SeparableConv2D(64, (1, 16), use_bias = False, padding = 'same')(x)
Run Code Online (Sandbox Code Playgroud)

SeparableConv2D 的 PyTorch 等效项是什么?

消息来源说:

如果 groups = nInputPlane,kernel=(K, 1),(之前是一个 Conv2d 层,groups=1 且 kernel=(1, K)),那么它是可分离的。

虽然该消息来源说:

其核心思想是将一个完整的卷积酸分解为两步计算,即Depthwise Convolution和Pointwise。

这是我的尝试:

class SeparableConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, depth, kernel_size, bias=False):
        super(SeparableConv2d, self).__init__()
        self.depthwise = nn.Conv2d(in_channels, out_channels*depth, kernel_size=kernel_size, groups=in_channels, bias=bias)
        self.pointwise = nn.Conv2d(out_channels*depth, out_channels, kernel_size=1, bias=bias)

    def forward(self, x):
        out = self.depthwise(x)
        out = self.pointwise(out)
        return out
Run Code Online (Sandbox Code Playgroud)

它是否正确?这相当于吗tensorflow.keras.layers.SeparableConv2D

关于什么padding = 'same'

这样做时如何确保我的输入和输出大小相同?

我的尝试:

x = F.pad(x, (8, 7, 0, 0), )
Run Code Online (Sandbox Code Playgroud)

因为内核大小为(1,16),所以我添加了左右填充,分别为 8 和 7。这是实现这一目标的正确方法(也是最好的方法)吗padding = 'same'?如何将其放置在我的SeparableConv2d类中,并根据输入数据维度大小进行动态计算?

全部一起

x = F.pad(x, (8, 7, 0, 0), )
Run Code Online (Sandbox Code Playgroud)

这些代码有问题吗?

Poe*_*tor 6

链接的定义通常是一致的。最好的一篇在文章中。

  • “Depthwise”(不是一个非常直观的名称,因为不涉及深度) - 是一系列常规的 2d 卷积,仅分别应用于数据层。- “逐点”与 1x1 内核相同Conv2d

我建议对你的课程进行一些更正SeparableConv2d

  • 不需要使用深度参数 - 它与 out_channels 相同
  • 我将 padding 设置为 1 以确保与kernel=(3,3). 如果内核大小不同 - 使用与常规 Conv2d 相同的原理相应地调整填充。Net()不再需要您的示例类- 填充是在SeparableConv2d.

这是更新后的代码,应该与tf.keras.layers.SeparableConv2D实现类似:

class SeparableConv2d(nn.Module):

def __init__(self, in_channels, out_channels, kernel_size, bias=False):
    super(SeparableConv2d, self).__init__()
    self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size=kernel_size, 
                               groups=in_channels, bias=bias, padding=1)
    self.pointwise = nn.Conv2d(in_channels, out_channels, 
                               kernel_size=1, bias=bias)

def forward(self, x):
    out = self.depthwise(x)
    out = self.pointwise(out)
    return out
Run Code Online (Sandbox Code Playgroud)