【问题标题】:How to perform sum pooling in PyTorch如何在 PyTorch 中执行 sum pooling
【发布时间】:2018-11-23 03:11:15
【问题描述】:

如何在 PyTorch 中执行 sum pooling。具体来说,如果我们输入(N, C, W_in, H_in) 并希望使用特定的kernel_sizestride 输出(N, C, W_out, H_out),就像nn.Maxpool2d 一样?

【问题讨论】:

    标签: conv-neural-network pytorch max-pooling spatial-pooling


    【解决方案1】:

    您可以使用执行平均池化的torch.nn.AvgPool1d(或torch.nn.AvgPool2dtorch.nn.AvgPool3d) - 与总池化成正比。如果您真的想要求和值,可以将平均输出乘以池化表面。

    【讨论】:

    • 你的意思是,首先我执行 Avgpool2d,然后如果我的内核大小为 4,则将结果张量乘以 4?
    • 是的,首先平均池化,然后将结果乘以 4 * 4 = 16,如果是 kernel_size=4(因为这意味着平均值是在 4 * 4 = 16 元素的区域上计算的)。
    【解决方案2】:

    扩展benjaminplanche's answer
    我也需要总和池,它似乎并不直接存在,但它相当于运行一个带有权重参数的 conv2d。我认为运行 AvgPool2d 并乘以内核大小乘积会更快。事实证明,不完全是。

    前面的底线:
    使用torch.nn.functional.avg_pool2d及其相关函数并乘以内核大小。

    我发现在 Jupyter 中进行测试:

    (开销)

    %%timeit
    x = torch.rand([1,1,1000,1000])
    >>> 3.49 ms ± 4.72 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    %%timeit
    _=F.avg_pool2d(torch.rand([1,1,1000,1000]), [10,10])*10*10
    >>> 4.99 ms ± 74.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    (所以 1.50 ms ± 79.0 µs)(我发现 *10*10 只在图中增加了大约 20 µs)

    avePool = nn.AvgPool2d([10, 10], 1, 0)

    %%timeit
    _=avePool(torch.rand([1,1,1000,1000]))*10*10
    >>> 80.9 ms ± 1.57 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    (所以 77.4 毫秒 ± 1.58 毫秒)

    y = torch.ones([1,1,10,10])

    %%timeit
    _=F.conv2d(torch.rand([1,1,1000,1000]), y)
    >>> 14.4 ms ± 421 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    (所以 10.9 毫秒 ± 426 微秒)

    sumPool = nn.Conv2d(1, 1, 10, 1, 0, 1, 1, False)
    sumPool.weight = torch.nn.Parameter(y)
    
    %%timeit
    _=sumPool(torch.rand([1,1,1000,1000]))
    >>> 7.24 ms ± 63.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    (所以 3.75 毫秒 ± 68.3 微秒)

    作为健全性检查。

    abs_err = torch.max(torch.abs(avePool(x)*10*10 - sumPool(x)))
    magnitude = torch.max(torch.max(avePool(x)*10*10, torch.max(sumPool(x))))
    relative_err = abs_err/magnitude
    abs_err.item(), magnitude.item(), relative_err.item()
    >>> (3.814697265625e-06, 62.89910125732422, 6.064788493631568e-08)
    

    这可能是一个合理的舍入相关错误。

    我不知道为什么功能版本比制作专用内核更快,但是看起来如果您想制作专用内核,更喜欢Conv2D版本,并且使用sumPool.weights.requires_grad = Falsewith torch.no_grad():使权重无法训练在创建内核参数期间。这些结果可能会随着内核大小而变化,因此如果您需要加快这部分的速度,请测试您自己的应用程序。如果我错过了什么,请告诉我...

    【讨论】:

      【解决方案3】:

      https://pytorch.org/docs/stable/generated/torch.nn.AvgPool2d.html#torch.nn.AvgPool2d 找到 divisor_override。
      设置 divisor_override=1
      你会得到一个 sumpool

      import torch
      input = torch.tensor([[[1,2,3],[3,2,1],[3,4,5]]])
      sumpool = torch.nn.AvgPool2d(2, stride=1, divisor_override=1)
      sumpool(input)
      

      你会得到

      tensor([[[ 8,  8],
               [12, 12]]])
      

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 2018-10-28
        • 2016-12-20
        • 2018-01-14
        • 1970-01-01
        • 2014-07-29
        相关资源
        最近更新 更多