Machine Learning Academy · Oppitunti

Painojen alustus: Xavier- ja He-alustus

Oppijat käyttävät Xavier-uniform- ja He-normal-alustusta sekä havaitsevat, miten ne estävät gradienttien katoamista ja räjähtämistä syvissä verkoissa oletusarvoiseen satunnaisalustukseen verrattuna.

Oppitunti 4/413 vaihetta

Painojen alustus: Xavier- ja He-alustus on ilmainen Machine Learning Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Machine Learning Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Miksi alustuksella on merkitystä

Neuroverkon painot on alustettava nollasta poikkeavilla arvoilla ennen koulutusta, mutta niiden alustustavan valinta vaikuttaa merkittävästi koulutuksen dynamiikkaan. Huono alustus aiheuttaa häviäviä gradientteja (painot kutistuvat lähes nollaan ja gradienteista tulee merkityksettömiä) tai räjähtäviä gradientteja (painot kasvavat rajoittamattomasti ja gradienteista tulee NaN-arvoja). Hyvä alustus pitää aktivaatiot ja gradientit sopivalla alueella heti ensimmäisestä erästä lähtien, mikä mahdollistaa vakaan ja nopean koulutuksen.

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 networks

Symmetrian rikkomisen ongelma

Jos kaikki painot alustetaan samaan arvoon (myös nollaan), kaikki kerroksen neuronit laskevat täsmälleen saman tuloksen ja saavat täsmälleen saman gradientin. Kaikki neuronit oppivat saman piirteen, joten piilokerros supistuu käytännössä yhdeksi neuroniksi. Tämä symmetriaongelma on syy siihen, miksi satunnaista alustusta tarvitaan: jokaisen neuronin on aloitettava eri satunnaisella painolla, jotta symmetria rikkoutuu ja neuronit voivat oppia erilaisia esityksiä.

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 indistinguishable

Naivi normaalijakauma-alustus ja sen epäonnistuminen

Painojen alustaminen standardinormaalijakaumasta N(0, 1) vaikuttaa järkevältä, mutta aiheuttaa ongelmia syvissä verkoissa. Kun kerroksen fan-in-arvo (syöteyhteyksien määrä) on 1000, tuhannen normaalijakautuneen arvon painotetun summan varianssi on 1000, mikä aiheuttaa räjähtäviä aktivaatioita syvissä verkoissa. Toisaalta hyvin pienet satunnaisarvot (esim. N(0, 0.001)) aiheuttavat häviäviä aktivaatioita. Kumpikaan ääripää ei mahdollista gradienttien kulkemista monen kerroksen läpi.

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 -> vanishing

Xavierin (Glorotin) alustus

Xavier-alustus (Glorot ja Bengio, 2010) suunniteltiin verkoille, joissa käytetään tanh- tai sigmoid-aktivaatioita. Keskeinen ajatus on valita painot niin, että aktivaatioiden ja gradienttien varianssi pysyy suunnilleen vakiona kerroksesta toiseen. Painot poimitaan tasaisesta tai normaalijakaumasta, jonka varianssi on 2 / (fan_in + fan_out). Tämä on PyTorchin nn.Linear-kerroksen oletusalustus (tasainen muunnelma).

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-alustus (Kaiming-alustus) ReLU-aktivaatioille

He-alustus (He ym., 2015) suunniteltiin erityisesti verkoille, joissa käytetään ReLU-aktivaatioita. Koska ReLU nollaa puolet syötteistään (negatiiviset arvot), aktivaation jälkeinen tehokas varianssi puolittuu. He-alustus kompensoi tämän käyttämällä varianssia 2 / fan_in, joka on kaksi kertaa Xavier-alustuksen käyttämä arvo. Xavier-alustuksen käyttäminen ReLU:n kanssa aiheuttaa gradienttien häviämisen syvissä verkoissa, kun taas He-alustus mahdollistaa yli 100-kerroksisten verkkojen kouluttamisen.

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

Alustusmenetelmien vertailu syvässä verkossa

Alustuksen vaikutus tulee näkyviin, kun seuraatte aktivaatioiden tilastotietoja syvän verkon kerroksissa. Kun käytetään Xavier-alustusta ja tanh-aktivaatiota, aktivaatioiden varianssi pysyy lähellä arvoa 1 kaikissa kerroksissa. He-alustuksella ja ReLU-aktivaatiolla tapahtuu sama ReLU-verkoissa. Väärä yhdistelmä (Xavier + ReLU tai He + sigmoid) johtaa aktivaatioiden järjestelmälliseen romahtamiseen tai räjähtämiseen, mikä vahvistaa, että alustustavan on vastattava aktivointifunktiota.

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

Mukautetun alustuksen käyttäminen koko mallissa

Voitte käyttää mukautettua alustusta koko mallissa model.apply(init_fn)-kutsulla, joka käy rekursiivisesti läpi kaikki moduulit. Funktio saa parametrikseen kunkin moduulin ja voi käyttää eri alustuksia kerrostyypin perusteella. Yleinen toimintatapa on käyttää He-alustusta Linear- ja Conv2d-kerroksille, Xavier-alustusta upotuskerroksille ja asettaa biasit nollaan. Tämä yksi kutsu korvaa PyTorchin oletukset koko verkossa.

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

