ML Atlas

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).

Ta ilustracja działa w przeglądarce z włączonym JavaScriptem: normy gradientu w każdej warstwie głębokiej sieci tuż po inicjalizacji, na paczce 256 cyfr: przy 20 warstwach sigmoidy z Xavierem stosunek pierwsza/ostatnia warstwa to 2,4·10⁻¹³, a przy ReLU z inicjalizacją He 2,19 — gradient nie zanika.

Dane: Digits (ręcznie pisane cyfry 8×8)

W praktyce

  • PyTorch: nn.Linear domyślnie losuje z rozkładu jednostajnego o skali zależnej od n_in (wariant Kaiminga); jawnie nn.init.xavier_uniform_, nn.init.kaiming_normal_(nonlinearity='relu').
  • Keras: Dense domyślnie glorot_uniform; he_normal dla ReLU.
  • scikit-learn: MLPClassifier stosuje inicjalizację Glorota; random_state kontroluje 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.zeros dla 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

Zobacz też