import torch
import torch.nn as nn
import torch.nn.functional as F
nn中定义的是类,functional里面定义的是函数操作。
输出shape的计算公式:
o u t _ s h a p e = r o u n d _ m o d e ( i n _ s h a p e + 2 ∗ p a d d i n g − k e r n e l _ s i z e s t r i d e + 1 ) out\_shape = round\_mode (\frac{in\_shape + 2 * padding - kernel\_size}{stride} + 1) out_shape=round_mode(stridein_shape+2∗padding−kernel_size+1)
默认的round_mode为floor,即向下取整。可以通过ceil_mode开关,指定为向上取整。
pool
平均池化
avg_pool2d
F.avg_pool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, divisor_override=None)->Tensor
input: [B, C, iH, iW]
kernel_size: 池化区域尺寸。单独的数或者[kH, kW]元组。
stride: 池化操作步长。单独的数或者[sH, sW]元组,默认值是kernel_size。
padding:输入两边padding数目。单独的数或者[padH, padW]元组。默认值是0。
ceil_mode: 如果为True,计算输出shape时使用ceil模式,否则为floor模式。默认是False。
在一个 k H × k W kH \times kW kH×kW的区域内做步长为 s H × s W sH \times sW sH×sW的 2 D 2D 2D平均池化操作。这里的 i H iH iH, k H kH kH, s H sH sH命名有点迷惑性,初看以为是相乘,其实每个就是一个独立名称,分别代表了 i n p u t _ h e i g h t input\_height input_height, k e r n e l _ h e i g h t kernel\_height kernel_height, s t r i d e _ h e i g h t stride\_height stride_height。
实际的底层pool计算逻辑:
o u t ( N i , C j , h , w ) = 1 k H × k W ∑ m = 0 k H − 1 ∑ n = 0 k W − 1 i n p u t ( N i , C j , s t r i d e [ 0 ] × h + m , s t r i d e [ 1 ] × w + n ) out(N_i, C_j, h, w) = \frac{1}{kH\times kW}\sum_{m=0}^{kH-1}\sum_{n=0}^{kW-1}input(N_i, C_j, stride[0] \times h + m, stride[1] \times w + n) out(Ni,Cj,h,w)=kH×kW1m=0∑kH−1n=0∑kW−1input(Ni,Cj,stride[0]×h+m,stride[1]×w+n)
input = torch.rand(1, 3, 64, 64)
output = F.avg_pool2d(input, kernel_size=4, stride=2, padding=1) # [1, 3, 32, 32]
AvgPool2d
nn.AvgPool2d(input, kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, divisor_override=None)
作用和F.avg_pool2d()是一样的,只是一个是函数,一个是类。
自适应平均池化
adaptive_avg_pool2d
F.adaptive_avg_pool2d(input, output_size)
具体参见下面的AdaptiveAvgPool2d。
AdaptiveAvgPool2d
nn.AdaptiveAvgPool2d(output_size)
不同于上面的AvgPool2d指定了滤波器的各种参数,得到输出特征。这里是指定输出特征的尺寸,算法自行计算出合适的滤波器参数,输出特征可以满足指定的尺寸要求。