【问题标题】:Performing Convolution (NOT cross-correlation) in pytorch在 pytorch 中执行卷积(非互相关)
【发布时间】:2017-08-15 15:37:34
【问题描述】:

我有 a network 我正在尝试在 pytorch 中实现,但我似乎无法弄清楚如何实现“纯”卷积。在 tensorflow 中可以这样完成:

def conv2d_flipkernel(x, k, name=None):
    return tf.nn.conv2d(x, flipkernel(k), name=name,
                        strides=(1, 1, 1, 1), padding='SAME')

flipkernel 函数为:

def flipkernel(kern):
      return kern[(slice(None, None, -1),) * 2 + (slice(None), slice(None))]

如何在 pytorch 中完成类似的操作?

【问题讨论】:

    标签: neural-network conv-neural-network pytorch convolution torch


    【解决方案1】:

    TLDR使用函数工具箱中的卷积torch.nn.fuctional.conv2d,而不是torch.nn.Conv2d,并围绕垂直和水平轴翻转您的过滤器。


    torch.nn.Conv2d 是网络的卷积层。因为权重是学习的,所以是否使用互相关实现并不重要,因为网络只会学习内核的镜像版本(感谢@etarion 的澄清)。

    torch.nn.fuctional.conv2d 使用作为参数提供的输入和权重执行卷积,类似于示例中的 tensorflow 函数。我写了一个简单的测试来确定它是否像 tensorflow 函数一样,实际上是在执行互相关,是否需要翻转滤波器以获得正确的卷积结果。

    import torch
    import torch.nn.functional as F
    import torch.autograd as autograd
    import numpy as np
    
    #A vertical edge detection filter. 
    #Because this filter is not symmetric, for correct convolution the filter must be flipped before element-wise multiplication
    filters = autograd.Variable(torch.FloatTensor([[[[-1, 1]]]]))
    
    #A test image of a square
    inputs = autograd.Variable(torch.FloatTensor([[[[0,0,0,0,0,0,0], [0, 0, 1, 1, 1, 0, 0], 
                                                 [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0],
                                                [0,0,0,0,0,0,0]]]]))
    print(F.conv2d(inputs, filters))
    

    这个输出

    Variable containing:
    (0 ,0 ,.,.) = 
      0  0  0  0  0  0
      0  1  0  0 -1  0
      0  1  0  0 -1  0
      0  1  0  0 -1  0
      0  0  0  0  0  0
    [torch.FloatTensor of size 1x1x5x6]
    

    此输出是互相关的结果。因此,我们需要翻转过滤器

    def flip_tensor(t):
        flipped = t.numpy().copy()
    
        for i in range(len(filters.size())):
            flipped = np.flip(flipped,i) #Reverse given tensor on dimention i
        return torch.from_numpy(flipped.copy())
    
    print(F.conv2d(inputs, autograd.Variable(flip_tensor(filters.data))))
    

    新的输出是卷积的正确结果。

    Variable containing:
    (0 ,0 ,.,.) = 
      0  0  0  0  0  0
      0 -1  0  0  1  0
      0 -1  0  0  1  0
      0 -1  0  0  1  0
      0  0  0  0  0  0
    [torch.FloatTensor of size 1x1x5x6] 
    

    【讨论】:

    • OP 要求卷积而不是互相关。我相信他们知道学习权重会导致相同的结果。但是,如果一个人想要例如通过从另一种语言移植并使用固定权重检查等价性来复制网络,然后人们可能会发现自己处于 OPs 的情况下,这个确切的问题 - 特别是考虑到 pytorch 尚未实现 [::-1] 的事实。
    • torch.nn.conv2d 现在在 CamelCase 中是 torch.nn.Conv2d,表示一个类。
    【解决方案2】:

    与上面的答案没什么不同,但torch 可以原生地做flip(i)(我猜你只想flip(2)flip(3)):

    def convolution(A, B):
      return F.conv2d(A, B.flip(2).flip(3), padding=padding)
    

    【讨论】:

      猜你喜欢
      • 2021-06-12
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 2013-12-17
      • 2021-04-13
      • 2021-11-09
      • 2018-11-11
      • 1970-01-01
      相关资源
      最近更新 更多