01 · Podstawy · 4 min czytania · Interaktywne · aktualizacja
Na czym polega reguła łańcuchowa i dlaczego jest sercem propagacji wstecznej?
W skrócie
Reguła łańcuchowa mówi, że pochodna funkcji złożonej to iloczyn pochodnych jej ogniw. Dzięki niej sieć wie, jak każda waga wpływa na błąd na końcu.
Co to jest
Reguła łańcuchowa to przepis na pochodną funkcji złożonej. Jeśli y zależy od u, a u zależy od x, to dy/dx = (dy/du) · (du/dx): tempo zmian na całej drodze to iloczyn temp zmian na kolejnych odcinkach. Dla dłuższego łańcucha mnoży się więcej czynników.
Intuicja: w przekładni zębatej pierwsze koło obraca się 3 razy szybciej niż korba, a drugie 2 razy szybciej niż pierwsze. Drugie koło kręci się więc 6 razy szybciej niż korba. Przełożenia się mnożą — i tak samo mnożą się pochodne.
Sieć neuronowa jest właśnie długim łańcuchem: wejście → mnożenie przez wagi → aktywacja → kolejna warstwa → … → predykcja → strata. Żeby poprawić wagę w pierwszej warstwie, trzeba wiedzieć, jak jej zmiana „przecieka” przez wszystkie następne ogniwa aż do błędu. Reguła łańcuchowa daje tę odpowiedź, a propagacja wsteczna to sprytny sposób, żeby policzyć ją dla milionów wag naraz.
Mechanizm — dlaczego tak działa
Dlaczego pochodne się mnożą? Z bliska każda gładka funkcja wygląda jak prosta. Jeśli x zmieni się o małe Δx, to u zmieni się o około u′ · Δx. Ta zmiana u jest z kolei małym zaburzeniem wejścia funkcji y, więc y zmieni się o około y′ · (u′ · Δx). Złożenie dwóch przybliżeń liniowych to przybliżenie liniowe o nachyleniu równym iloczynowi nachyleń. Nic więcej się tu nie dzieje.
Gdy zmienna wpływa na wynik kilkoma drogami naraz, wkłady z różnych dróg się sumują: pochodna to suma iloczynów wzdłuż wszystkich ścieżek. To dlatego waga w środku sieci, połączona z wieloma neuronami następnej warstwy, zbiera gradient ze wszystkich z nich.
Propagacja wsteczna wykorzystuje strukturę łańcucha. Zamiast liczyć każdą pochodną od zera, idzie od końca: najpierw pochodna straty względem predykcji, potem mnoży ją przez pochodną predykcji względem ostatniej warstwy, i tak dalej w stronę wejścia. Każdy pośredni iloczyn jest używany wielokrotnie, więc koszt policzenia gradientu względem wszystkich wag jest tego samego rzędu co koszt jednego przejścia w przód. Bez tego trening dużych sieci byłby niewykonalny.
Iloczyn wielu czynników ma też ciemną stronę. Jeśli każde ogniwo ma pochodną mniejszą od 1 — sigmoid ma pochodną co najwyżej 0,25 — to po kilkudziesięciu warstwach iloczyn spada praktycznie do zera i pierwsze warstwy przestają się uczyć (zanikający gradient). Jeśli czynniki są większe od 1, iloczyn eksploduje. Funkcja ReLU, staranna inicjalizacja wag, normalizacja i połączenia rezydualne to w dużej mierze sposoby na utrzymanie tych iloczynów w okolicy jedynki.
Warto zauważyć jeszcze jedną rzecz: w wielu wymiarach „pochodna” każdego ogniwa jest macierzą (jakobianem), a reguła łańcuchowa to mnożenie macierzy. Idea pozostaje ta sama.
Na przykładzie
Zbiór Breast Cancer Wisconsin ma 569 guzów, z czego 212 (37,3%) to zmiany złośliwe. Weźmy jedną cechę — średni promień, wystandaryzowany do x — i model logistyczny: z = w · x + b, p = σ(z), strata L = −[y log p + (1 − y) log(1 − p)]. Pierwszy guz ma promień 17,99 (średnia w zbiorze 14,13, odchylenie 3,52), czyli x = 1,097, i jest złośliwy (y = 1). Przy w = 1 i b = 0 dostajemy z = 1,097, p = 0,750 i stratę 0,288.
Łańcuch ma trzy ogniwa: dL/dp = −1,334, dp/dz = p(1 − p) = 0,188 oraz dz/dw = x = 1,097. Iloczyn wynosi −0,275 i dokładnie zgadza się ze skróconym wzorem (p − y) · x, który wychodzi po uproszczeniu. Uśredniony po wszystkich 569 guzach gradient to −0,152 — identycznie jak przy różniczkowaniu numerycznym. Ujemny znak mówi: zwiększ w. Model dopasowany do końca ma w ≈ 3,64 i b ≈ −0,64, a średnia strata spada z 0,451 do 0,290.
Dane: Breast Cancer Wisconsin (diagnostyka raka piersi)
W praktyce
- W PyTorch nie piszesz reguły łańcuchowej ręcznie: każda operacja na tensorze z
requires_grad=Truezapisuje się w grafie, aloss.backward()przechodzi go od końca, mnożąc lokalne pochodne. - Własną operację z ręcznie podaną pochodną definiuje się przez
torch.autograd.Function(metodyforwardibackward); sprawdź jątorch.autograd.gradcheck. - Normy gradientów kolejnych warstw (
p.grad.norm()) pokazują, czy łańcuch nie zanika lub nie eksploduje; przy eksplozji pomagatorch.nn.utils.clip_grad_norm_. - Funkcja straty łącząca sigmoid lub softmax z entropią krzyżową (
BCEWithLogitsLoss,CrossEntropyLoss) jest stabilniejsza niż osobne ogniwa, bo uproszczony gradient p − y nie przechodzi przez logarytmy bliskich zeru liczb. - Operacje nieróżniczkowalne (zaokrąglenie,
argmax, indeksowanie wynikiem porównania) przerywają łańcuch — gradient przed nimi wynosi zero.
Najczęstsze pytania
- Czy propagacja wsteczna to po prostu reguła łańcuchowa?
- Matematycznie tak. Propagacja wsteczna to reguła łańcuchowa zastosowana w określonej kolejności (od wyjścia do wejścia) z zapamiętywaniem wyników pośrednich, co sprawia, że koszt gradientu jest porównywalny z kosztem predykcji.
- Dlaczego gradient sigmoidu w połączeniu z entropią krzyżową jest taki prosty?
- Bo pochodna logarytmu (1/p) skraca się z pochodną sigmoidu (p(1 − p)). Zostaje p − y: różnica między przewidywanym prawdopodobieństwem a prawdą, pomnożona przez wejście.
- Skąd biorą się zanikające gradienty?
- Z mnożenia wielu czynników mniejszych od 1 wzdłuż długiego łańcucha warstw. Każda warstwa z nasyconą aktywacją dokłada mały mnożnik, a ich iloczyn maleje wykładniczo z głębokością.
Źródła
- Rumelhart, Hinton, Williams, 1986, „Learning representations by back-propagating errors”, Nature 323, 533–536.
- Goodfellow, Bengio, Courville „Deep Learning”, MIT Press, 2016, rozdz. 6.5 (Back-Propagation and Other Differentiation Algorithms).
- Baydin, Pearlmutter, Radul, Siskind, 2018, „Automatic differentiation in machine learning: a survey”, Journal of Machine Learning Research 18(153), 1–43.
- Deisenroth, Faisal, Ong „Mathematics for Machine Learning”, Cambridge University Press, 2020, rozdz. 5.
- Dokumentacja PyTorch: Autograd mechanics, https://pytorch.org/docs/stable/notes/autograd.html