Adaptive Poolingとは?
Poolingを行う時に、kernel sizeをoverlapが極力ないように自動で調整してくれるpooling層です。
例えば、下記のようにinputとoutputのサイズが決まっている1次元の配列を考えます。

この時、stride(フィルターを適用する間隔)は out_length/in_length の商から1となります。またkernel size(フィルターの大きさ)は、padding(入力サイズ調整のための0埋め)がない場合、こちらの計算式より逆説的に3(kernel size= input – stride(output – 1))と求められます。
この時、MaxPoolingを適用した場合は下記のように計算されます。

一方、Adaptive Poolingの場合は、overlapを防ぐようにkernel sizeが自動調整されているので下記のように計算されます。

精度に関しては、最初と最後の要素が異なるだけなので実用上どちらでも問題なさそうです。(実装は当然Adaptive poolingの方が楽)
またAdaptive max poolingは、出力に近い位置で、チャンネル毎のシーケンス長の次元圧縮で使われているようです(1次元の場合)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import torch import torch.nn as nn class Conv1D(nn.Module): def __init__(self): super(Conv1D, self).__init__() self.conv1 = nn.Conv1d(in_channels=1, out_channels=64, kernel_size=8) self.bn1 = nn.BatchNorm1d(64) self.relu = nn.ReLU() self.conv2 = nn.Conv1d(in_channels=64, out_channels=64, kernel_size=8) self.bn2 = nn.BatchNorm1d(64) self.dropout = nn.Dropout(0.3) self.gap = nn.AdaptiveAvgPool1d(1) self.fc = nn.Linear(64, 1) def forward(self, x): x = self.conv1(x) x = self.relu(x) x = self.bn1(x) x = self.dropout(x) x = self.conv2(x) x = self.relu(x) x = self.bn2(x) x = self.dropout(x) x = self.gap(x) x = x.view(x.size(0),-1) x = self.fc(x) return x if __name__ == "__main__": input = torch.randn(10, 1, 511) # N, C in, L in model = Conv1D() out = model(input) |
pytorchの公式Documuentはこちらになります。(Adaptive max poolingの方は説明が少なく初見ではわからなかった…)
スポンサーリンク
スポンサーリンク