Ortogonaalinen alustus RNN-verkoille

Ortogonaalinen alustus asettaa painomatriisit ortogonaalisiksi (QR-hajotelman Q), mikä säilyttää gradienttien normit ajan yli tapahtuvan takaisinlevityksen aikana. Tämä on erityisen hyödyllistä rekurrenteissa verkoissa, joissa sama painomatriisi kerrotaan toistuvasti (kerran jokaista aika-askelta kohti). Ortogonaaliset painot estävät gradienttien räjähtämisen tai häviämisen, kun niitä levitetään taaksepäin pitkien sekvenssien monien aika-askelten läpi.

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 norms

PyTorchin oletusalustukset

PyTorch käyttää automaattisesti järkeviä oletuksia: nn.Linear käyttää painoille Kaiming-uniform-alustusta ja bias-arvoille tasaista jakaumaa. nn.Conv2d käyttää myös Kaiming-uniform-alustusta. nn.Embedding käyttää standardinormaalijakaumaa N(0, 1). nn.LSTM käyttää tasaista jakaumaa välillä [-1/sqrt(hidden), 1/sqrt(hidden)]. Oletukset toimivat monissa tapauksissa hyvin, mutta erittäin syvissä verkoissa tai epätyypillisiä aktivaatioita käytettäessä edellä esitetyillä kaavoilla tehty eksplisiittinen alustus antaa parempia tuloksia.

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

Käytännön opas alustukseen

Käytännön ohje alustuksen valintaan: käyttäkää He- (Kaiming-) normaalijakaumaa tai tasaista jakaumaa kaikissa verkoissa, joissa käytetään ReLU-aktivaatioita tai niiden muunnelmia (LeakyReLU, ELU, GELU). Käyttäkää Xavierin normaalijakaumaa tai tasaista jakaumaa tanh- tai sigmoid-aktivaatioille. Käyttäkää ortogonaalista alustusta rekurrenteille painoille. Asettakaa biasit nollaan kaikissa tapauksissa. GELU-aktivaatiota käyttävissä Transformereissa N(0, 0.02) on GPT-2:ssa ja sitä seuranneissa malleissa käytetty empiirinen standardi. Luottakaa PyTorchin oletuksiin tavanomaisissa arkkitehtuureissa ja ohittakaa ne vain, jos koulutus on epävakaata.

# 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}')

Alustuksen laadun tarkistaminen

Kun olette tehneet alustuksen, tarkistakaa se tutkimalla aktivaatioiden tilastotietoja ensimmäisellä eteenpäinlaskennalla. Terveessä verkossa aktivaatioiden keskihajonnan tulisi olla lähellä arvoa 1,0 kaikissa kerroksissa ja gradienttinormien tulisi olla samansuuruisia eri kerroksissa. Suuret erot (esim. std=10 yhdessä kerroksessa ja std=0.001 toisessa) viittaavat alustuksen ja aktivointifunktion yhteensopimattomuuteen. Tämä nopea järkevyystarkistus vie vain sekunteja ja voi säästää tuntikausia huonon koulutusdynamiikan selvittämiseltä.

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

Pikatesti

Testatkaa tämän oppitunnin koneoppimista Pythonilla koskevien käsitteiden ymmärtämistänne.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte, että Xavier-alustus on suunniteltu tanh- ja sigmoid-aktivaatioille käyttäen varianssia 2/(fan_in + fan_out), He- (Kaiming-) alustus on suunniteltu ReLU-aktivaatioille käyttäen varianssia 2/fan_in kompensoimaan sitä, että ReLU nollaa puolet syötteistään, ja model.apply(init_fn) käyttää mukautettua alustusta verkon jokaisessa kerroksessa. Seuraavaksi tutustumme konvoluutiohermoverkkoihin aloittaen konvoluutioista ja suodatinoperaatioista.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Painojen alustus: Xavier- ja He-alustus” ilmainen?

Kyllä – oppitunnin ”Painojen alustus: Xavier- ja He-alustus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Machine Learning Academy-kurssin, päivitä CoddyKit PROhon. Machine Learning Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Painojen alustus: Xavier- ja He-alustus”?

Oppijat käyttävät Xavier-uniform- ja He-normal-alustusta sekä havaitsevat, miten ne estävät gradienttien katoamista ja räjähtämistä syvissä verkoissa oletusarvoiseen satunnaisalustukseen verrattuna. Harjoittelet Machine Learning Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Machine Learning Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Machine Learning Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Painojen alustus: Xavier- ja He-alustus”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Machine Learning Academy-oppitunnilla?

Kyllä. Jokainen Machine Learning Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Oppimisnopeus: tärkein hyperparametri
  2. Eränormalisointi: vakaampi ja nopeampi koulutus
  3. Dropout-säännöllistäminen ylisovittamisen estämiseksi
  4. Painojen alustus: Xavier- ja He-alustus
← Takaisin: Machine Learning Academy