热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

如何在PyTorch中合并2D卷积?

如何解决《如何在PyTorch中合并2D卷积?》经验,为你挑选了1个好方法。

从线性代数我们知道线性算子是可交换的和关联的。

在深度学习世界中,此概念用于证明在NN层之间引入非线性是合理的,这种现象俗称线性千层面(参考)。

在信号处理中,这是优化内存和/或运行时要求(参考)的众所周知的技巧。

因此,从不同的角度来看,合并卷积是一个非常有用的工具。如何使用PyTorch实施它?



1> fr_andres Su..:

如果有y = x * a * b(其中*表示卷积并且a, b是您的内核),则可以c = a * b这样定义y = x * c = x * a * b

import torch

def merge_conv_kernels(k1, k2):
    """
    :input k1: A tensor of shape ``(out1, in1, s1, s1)``
    :input k1: A tensor of shape ``(out2, in2, s2, s2)``
    :returns: A tensor of shape ``(out2, in1, s1+s2-1, s1+s2-1)``
      so that convolving with it equals convolving with k1 and
      then with k2.
    """
    padding = k2.shape[-1] - 1
    # Flip because this is actually correlation, and permute to adapt to BHCW
    k3 = torch.conv2d(k1.permute(1, 0, 2, 3), k2.flip(-1, -2),
                      padding=padding).permute(1, 0, 2, 3)
    return k3

为了说明等效性,此示例将分别具有900个参数和5000个参数的两个内核组合为一个包含28个参数的等效内核:

# Create 2 conv. kernels
out1, in1, s1 = (100, 1, 3)
out2, in2, s2 = (2, 100, 5)
kernel1 = torch.rand(out1, in1, s1, s1, dtype=torch.float64)
kernel2 = torch.rand(out2, in2, s2, s2, dtype=torch.float64)

# propagate a random tensor through them. Note that padding
# corresponds to the "full" mathematical operation (s-1)
b, c, h, w = 1, 1, 6, 6
x = torch.rand(b, c, h, w, dtype=torch.float64) * 10
c1 = torch.conv2d(x, kernel1, padding=s1 - 1)
c2 = torch.conv2d(c1, kernel2, padding=s2 - 1)

# check that the collapsed conv2d is same as c2:
kernel3 = merge_conv_kernels(kernel1, kernel2)
c3 = torch.conv2d(x, kernel3, padding=kernel3.shape[-1] - 1)
print(kernel3.shape)
print((c2 - c3).abs().sum() <1e-5)

注意:等效条件是假设我们具有无限的数值分辨率。我认为已经进行了有关堆叠许多低分辨率浮点线性运算的研究,并表明网络从数值误差中获利,但我找不到它。任何参考表示赞赏!


推荐阅读
author-avatar
寒夜孤星TM
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有