nn.AdaptiveAvgPool2d(output_size)输入和输出怎么回事?

前言

nn.AdaptiveAvgPool2d(output_size)
函数作用:自适应进行平均池化。不用管输入、stride、padding,函数参数只有输出大小,其他的这个函数帮你搞定。
问题就是,我想知道他是咋搞定的?

1 函数的使用

先把例子摆上来:

input = torch.randn(20, 3, 10, 9)
m = nn.AdaptiveAvgPool2d((5, 7))
output = m(input)

1.1 输入输出

  • 输入 input 应为:(N, C, H_in, W_in) (C, H_in W_in)。这里的 N 表示batch_size,C 表示通道数量。
  • 输出 output 为: (N, C, S_0, S_1) (C, S_0, S_1) ,这里 C 不会改变。

1.2 写法

假设输入是input = torch.randn(20, 3, 10, 9)
他的参数有三种写法:

  1. 如果目标输出size是 5x7: m = nn.AdaptiveAvgPool2d((5, 7))
  2. 如果目标输出size是7x7,即长宽一样,就可以写成:m = nn.AdaptiveAvgPool2d(7)
  3. 如果目标输出size是10x7,即某一边与输入一样,就可以写成m = nn.AdaptiveAvgPool2d((None, 7))

2 函数是咋自适应的?

2.1 结论

2.1.1 input size 可以整除 output size

o u t p u t = i n p u t + 2 ∗ p a d d i n g − k e r n e l s t r i d e + 1 output = \frac{input+2*padding -kernel}{stride}+1 output=strideinput+2paddingkernel+1
其中 p a d d i n g = 0 、 s t r i d e = i n p u t o u t p u t , k e r n e l = i n p u t − ( o u t p u t − 1 ) ∗ s t r i d e padding=0、stride=\frac{input}{output},kernel=input-(output-1)*stride padding=0stride=outputinputkernel=input(output1)stride

举例:input size = 6*6,output = 2*3
计算:padding = 0、stride为3和2、kernel size = 3*2
代码验证:

m = nn.AdaptiveAvgPool2d((2, 3))
temp = torch.tensor([1.0,2,3,4,5,6,7,8,9,0,
                     1.0,2,3,4,5,6,7,8,9,0,
                     1.0,2,3,4,5,6,7,8,9,0,
                     1.0,2,3,4,5,6])
input = temp.reshape(1,6,6)
print("input1")
print(input)
output = m(input)
print("output1")
print(output)

nn.AdaptiveAvgPool2d(output_size)输入和输出怎么回事?_第1张图片

2.1.2 不能整除的时候

自适应公式是这样的:
i 从0开始:
K i = c e i l ( ( i + 1 ) ∗ i n p u t o u t p u t ) − f l o o r ( i ∗ i n p u t o u t p u t ) K_i=ceil((i+1)*\frac{input}{output})-floor(i*\frac{input}{output}) Ki=ceil((i+1)outputinput)floor(ioutputinput)

S i = f l o o r ( ( i + 1 ) ∗ i n p u t o u t p u t ) − f l o o r ( i ∗ i n p u t o u t p u t ) S_i=floor((i+1)*\frac{input}{output})-floor(i*\frac{input}{output}) Si=floor((i+1)outputinput)floor(ioutputinput)

上述公式由源码推导,实际代码中并没有去计算核大小和步长,因为核大小和步长是在不算变化的。

举例解释一波:
假设我们输入size是1维的14,我们想要的输出的size是4,
14/4=3.5
那么我们核大小就为向上取整为4,步长随之而变
在这里插入图片描述
输出的size改为3,
14/3=4.666
那么我们核大小就为向上取整为5,步长随之而变
在这里插入图片描述

2.2 推导

pytorch官网代码
参考连接
nn.AdaptiveAvgPool2d(output_size)输入和输出怎么回事?_第2张图片
nn.AdaptiveAvgPool2d(output_size)输入和输出怎么回事?_第3张图片

你可能感兴趣的:(深度学习,python,pytorch)