Strona głównaArtykułyDeep Learning

Convolutional Neural Networks: A Deep Dive

Convolutional Neural Networks (CNNs) have revolutionized image recognition and computer vision. This guide breaks down the core principles, from convolutional layers extracting features to pooling layers reducing dimensionality and activation functions introducing non-linearity. We'll explore how these components work together to create powerful models.

mysimulator teamZaktualizowano — czerwiec 2026≈ 12 min czytania▶ Otwórz symulację

Sieć to funkcja, którą można różniczkować

Pozbaczmy metafory biologicznej i sieć neuronowa typu feed-forward to długa łańcuch reakcji: transformacja afiniczna (mnożenie przez macierz współczynników, dodawanie błędu) i nieliniowość zastosowana element po elemencie. Sieć z dwoma ukrytymi warstwami jest niczym

a⁰ = x // wejście z¹ = W¹ a⁰ + b¹ a¹ = φ(z¹) // warstwa ukryta 1 z² = W² a¹ + b² a² = φ(z²) // warstwa ukryta 2 z³ = W³ a² + b³ ŷ = σ(z³) // wyjście L = strata(ŷ, y) // pojedyncza wartość Nieliniowość nie jest ozdobą. Usuń ją i cała konstrukcja zawali się: suma transformacji afinicznych to jedna transformacja afiniczna, a setna warstwa ma dokładnie tę samą ekspresyjną moc co jedna. To φ daje ci wszystko.

Trenowanie polega na znalezieniu wag, które minimalizują L. L jest funkcją skalarnej o kilku tysiącach lub miliardach parametrów, więc naturalnym narzędziem jest metoda gradientu – delikatnie przesuwaj każdy parametr w kierunku jego pochodnej cząstkowej względem L. Jedynym pytaniem jest jak uzyskać miliony tych pochodnych cząstkowych bez wykonywania milionów oddzielnych obliczeń. To właśnie wsteczna propagacja odpowiada na to pytanie.

a⁰ = x                                  // the input
z¹ = W¹ a⁰ + b¹      a¹ = φ(z¹)          // hidden layer 1
z² = W² a¹ + b²      a² = φ(z²)          // hidden layer 2
z³ = W³ a² + b³      ŷ  = σ(z³)          // output
L  = loss(ŷ, y)                          // a single number
demo na żywo · powiązana symulacja● LIVE

Zasada łańcuchowa, zastosowana w sposób ekonomiczny

Można obliczyć ∂L/∂w za pomocą różnic skończonych: zmodyfikuj w, uruchom sieć ponownie i obserwuj zmianę L. Kosztuje to jeden pełny przebieg do przodu dla każdego parametru – niewyjałowicie droga i zawodne obliczeniowo. Zamiast tego, backpropagation stosuje zasadę łańcuchową od tyłu z funkcji strat i oblicza każdy gradient w sieci w jednym przebiegu wstecznym, którego koszt jest zbliżony do kosztu jednego przebiegu do przodu.

Kluczem jest propagowanie jednej wartości pośredniej, konwencjonalnie zapisywanej jako δ – wrażliwości straty na preaktywację z:

δᴸ = ∂L/∂zᴸ = ∇_ŷ L ⊙ σ'(zᴸ) // warstwa wyjściowa δˡ = (Wˡ⁺¹ᵀ δˡ⁺¹) ⊙ φ'(zˡ) // każda wcześniejsza warstwa ∂L/∂Wˡ = δˡ (aˡ⁻¹)ᵀ // gradient wag ∂L/∂bˡ = δˡ // gradient biasów Przeczytaj uważnie środkową linię, ponieważ to jest cały algorytm: aby uzyskać sygnał błędu na warstwie, weź sygnał błędu z warstwy powyżej, przesła go wstecz przez transpozycję macierzy wag tej warstwy i zmodyfikuj go przez pochodną aktywacji tej warstwy. Przebieg do przodu wysyła aktywacje w górę przez W; przebieg wsteczny wysyła błędy w dół przez Wᵀ. Gradient dla każdego ciężaru jest wtedy po prostu iloczynem zewnętrznym przychodzącego sygnału błędu na jego wyjściu i aktywacji, która weszła do jego wejścia.

