07 · Architektury · 4 min czytania · Interaktywne · aktualizacja
Co to jest pooling, stride i padding w sieci konwolucyjnej i jak policzyć rozmiar wyjścia?
W skrócie
Dopełnienie (padding) chroni brzegi obrazu, krok (stride) przeskakuje pozycje filtra, a pooling streszcza okienka. Razem ustalają rozmiar map cech w CNN.
Co to jest
Dopełnienie (padding), krok (stride) i pooling to trzy ustawienia, które decydują, jak duże są mapy cech w sieci konwolucyjnej. Dopełnienie dokleja wokół obrazu ramkę (zwykle zer), żeby filtr mógł stanąć także na brzegach. Krok mówi, o ile pikseli filtr przesuwa się między kolejnymi pozycjami. Pooling (np. max pooling 2×2) zastępuje każde okienko jedną liczbą — maksimum albo średnią — i w ten sposób zmniejsza mapę.
Rozmiar wyjścia wzdłuż jednego wymiaru opisuje jeden wzór: n_out = ⌊(n + 2p − k) / s⌋ + 1, gdzie n to rozmiar wejścia, k rozmiar filtra (lub okna poolingu), p dopełnienie z każdej strony, s krok, a ⌊ ⌋ to zaokrąglenie w dół.
Intuicja: splot z krokiem 1 to czytanie obrazu przez lupę, przesuwaną piksel po pikselu. Krok 2 to przeskakiwanie co drugą pozycję — szybciej i z mniejszym wynikiem. Pooling to streszczenie: „w tym kwadracie 2×2 najsilniejszy sygnał krawędzi miał wartość 40” — bez informacji, w którym dokładnie pikselu.
Mechanizm — dlaczego tak działa
Dopełnienie rozwiązuje dwa problemy. Bez niego każdy splot 3×3 zjada po pikselu z każdej strony: obraz 8×8 staje się 6×6, potem 4×4, potem 2×2 — po trzech warstwach prawie nic nie zostaje. Po drugie, piksele brzegowe trafiają pod filtr rzadziej niż środkowe, więc informacja z krawędzi obrazu ma mniejszy wpływ. Dopełnienie „same” (dla k = 3 to p = 1) zachowuje rozmiar mapy i pozwala budować głębokie sieci. Ceną są sztuczne zera na brzegach, które filtr może brać za krawędź.
Krok większy niż 1 zmniejsza rozdzielczość już w trakcie splotu. Krok 2 dzieli rozmiar mapy na pół, a liczbę obliczeń w następnych warstwach — mniej więcej na cztery. Jest to podpróbkowanie, które sieć może się nauczyć robić „mądrze”, bo filtr ze stridem ma uczone wagi.
Pooling robi podpróbkowanie bez wag. Max pooling przepuszcza najsilniejszą odpowiedź z okienka, co ma sens, gdy pytanie brzmi „czy w tym rejonie jest krawędź?”, a nie „gdzie dokładnie?”. Daje to lokalną odporność na drobne przesunięcia: jeśli najsilniejszy piksel przesunie się w obrębie okna, wynik się nie zmieni. Average pooling uśrednia i lepiej zachowuje informację o „ilości” cechy; w wersji globalnej (cała mapa → jedna liczba) zastąpił w nowoczesnych CNN ogromne warstwy gęste na końcu sieci.
Wszystkie trzy mechanizmy powiększają pole recepcyjne. Trzy sploty 3×3 z krokiem 1 widzą okno 7×7; jeśli między nimi stoi pooling 2×2, neurony głębszej warstwy obejmują znacznie większy fragment obrazu. Dzięki temu głębokie warstwy mogą wykrywać całe obiekty, a nie tylko krawędzie. Zastrzeżenie: każde podpróbkowanie wyrzuca informację o dokładnym położeniu, co szkodzi w segmentacji — stąd architektury typu U-Net, które ją odzyskują połączeniami skrótowymi.
Na przykładzie
Obraz z Digits ma 8×8 pikseli. Splot 3×3 bez dopełnienia: ⌊(8 + 0 − 3)/1⌋ + 1 = 6, mapa 6×6. Z dopełnieniem p = 1: ⌊(8 + 2 − 3)/1⌋ + 1 = 8, rozmiar zachowany. Z krokiem 2 i p = 1: ⌊(8 + 2 − 3)/2⌋ + 1 = 4. Max pooling 2×2 z krokiem 2: ⌊(8 − 2)/2⌋ + 1 = 4. Na pierwszej cyfrze zbioru (zerze) splot filtrem pionowej krawędzi daje mapę 6×6, której max pooling 2×2 streszcza do 3×3; lewa górna komórka to maksimum z wartości 33, 27, 40 i 10, czyli 40. Average pooling tego samego okna dałby 27,5.
Ten sam wzór opisuje wejście ResNet-50: obraz 224×224, splot 7×7 z krokiem 2 i p = 3 daje ⌊(224 + 6 − 7)/2⌋ + 1 = 112, a max pooling 3×3 z krokiem 2 i p = 1 — ⌊(112 + 2 − 3)/2⌋ + 1 = 56. Po dwóch operacjach mapa jest 4 razy mniejsza w każdym wymiarze, czyli ma 16 razy mniej pozycji. Dla porównania: trzy sploty 3×3 na 64 kanałach (pole 7×7) mają 3·9·64·64 = 110 592 wagi, a jeden splot 7×7 — 49·64·64 = 200 704, prawie dwa razy więcej.
Dane: Digits (ręcznie pisane cyfry 8×8)
W praktyce
- W PyTorch:
nn.Conv2d(c_in, c_out, kernel_size=3, stride=1, padding=1); od wersji 1.9 można też podaćpadding="same"(tylko dlastride=1). - Pooling:
nn.MaxPool2d(2),nn.AvgPool2d(2), a na końcu siecinn.AdaptiveAvgPool2d(1), który działa dla dowolnego rozmiaru wejścia. - Zasada kciuka: k = 3, p = 1, s = 1 zachowuje rozmiar; s = 2 albo pooling 2×2 dzieli go na pół.
- Gdy (n + 2p − k) nie dzieli się przez s, ostatnie piksele są po cichu pomijane — warto sprawdzać kształty
print(x.shape)po każdej warstwie. - Wiele nowoczesnych sieci zamiast poolingu stosuje sploty z krokiem 2, bo wtedy podpróbkowanie ma uczone wagi.
Najczęstsze pytania
- Max pooling czy average pooling?
- Max pooling częściej w środku sieci, bo przepuszcza najsilniejszy sygnał i jest odporny na drobne przesunięcia. Globalny average pooling standardowo na końcu, przed klasyfikatorem. Różnice w dokładności są zwykle niewielkie.
- Czy pooling ma parametry do uczenia?
- Nie — to stała operacja (maksimum lub średnia). Dlatego nie zwiększa liczby parametrów, ale też nie może się dopasować do danych, w przeciwieństwie do splotu z krokiem 2.
- Jakie dopełnienie wybrać?
- Najczęściej zerowe, o wielkości (k − 1)/2, żeby zachować rozmiar. Dla obrazów, w których brzeg ma znaczenie, stosuje się czasem dopełnienie odbiciem lustrzanym (`padding_mode="reflect"`).
Źródła
- Dumoulin, Visin „A guide to convolution arithmetic for deep learning”, arXiv:1603.07285, 2016.
- Goodfellow, Bengio, Courville „Deep Learning”, MIT Press, 2016, rozdz. 9.3 („Pooling”).
- Zhang i in. „Dive into Deep Learning”, d2l.ai, rozdz. 7.3 („Padding and Stride”) i 7.5 („Pooling”).
- He, Zhang, Ren, Sun „Deep Residual Learning for Image Recognition”, CVPR 2016.
- Dokumentacja PyTorch:
torch.nn.MaxPool2d, https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html