06 · Sieci · 4 min czytania · Interaktywne · aktualizacja
Jak inicjalizować wagi sieci neuronowej i dlaczego nie zerami?
W skrócie
Inicjalizacja wag to wybór wartości startowych przed treningiem. Losowy start łamie symetrię neuronów, a skala Xavier lub He trzyma sygnał w rozsądnym zakresie.
Co to jest
Inicjalizacja wag to sposób nadania wagom wartości startowych, zanim zacznie się trening gradientowy. Standardem jest losowanie małych liczb z rozkładu, którego skala zależy od liczby wejść (i wyjść) warstwy: inicjalizacja Xaviera (Glorota) dla sigmoidu i tanh, inicjalizacja He dla ReLU.
Dotyczy sieci neuronowych każdej wielkości, od małego MLP po duże modele językowe. Drzewa decyzyjne tego problemu nie mają, bo nie startują z wag.
Intuicja: zespół, w którym wszyscy dostali identyczne instrukcje i identyczne informacje zwrotne, będzie robił dokładnie to samo — sto osób pracuje jak jedna. Losowy start daje każdemu inny punkt wyjścia, a dobrana skala sprawia, że nikt nie zaczyna ani od szeptu, ani od krzyku.
Mechanizm — dlaczego tak działa
Pierwsze zagrożenie: symetria. Gdy wszystkie wagi warstwy startują równe (np. zero), wszystkie neurony liczą dokładnie to samo wyjście i dostają dokładnie ten sam gradient. Po kroku są nadal równe — zostają klonami na zawsze, a warstwa ze 100 neuronów działa jak jeden. Przy samych zerach jest jeszcze gorzej: gradient wag pierwszej warstwy jest mnożony przez zerowe wagi warstwy następnej, więc w ogóle się nie rusza. Losowy start łamie symetrię: każdy neuron zaczyna w innym miejscu i może nauczyć się innej cechy.
Drugie zagrożenie: skala. Suma ważona neuronu to suma n iloczynów waga × wejście. Jeśli wejścia mają wariancję 1, a wagi wariancję σ², to suma ma wariancję n·σ². Przy σ ustalonym bez względu na n sygnał w szerokiej warstwie rośnie, w wąskiej maleje, a w głębokiej sieci efekt mnoży się przez warstwy — aktywacje i gradienty zanikają albo wybuchają. Glorot i Bengio (2010) zaproponowali wariancję 2/(n_in + n_out), która utrzymuje wariancję sygnału w przód i gradientu wstecz blisko stałej dla aktywacji symetrycznych (tanh, sigmoid w okolicy zera). He i in. (2015) zauważyli, że ReLU zeruje mniej więcej połowę wejść, co o połowę zmniejsza wariancję, i zalecili 2/n_in.
Z dobrą skalą sieć startuje w reżimie, w którym każda warstwa jest w przybliżeniu „przepuszczalna”: ani nasycona, ani martwa. Biasy zwykle inicjalizuje się zerem — dla nich symetria nie jest problemem, bo łamią ją już losowe wagi.
Zastrzeżenie: inicjalizacja jest najważniejsza na starcie; normalizacja warstw (batch norm, layer norm) i połączenia residualne zmniejszają jej wagę w bardzo głębokich sieciach. Różne losowe starty (seedy) dają różne wyniki końcowe — ta wariancja jest realna i warto ją mierzyć.
Na przykładzie
Napisałem w numpy sieć z jedną warstwą ukrytą (32 neurony tanh) i uczyłem ją pełnym spadkiem gradientu na Digits 8×8 (1347 standaryzowanych obrazów treningowych, 450 testowych, random_state=0, 300 kroków). Ze startu z samych zer trafność testowa wynosi 10,2% (zgadywanie), ze startu ze stałej 0,05 — 38,2%, a z losowego startu w skali 1/√n — 97,1%. Po treningu policzyłem, ile różnych neuronów jest w warstwie ukrytej: przy zerach i stałej — jeden, powielony 32 razy; przy losowym starcie — 32.
Skalę widać w sieci z 10 warstwami po 64 neurony, przed treningiem. Przy tanh i wagach o odchyleniu 0,01 odchylenie aktywacji spada z 0,074 w warstwie 1 do 0,000003 w warstwie 5 i 9·10⁻¹² w warstwie 10 — sygnał znika. Przy odchyleniu 1 aktywacje nie znikają, ale 69% z nich w pierwszej warstwie ma |a| > 0,99, czyli neurony są nasycone. Przy ReLU skala Xaviera daje odchylenia 0,56 → 0,13 → 0,024 (sygnał gaśnie), a skala He — 0,79 → 0,70 → 0,77 (stabilnie).
Dane: Digits (ręcznie pisane cyfry 8×8)
W praktyce
- PyTorch:
nn.Lineardomyślnie losuje z rozkładu jednostajnego o skali zależnej od n_in (wariant Kaiminga); jawnienn.init.xavier_uniform_,nn.init.kaiming_normal_(nonlinearity='relu'). - Keras:
Densedomyślnieglorot_uniform;he_normaldla ReLU. - scikit-learn:
MLPClassifierstosuje inicjalizację Glorota;random_statekontroluje seed. - LLM: małe rozkłady normalne (np. odchylenie 0,02 w GPT-2) ze skalowaniem warstw residualnych zależnym od głębokości.
- Typowy błąd:
torch.zerosdla wag „dla powtarzalności” — sieć nie uczy się nic ponad jeden neuron na warstwę. Powtarzalność daje seed, nie zero.
Najczęstsze pytania
- Dlaczego nie można inicjalizować wag zerami?
- Bo wszystkie neurony warstwy liczą wtedy to samo i dostają identyczny gradient, więc na zawsze pozostają kopiami jednego neuronu. Sieć ma pojemność pojedynczego neuronu na warstwę. Biasy mogą być zerowe, wagi muszą być losowe.
- Czym różni się inicjalizacja Xaviera od He?
- Obie dobierają wariancję wag do liczby wejść, by sygnał nie rósł ani nie zanikał. Xavier (2/(n_in + n_out)) zakłada aktywację symetryczną, jak tanh. He (2/n_in) uwzględnia, że ReLU zeruje połowę wejść, więc daje mniej więcej dwukrotnie większą wariancję.
- Czy inicjalizacja ma znaczenie, gdy używam batch norm?
- Mniejsze: normalizacja na bieżąco przywraca sensowną skalę aktywacji, więc sieć wybacza gorszy start. Nadal trzeba złamać symetrię losowaniem, a w bardzo głębokich sieciach bez normalizacji (lub z layer norm w transformerach) skala startowa wciąż wpływa na stabilność pierwszych kroków.
Źródła
- Glorot, X., Bengio, Y. (2010). "Understanding the difficulty of training deep feedforward neural networks". AISTATS, PMLR 9, 249–256.
- He, K., Zhang, X., Ren, S., Sun, J. (2015). "Delving deep into rectifiers: surpassing human-level performance on ImageNet classification". ICCV. arXiv:1502.01852
- Goodfellow, Bengio, Courville (2016). Deep Learning, rozdz. 8.4 "Parameter initialization strategies". https://www.deeplearningbook.org/contents/optimization.html
- Zhang i in. Dive into Deep Learning, rozdz. 5.4 "Numerical stability and initialization". https://d2l.ai/chapter_multilayer-perceptrons/numerical-stability-and-init.html