Wnioski są następujące. Po pierwsze, musisz buforować aktywacje z przebiegu do przodu – przebieg wsteczny potrzebuje każdego aˡ⁻¹ i każdej zˡ. Dlatego też szkolenie głębokiej sieci kosztuje znacznie więcej pamięci niż jej uruchomienie. Drugi, backpropagation nie jest algorytmem uczenia się; to obliczenie gradientu. Uczenie się odbywa się przez optymalizator, który konsumuje te gradienty.

δᴸ = ∂L/∂zᴸ = ∇_ŷ L ⊙ σ'(zᴸ)              // output layer

δˡ = (Wˡ⁺¹ᵀ δˡ⁺¹) ⊙ φ'(zˡ)                 // every earlier layer

∂L/∂Wˡ = δˡ (aˡ⁻¹)ᵀ                        // gradient of the weights
∂L/∂bˡ = δˡ                                // gradient of the biases

Aktywacje i zanikający gradient

Sigmoid, φ(z) = 1/(1 + e^(-z)), był klasycznym wyborem, a jego pochodna jest przyczyną, dla której głębokie sieci przez lata uważano za nieuczalne. Ta pochodna to φ(z)(1 − φ(z)), która ma maksymalną wartość 0,25 przy z = 0 i spada do prawie zera, gdy neuron się saturuje. Każdy warstwa backpropagation mnoży sygnał błędu przez jeden z tych czynników — więc przez dziesięć warstw sigmoid gradient jest przeskalowany najwyżej o 0,25¹⁰ ≈ 10⁻⁶ nawet w najlepszym przypadku. Jest to problem zanikającego gradientu: wczesne warstwy otrzymują zasadniczo bez sygnału i nigdy nie uczą się.

φ(z) = 1/(1+e^(-z)) φ'(z) = φ(1−φ) ∈ (0, 0.25] saturuje φ(z) = tanh(z) φ'(z) = 1 − tanh²z ∈ (0, 1] zero-centered φ(z) = max(0, z) φ'(z) = 1 if z > 0 ∈ {0, 1} ReLU else 0 może umrzeć φ(z) = max(αz, z) φ'(z) = 1 or α lekkie ReLU, α ≈ 0.01 ReLU rozwiązuje to brutalną siłą: dla jakiegokolwiek dodatniego wejścia jego pochodna jest dokładnie 1, więc sygnał błędu przechodzi niezmieniony bez względu na to, ile warstw go przecina. Jego własna patologia to umierający ReLU — jednostka pchnięta trwale ujemnie ma zerowy gradient na zawsze i nigdy nie może się z niego wyleczyć — które lekkie ReLU i jego krewni łagodzią, dając negatywnej stronie mały nachylenie.

φ(z) = 1/(1+e^-z)     φ'(z) = φ(1−φ)      ∈ (0, 0.25]   saturates
φ(z) = tanh(z)        φ'(z) = 1 − tanh²z   ∈ (0, 1]      zero-centred
φ(z) = max(0, z)      φ'(z) = 1 if z > 0   ∈ {0, 1}      ReLU
                                 else 0                  can die
φ(z) = max(αz, z)     φ'(z) = 1 or α       leaky ReLU, α ≈ 0.01

Inicjalizacja nie jest szczegółem

Zainicjuj wszystkie wagi zerami, a każda neuronka w warstwie oblicza to samo, otrzymuje ten sam gradient i pozostaje identyczna na zawsze: sieć nigdy nie łamie symetrii i zachowuje się jak pojedyncza jednostka na warstwę. Dlatego wagi muszą być losowe. Ale ich skala ma tak samo duże znaczenie, ponieważ wariancja sygnału jest mnożona warstwa po warstwie – zbyt duża powoduje wybuchające aktywacje, a zbyt mała sprawia, że upadają do zera. Dwa standardowe schematy utrzymują tę wariancję na poziomie 1:

Xavier / Glorot   Var(W) = 2 / (fan_in + fan_out)   for tanh, sigmoid
He / Kaiming      Var(W) = 2 / fan_in                for ReLU
                  (the factor 2 compensates for ReLU zeroing half
                   the activations, which halves the variance)

