Vektinitialisering: Xavier- og He-initialisering
Deltakere vil bruke Xavier-uniform- og He-normal-initialisering, og observere hvordan de forhindrer forsvinnende og eksploderende gradienter i dype nettverk sammenlignet med standard tilfeldig initialisering.
Vektinitialisering: Xavier- og He-initialisering er en gratis leksjon i Machine Learning Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Machine Learning Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Machine Learning Academy inneholder totalt 4 leksjoner.
Hvorfor initialisering er viktig
Vektene i et nevralt nettverk må initialiseres til verdier som ikke er null før trening — men valget av hvordan de initialiseres, påvirker treningsdynamikken i stor grad. Dårlig initialisering fører til forsvinnende gradienter (vektene krymper mot null, og gradientene blir ubetydelige) eller eksploderende gradienter (vektene vokser uten grenser, og gradientene blir NaN). God initialisering holder aktiveringer og gradienter innenfor et sunt område fra og med den første batchen, noe som muliggjør stabil og rask trening.
import torch
import torch.nn as nn
# All-zeros init: disaster! All neurons compute the same
# gradient (symmetry breaking fails)
model_bad = nn.Linear(4, 4)
nn.init.zeros_(model_bad.weight)
print('All-zero gradients:', model_bad.weight.grad)
# Constant init: same problem
# Random init from N(0,1): works for shallow, fails deep
# Xavier / He: designed for deep networksProblemet med symmetribrudd
Hvis alle vekter initialiseres til samme verdi (inkludert null), beregner alle nevronene i et lag nøyaktig samme utdata og mottar nøyaktig samme gradient. Alle nevronene lærer den samme egenskapen — det skjulte laget reduseres i praksis til ett enkelt nevron. Dette symmetriproblemet er grunnen til at tilfeldig initialisering er nødvendig: hvert nevron må starte med en annen tilfeldig vekt for å bryte symmetrien og lære ulike representasjoner.
import torch
import torch.nn as nn
# Demonstrate symmetry breaking failure
model = nn.Linear(3, 4, bias=False)
nn.init.constant_(model.weight, 0.1) # all same
x = torch.randn(5, 3)
y = model(x)
# All 4 neurons produce identical outputs!
print('All neurons identical:', torch.allclose(y[:, 0], y[:, 1]))
# True -- the 4 output neurons are indistinguishableNaiv normalinitialisering og hvorfor den mislykkes
Det virker rimelig å initialisere vekter fra en standard normalfordeling N(0, 1), men dette skaper problemer i dype nettverk. For et lag med fan-in (antall inngangstilkoblinger) lik 1000 vil den vektede summen av 1000 normalfordelte verdier ha varians 1000 — noe som fører til eksploderende aktiveringer i dype nettverk. Omvendt fører svært små tilfeldige verdier (for eksempel N(0, 0.001)) til forsvinnende aktiveringer. Ingen av ytterpunktene lar gradientene flyte gjennom mange lag.
import torch
import torch.nn as nn
# Track activation variance through 10 deep layers
def test_deep_init(std):
x = torch.randn(1, 256)
for i in range(10):
W = torch.randn(256, 256) * std
x = torch.tanh(x @ W)
return x.std().item()
print(f'std=1.0: activation_std={test_deep_init(1.0):.6f}')
# Huge -> saturation
print(f'std=0.01: activation_std={test_deep_init(0.01):.6f}')
# Near zero -> vanishingXavier-Glorot-initialisering
Xavier-initialisering (Glorot og Bengio, 2010) ble utviklet for nettverk som bruker tanh- eller sigmoid-aktiveringer. Innsikten er å velge vekter slik at variansen til aktiveringene og gradientene holder seg omtrent konstant gjennom lagene. Vektene trekkes fra en uniform eller normalfordeling med varians 2 / (fan_in + fan_out). Dette er standardinitialiseringen for nn.Linear (uniform variant) i PyTorch.
import torch
import torch.nn as nn
layer = nn.Linear(256, 128)
# Xavier uniform: default for nn.Linear
nn.init.xavier_uniform_(layer.weight)
print('Xavier uniform std:', layer.weight.std().item())
# Approximately sqrt(2 / (256 + 128)) = 0.081
# Xavier normal: Gaussian version
nn.init.xavier_normal_(layer.weight)
print('Xavier normal std:', layer.weight.std().item())He-initialisering (Kaiming) for ReLU
He-initialisering (He et al., 2015) ble utviklet spesielt for nettverk som bruker ReLU-aktiveringer. Siden ReLU setter halvparten av inngangsverdiene (de negative) til null, halveres den effektive variansen etter aktiveringen. He-initialisering kompenserer for dette ved å bruke variansen 2 / fan_in — dobbelt så stor som den Xavier bruker. Bruk av Xavier med ReLU fører til at gradientene forsvinner i dype nettverk, mens He-initialisering gjør det mulig å trene nettverk med over 100 lag.
import torch
import torch.nn as nn
layer = nn.Linear(512, 256)
# He (Kaiming) uniform: designed for ReLU
nn.init.kaiming_uniform_(layer.weight,
nonlinearity='relu')
print('Kaiming uniform std:', layer.weight.std().item())
# Approximately sqrt(2/512) * sqrt(3) = 0.108
# He (Kaiming) normal: Gaussian variant
nn.init.kaiming_normal_(layer.weight,
nonlinearity='relu')
print('Kaiming normal std:', layer.weight.std().item())Sammenligning av initialiseringsmetoder i et dypt nettverk
Effekten av initialisering blir synlig når du følger med på aktiveringsstatistikk gjennom lagene i et dypt nettverk. Med Xavier-initialisering og tanh holder aktiveringsvariansen seg nær 1 gjennom alle lagene. Med He-initialisering og ReLU gjelder det samme for ReLU-nettverk. Feil kombinasjon (Xavier + ReLU eller He + sigmoid) fører til systematisk kollaps eller eksplosjon av aktiveringene, noe som bekrefter at valget av initialisering må passe med aktiveringsfunksjonen.
import torch
import torch.nn as nn
def track_activation_std(init_fn, activation, n_layers=10):
x = torch.randn(64, 256)
stds = []
for _ in range(n_layers):
W = torch.empty(256, 256)
init_fn(W)
x = activation(x @ W.T)
stds.append(x.std().item())
return stds
xavier = lambda W: nn.init.xavier_uniform_(W)
he = lambda W: nn.init.kaiming_uniform_(W, nonlinearity='relu')
xavier_stds = track_activation_std(xavier, torch.tanh)
he_stds = track_activation_std(he, torch.relu)
print('Xavier+tanh layer stds:', [f'{s:.2f}' for s in xavier_stds])
print('He+ReLU layer stds:', [f'{s:.2f}' for s in he_stds])Bruk av egendefinert initialisering på en hel modell
Du kan bruke en egendefinert initialisering på en hel modell med model.apply(init_fn), som går gjennom hver modul rekursivt. Funksjonen mottar hver modul og kan bruke ulike initialiseringer basert på lagtypen. Et vanlig mønster er å bruke He-initialisering på Linear- og Conv2d-lag, Xavier-initialisering på embedding-lag og sette biasverdier til null. Dette ene kallet erstatter PyTorchs standardinnstillinger i hele nettverket.
import torch.nn as nn
def init_weights(module):
if isinstance(module, nn.Linear):
nn.init.kaiming_normal_(module.weight,
nonlinearity='relu')
if module.bias is not None:
nn.init.zeros_(module.bias)
elif isinstance(module, nn.Conv2d):
nn.init.kaiming_normal_(module.weight,
nonlinearity='relu')
model = nn.Sequential(
nn.Linear(64, 128), nn.ReLU(),
nn.Linear(128, 64), nn.ReLU(),
nn.Linear(64, 10)
)
model.apply(init_weights)
print('Custom He init applied to all layers')Ortogonal initialisering for RNN-er
Ortogonal initialisering setter vektmatriser til å være ortogonale (Q fra QR-dekomponering), noe som bevarer gradientnormene under tilbakepropagering gjennom tid. Dette er spesielt nyttig for rekurrente nettverk, der den samme vektmatrisen multipliseres gjentatte ganger (én gang per tidssteg). Ortogonale vekter forhindrer at gradientene eksploderer eller forsvinner når de propageres bakover gjennom mange tidssteg i lange sekvenser.
import torch
import torch.nn as nn
# Orthogonal init: columns are orthonormal
layer = nn.Linear(64, 64)
nn.init.orthogonal_(layer.weight)
# Verify: W @ W.T should be identity (approx)
I_approx = layer.weight @ layer.weight.T
print('Close to identity:', torch.allclose(
I_approx,
torch.eye(64),
atol=1e-5
))
# True -- orthogonal matrices preserve vector normsPyTorchs standardinitialiseringer
PyTorch bruker fornuftige standardinnstillinger automatisk: nn.Linear bruker Kaiming uniform for vekter og uniform fordeling for biasverdier. nn.Conv2d bruker også Kaiming uniform. nn.Embedding bruker standard normalfordeling N(0, 1). nn.LSTM bruker uniform fordeling i [-1/sqrt(hidden), 1/sqrt(hidden)]. I mange tilfeller fungerer standardinnstillingene godt, men for svært dype nettverk eller ikke-standardiserte aktiveringsfunksjoner gir eksplisitt initialisering med formlene ovenfor bedre resultater.
import torch.nn as nn
# Check PyTorch defaults
linear = nn.Linear(256, 128)
print('Linear weight std:', linear.weight.std().item())
# ~0.088 = Kaiming uniform for fan_in=256
conv = nn.Conv2d(3, 64, kernel_size=3)
print('Conv2d weight std:', conv.weight.std().item())
# Kaiming uniform based on receptive field size
emb = nn.Embedding(1000, 128)
print('Embedding weight std:', emb.weight.std().item())
# ~1.0 = N(0, 1) defaultPraktisk veiledning for initialisering
En praktisk veiledning for valg av initialisering: bruk He (Kaiming) normal eller uniform for nettverk som bruker ReLU eller varianter av ReLU (LeakyReLU, ELU, GELU). Bruk Xavier normal eller uniform for tanh- eller sigmoid-aktiveringer. Bruk ortogonal initialisering for rekurrente vekter. Sett biasverdier til null i alle tilfeller. For transformere med GELU er N(0, 0.02) den empiriske standarden som brukes i GPT-2 og etterfølgende modeller. Stol på PyTorchs standardinnstillinger for standardarkitekturer, og overstyr dem bare når treningen er ustabil.
# Quick reference table
init_guide = {
'ReLU (Linear, Conv)': 'kaiming_normal_ / kaiming_uniform_',
'Tanh / Sigmoid': 'xavier_normal_ / xavier_uniform_',
'RNN hidden matrix': 'orthogonal_',
'Transformer (GELU)': 'normal_(mean=0, std=0.02)',
'Embedding': 'normal_(mean=0, std=1)',
'Biases': 'zeros_()'
}
for activation, method in init_guide.items():
print(f'{activation}: {method}')Kontroll av initialiseringskvalitet
Etter at du har brukt initialisering, bør du kontrollere den ved å sjekke aktiveringsstatistikken i den første fremoverpasseringen. Et sunt nettverk bør ha aktiveringsstandardavvik nær 1,0 i alle lag og gradientnormer av tilsvarende størrelse gjennom lagene. Store avvik (for eksempel std=10 i ett lag og std=0.001 i et annet) tyder på at initialiseringen ikke passer. Denne raske kontrollen tar sekunder og kan spare deg for timevis med feilsøking av dårlig treningsdynamikk.
import torch
import torch.nn as nn
model = nn.Sequential(
nn.Linear(64, 256), nn.ReLU(),
nn.Linear(256, 256), nn.ReLU(),
nn.Linear(256, 64), nn.ReLU(),
nn.Linear(64, 10)
)
model.apply(lambda m: nn.init.kaiming_normal_(m.weight)
if isinstance(m, nn.Linear) else None)
# Check activation std through the network
x = torch.randn(32, 64)
hooks = []
stds = []
for layer in model:
x = layer(x)
if hasattr(x, 'std'):
stds.append(x.std().item())
print('Activation stds:', [f'{s:.2f}' for s in stds])Hurtigsjekk
Test forståelsen din av konsepter innen maskinlæring med Python fra denne leksjonen.
Oppsummering av leksjonen
I denne leksjonen har du lært: Xavier-initialisering er utviklet for tanh-/sigmoid-aktiveringer og bruker variansen 2/(fan_in + fan_out), He-initialisering (Kaiming) er utviklet for ReLU og bruker variansen 2/fan_in for å kompensere for at ReLU setter halvparten av inngangsverdiene til null, og model.apply(init_fn) bruker en egendefinert initialisering på hvert lag i nettverket. Neste gang går vi i dybden på konvolusjonelle nevrale nettverk, med konvolusjons- og filteroperasjoner som utgangspunkt.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Vektinitialisering: Xavier- og He-initialisering» gratis?
Ja – hele teksten i «Vektinitialisering: Xavier- og He-initialisering» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Machine Learning Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Machine Learning Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Vektinitialisering: Xavier- og He-initialisering»?
Deltakere vil bruke Xavier-uniform- og He-normal-initialisering, og observere hvordan de forhindrer forsvinnende og eksploderende gradienter i dype nettverk sammenlignet med standard tilfeldig initia… Du øver på Machine Learning Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Machine Learning Academy?
Ingen tidligere erfaring er nødvendig. Machine Learning Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Vektinitialisering: Xavier- og He-initialisering»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Machine Learning Academy-leksjonen?
Ja. Alle Machine Learning Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Læringsrate: Den viktigste hyperparameteren
- Batch-normalisering: Stabilere og raskere trening
- Dropout-regularisering for å forhindre overtilpasning
- Vektinitialisering: Xavier- og He-initialisering