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×kW1?m=0∑kH?1?n=0∑kW?1?input(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指定了濾波器的各種參數,得到輸出特征。這里是指定輸出特征的尺寸,算法自行計算出合適的濾波器參數,輸出特征可以滿足指定的尺寸要求。