Od gradientów do uczenia się

Z gradientami w ręku, zasada aktualizacji jest ostatnią decyzją. Prosta stochastyczna regresja gradientu (SGD) wykonuje krok w kierunku przeciwnym do gradientu mini-partii. Momentum akumuluje wykładniczo zanikającą średnią z przeszłych gradientów, co tłumi oscylacje na stromych ścianach doliny i przyspiesza jej dno. Adam utrzymuje bieżące szacunki pierwszej i drugiej chwili gradientu oraz dzieli przez pierwiastek kwadratowy z drugiego – nadaje każdemu parametrowi własną efektywną szybkość uczenia się.

SGD w -= lr * g Momentum v = μ*v + g ; w -= lr * v μ ≈ 0.9 Adam m = β₁*m + (1−β₁)*g β₁ ≈ 0.9 v = β₂*v + (1−β₂)*g² β₂ ≈ 0.999 (koryguje bias m̂, v̂ przez 1−βᵗ) w -= lr * m̂ / (sqrt(v̂) + ε) ε ≈ 1e-8 Szybkość uczenia się pozostaje jedynym najważniejszym hiperparametrem: zbyt duża powoduje rozpad lub oscylacje straty, zbyt mała zatrzymuje trening na płaskim dnie. A gdy sieć w ogóle nie uczy się, pierwszym co należy sprawdzić, to nie architektura, ale same gradienty – porównaj kilka analitycznych gradientów z centralną różnicą skończoną, (L(w+ε) − L(w−ε)) / 2ε, na małej sieci z podwójną precyzją. Implementacja wstecznej propagacji z błędem znaku lub pominiętym transpozycją wygląda identycznie jak źle dostrojona, a tylko sprawdzanie gradientów rozróżnia obie.

SGD          w -= lr * g
Momentum     v = μ*v + g            ;  w -= lr * v          μ ≈ 0.9
Adam         m = β₁*m + (1−β₁)*g                             β₁ ≈ 0.9
             v = β₂*v + (1−β₂)*g²                            β₂ ≈ 0.999
             (bias-correct m̂, v̂ by 1−βᵗ)
             w -= lr * m̂ / (sqrt(v̂) + ε)                     ε ≈ 1e-8

Często zadawane pytania

Czy wsteczna propagacja jest to samo co zejście gradientu?

Nie. Wsteczna propagacja oblicza gradient funkcji straty względem każdego wagi, w jednym przejściu wstecznym kosztującym około tyle, ile jeden przejazd do przodu. Z kolei zejście gradientu (lub SGD, Adam, momentum) to osobny krok wykorzystujący te gradienty do aktualizacji wag. Można sparować wsteczną propagację z dowolnym optymalizatorem.

Co to jest problem zanikającego gradientu?

Przejście wsteczne mnoży sygnał błędu przez pochodną aktywacji na każdym warstwie. Pochodna funkcji sigmoid nigdy nie przekracza 0,25 i zbliża się do zera, gdy jednostka saturuje, więc przez wiele warstw iloczyn skurcza się do zera, a wczesne warstwy przestają uczyć się. ReLU unika tego problemu, ponieważ jego pochodna wynosi dokładnie 1 dla dodatnich wartości.

Dlaczego nie mogę zainicjalizować wszystkich wag zerami?

Ponieważ wtedy każda neuron w warstwie oblicza ten sam wynik i otrzymuje ten sam gradient, więc pozostają one identyczne na zawsze – warstwa nigdy nie łamie symetrii i zasadniczo zawiera jedną jednostkę. Wagi muszą być losowe i przeskalowane (Xavier dla tanh, He dla ReLU), aby wariancja sygnału nie eksplodowała ani nie uległa kolapsowi na kolejnych warstwach.

Wypróbuj na żywo

Wszystko powyżej działa bezpośrednio w Twojej przeglądarce — otwórz Neural Network — Backpropagation i zmieniaj parametry podczas działania. Nic nie jest instalowane ani przesyłane na serwer, cały model działa w jednej karcie.

▶ Otwórz symulację Neural Network — Backpropagation

Co znalazłeś?

Dodaj kroki odtworzenia (opcjonalnie)