[開發技巧]·AdaptivePooling與Max/AvgPooling相互轉換
我的網站--> http://www.yansongsong.cn/python
1.問題描述
自適應池化Adaptive Pooling是PyTorch的一種池化層,根據1D,2D,3D以及Max與Avg可分爲六種形式。c++
自適應池化Adaptive Pooling與標準的Max/AvgPooling區別在於,自適應池化Adaptive Pooling會根據輸入的參數來控制輸出output_size,而標準的Max/AvgPooling是經過kernel_size,stride與padding來計算output_size: git
output_size = ceil ( (input_size+2∗padding−kernel_size)/stride)+1github
Adaptive Pooling僅存在與PyTorch,若是須要將包含Adaptive Pooling的代碼移植到Keras或者TensorFlow就會遇到問題。bash
本文將提供一個公式,能夠簡便的將AdaptivePooling準換爲Max/AvgPooling,便於你們移植使用。app
2.原理講解
咱們已經知道了普通Max/AvgPooling計算公式爲:output_size = ceil ( (input_size+2∗padding−kernel_size)/stride)+1 框架
當咱們使用Adaptive Pooling時,這個問題就變成了由已知量input_size,output_size求解kernel_size與strideide
爲了簡化問題,咱們將padding設爲0(後面咱們能夠發現源碼裏也是這樣操做的c++源碼部分)學習
stride = floor ( (input_size / (output_size) )網站
kernel_size = input_size − (output_size−1) * stride
3.實戰演示
下面咱們經過一個實戰來操做一下,驗證公式的正確性
輸出結果
tensor([[[ 0.9095, 0.8043, 0.4052, 0.3410, 1.8831, 0.8703, -0.0839],
[ 0.3300, -1.2951, -1.8148, -1.1118, -1.1091, 1.5657, 0.7093],
[-0.6788, -1.2790, -0.6456, 1.9085, 0.8627, 1.1711, 0.5614],
[-0.0129, -0.6447, -0.6685, -1.2087, 0.8535, -1.4802, 0.5274],
[ 0.7347, 0.0374, -1.7286, -0.7225, -0.4257, -0.0819, -0.9878],
[-1.2553, -1.0774, -0.1936, -1.4741, -0.9028, -0.1584, -0.6612]],
[[-0.3473, 1.0599, -1.5744, -0.2023, -0.5336, 0.5512, -0.3200],
[-0.2518, 0.1714, 0.6862, 0.3334, -1.2693, -1.3348, -0.0878],
[ 1.0515, 0.1385, 0.4050, 0.8554, 1.0170, -2.6985, 0.3586],
[-0.1977, 0.8298, 1.6110, -0.9102, 0.7129, 0.2088, 0.9553],
[-0.2218, -0.7234, -0.4407, 1.0369, -0.8884, 0.3684, 1.2134],
[ 0.5812, 1.1974, -0.1584, -0.0903, -0.0628, 3.3684, 2.0330]]])
tensor([[[-0.3627, 0.0799, 0.7145],
[-0.5343, -0.7190, -0.3686]],
[[ 0.1488, -0.0314, -0.4797],
[ 0.2753, 0.0900, 0.8788]]])
tensor([[[-0.3627, 0.0799, 0.7145],
[-0.5343, -0.7190, -0.3686]],
[[ 0.1488, -0.0314, -0.4797],
[ 0.2753, 0.0900, 0.8788]]])
能夠發現adp = t.nn.AdaptiveAvgPool2d(list(outputsz))與avg = t.nn.AvgPool2d(kernel_size=list(kernelsz),stride=list(stridesz))結果一致
爲了防止這是偶然現象,修改參數,使用AdaptiveAvgPool1d進行試驗
輸出結果
tensor([[[ 1.3405, 0.3509, -1.5119, -0.1730, 0.6971, 0.3399, -0.0874,
-1.2417, 0.6564],
[ 2.0482, 0.3528, 0.0703, 1.2012, -0.8829, -0.3156, 1.0603,
-0.7722, -0.6086],
[ 1.0470, -0.9374, 0.3594, -0.8068, 0.5126, 1.4135, 0.3538,
-1.0973, 0.3046]],
[[-0.1688, 0.7300, -0.3457, 0.5645, -1.2507, -1.9724, 0.4469,
-0.3362, 0.7910],
[ 0.5676, -0.0614, -0.0243, 0.1529, 0.8276, 0.2452, -0.1783,
0.7460, 0.2577],
[-0.1433, -0.7047, -0.4883, 1.2414, -1.4316, 0.9704, -1.7088,
-0.0094, -0.3739]]])
tensor([[[ 0.0598, -0.3293, 0.3165, -0.2242],
[ 0.8237, 0.1295, -0.0461, -0.1069],
[ 0.1563, 0.0217, 0.7600, -0.1463]],
[[ 0.0718, -0.3440, -0.9254, 0.3006],
[ 0.1606, 0.3187, 0.2982, 0.2751],
[-0.4454, -0.2262, -0.7233, -0.6973]]])
tensor([[[ 0.0598, -0.3293, 0.3165, -0.2242],
[ 0.8237, 0.1295, -0.0461, -0.1069],
[ 0.1563, 0.0217, 0.7600, -0.1463]],
[[ 0.0718, -0.3440, -0.9254, 0.3006],
[ 0.1606, 0.3187, 0.2982, 0.2751],
[-0.4454, -0.2262, -0.7233, -0.6973]]])
能夠發現adp = t.nn.AdaptiveAvgPool1d(list(outputsz))與avg = t.nn.AvgPool1d(kernel_size=list(kernelsz),stride=list(stridesz))結果也是相同的。
4.總結分析
在之後遇到別人代碼使用Adaptive Pooling,能夠經過這兩個公式轉換爲標準的Max/AvgPooling,從而應用到不一樣的學習框架中
stride = floor ( (input_size / (output_size) )
kernel_size = input_size − (output_size−1) * stride
只須要知道輸入的input_size ,就能夠推導出stride 與kernel_size ,從而替換爲標準的Max/AvgPooling
Hope this helps