自适应池化的目标是输出固定尺寸(自适应池化 - 图1)的池化层

    nn.AdaptiveAvgPool2d 实现和普通的池化层有所差异:

    源代码如下:

    自适应池化 - 图2

    可以看到自适应池化的做法是:为了输出固定尺寸的图像,根据 自适应池化 - 图3 的大小划分成 自适应池化 - 图4 个前闭后开区间,对这个区间上的数进行池化操作。(其实多维度在宽高是分别计算,这里为了统一描述,不做区分)

    然而由于 自适应池化 - 图5 计算结果可能是小数,在取整的过程中可能,会使各个区间的划分的大小不一致,相邻区间也可能也会有共享元素,可能没有共享元素。所以并不是像普通池化那样,固定 自适应池化 - 图6自适应池化 - 图7 以一个固定尺寸向滑动。

    下面举一个1维具体的例子:

    输入特征图 自适应池化 - 图8 ,输入尺度 自适应池化 - 图9 ,输出固定尺度 自适应池化 - 图10,所以 自适应池化 - 图11

    所以对应的 4 个池化区间分别是:

    自适应池化 - 图12自适应池化 - 图13 ,即 自适应池化 - 图14#card=math&code=%5B0%2C3%29),均值为 1.0

    自适应池化 - 图15自适应池化 - 图16 ,即 自适应池化 - 图17#card=math&code=%5B2%2C6%29),均值为 3.5

    自适应池化 - 图18自适应池化 - 图19 ,即 自适应池化 - 图20#card=math&code=%5B5%2C9%29),均值为 6.5

    自适应池化 - 图21自适应池化 - 图22,即 自适应池化 - 图23#card=math&code=%5B8%2C11%29),均值为 9.0

    则输出特征图:自适应池化 - 图24

    指定输出特征图的梯度:自适应池化 - 图25

    反向传播后特征图的梯度:自适应池化 - 图26自适应池化 - 图27

    测试代码如下:

    1. import torch
    2. a = torch.arange(0, 11., requires_grad=True)
    3. b = torch.nn.functional.adaptive_avg_pool1d(a[None, None], 4)
    4. b.backward(torch.arange(1., 1+b.size(-1))[None, None])
    5. print(a, b, a.grad)

    结果如下:

    1. tensor([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
    2. requires_grad=True)
    3. tensor([[[1.0000, 3.5000, 6.5000, 9.0000]]], grad_fn=<SqueezeBackward1>)
    4. tensor([0.3333, 0.3333, 0.8333, 0.5000, 0.5000, 1.2500, 0.7500, 0.7500, 2.0833,
    5. 1.3333, 1.3333])