Inizializzazione dei pesi: inizializzazione Xavier e He
Imparerete ad applicare l’inizializzazione uniforme di Xavier e quella normale di He, osservando come prevengano la scomparsa o l’esplosione dei gradienti nelle reti profonde rispetto all’inizializzazione casuale predefinita.
Inizializzazione dei pesi: inizializzazione Xavier e He è una lezione Machine Learning Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Machine Learning Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Machine Learning Academy include 4 lezioni in totale.
Perché l'inizializzazione è importante
I pesi di una rete neurale devono essere inizializzati a valori diversi da zero prima dell'addestramento, ma la scelta di come inizializzarli influisce profondamente sulla dinamica dell'addestramento. Un'inizializzazione inadeguata causa la scomparsa dei gradienti (i pesi si riducono quasi a zero e i gradienti diventano trascurabili) oppure l'esplosione dei gradienti (i pesi crescono senza limiti e i gradienti diventano NaN). Una buona inizializzazione mantiene attivazioni e gradienti in un intervallo adeguato fin dal primo batch, consentendo un addestramento stabile e rapido.
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 networksIl problema della rottura della simmetria
Se tutti i pesi sono inizializzati allo stesso valore (compreso zero), ogni neurone di un livello calcola esattamente lo stesso output e riceve esattamente lo stesso gradiente. Tutti i neuroni imparano la stessa caratteristica: a tutti gli effetti, il livello nascosto collassa in un unico neurone. Questo problema di simmetria spiega perché sia necessaria un'inizializzazione casuale: ogni neurone deve iniziare con un peso casuale diverso per rompere la simmetria e imparare rappresentazioni differenti.
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 indistinguishableInizializzazione normale ingenua e relativi problemi
Inizializzare i pesi con una distribuzione normale standard N(0, 1) può sembrare ragionevole, ma nelle reti profonde causa problemi. Per un livello con fan-in (numero di connessioni in ingresso) pari a 1000, la somma pesata di 1000 valori distribuiti normalmente ha varianza 1000, causando l'esplosione delle attivazioni nelle reti profonde. Al contrario, valori casuali molto piccoli (ad esempio N(0, 0.001)) causano la scomparsa delle attivazioni. Nessuno dei due estremi consente ai gradienti di propagarsi attraverso molti livelli.
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 -> vanishingInizializzazione Xavier Glorot
L'inizializzazione Xavier (Glorot e Bengio, 2010) è stata progettata per le reti che utilizzano attivazioni tanh o sigmoid. L'idea è scegliere i pesi in modo che la varianza delle attivazioni e dei gradienti rimanga approssimativamente costante tra i livelli. I pesi vengono estratti da una distribuzione uniforme o normale con varianza 2 / (fan_in + fan_out). Questa è l'inizializzazione predefinita di nn.Linear (variante uniforme) in 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())Inizializzazione He (Kaiming) per ReLU
L'inizializzazione He (He et al., 2015) è stata progettata specificamente per le reti che utilizzano attivazioni ReLU. Poiché ReLU azzera metà dei suoi ingressi (quelli negativi), la varianza effettiva dopo l'attivazione si dimezza. L'inizializzazione He compensa questo effetto usando la varianza 2 / fan_in, il doppio di quella usata da Xavier. Usare Xavier con ReLU causa la scomparsa dei gradienti nelle reti profonde; usare l'inizializzazione He consente di addestrare reti con oltre 100 livelli.
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())Confronto tra metodi di inizializzazione su una rete profonda
L'effetto dell'inizializzazione diventa visibile quando si monitorano le statistiche delle attivazioni attraverso i livelli di una rete profonda. Con l'inizializzazione Xavier e tanh, la varianza delle attivazioni rimane vicina a 1 in tutti i livelli. Con l'inizializzazione He e ReLU accade lo stesso nelle reti ReLU. Usare la combinazione sbagliata (Xavier + ReLU oppure He + sigmoid) porta al collasso o all'esplosione sistematica delle attivazioni, confermando che la scelta dell'inizializzazione deve essere compatibile con la funzione di attivazione.
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])Applicare un'inizializzazione personalizzata a un modello completo
Può applicare un'inizializzazione personalizzata a un modello intero usando model.apply(init_fn), che visita ricorsivamente ogni modulo. La funzione riceve ciascun modulo e può applicare inizializzazioni diverse in base al tipo di livello. Un approccio comune consiste nell'applicare l'inizializzazione He ai livelli Linear e Conv2d, l'inizializzazione Xavier ai livelli di embedding e nell'impostare i bias a zero. Questa singola chiamata sostituisce i valori predefiniti di PyTorch nell'intera rete.
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')Inizializzazione ortogonale per le RNN
L'inizializzazione ortogonale imposta le matrici dei pesi come matrici ortogonali (Q ottenuta dalla decomposizione QR), preservando le norme dei gradienti durante la retropropagazione nel tempo. È particolarmente utile per le reti ricorrenti, nelle quali la stessa matrice dei pesi viene moltiplicata ripetutamente (una volta per ogni passo temporale). I pesi ortogonali impediscono ai gradienti di esplodere o scomparire mentre vengono propagati all'indietro attraverso molti passi temporali nelle sequenze lunghe.
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 normsInizializzazioni predefinite di PyTorch
PyTorch applica automaticamente valori predefiniti appropriati: nn.Linear usa l'inizializzazione uniforme di Kaiming per i pesi e una distribuzione uniforme per i bias. Anche nn.Conv2d usa l'inizializzazione uniforme di Kaiming. nn.Embedding usa la distribuzione normale standard N(0, 1). nn.LSTM usa una distribuzione uniforme in [-1/sqrt(hidden), 1/sqrt(hidden)]. In molti casi i valori predefiniti funzionano bene, ma per le reti molto profonde o per le funzioni di attivazione non standard, un'inizializzazione esplicita con le formule precedenti produce risultati migliori.
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) defaultGuida pratica all'inizializzazione
Una guida pratica alla scelta dell'inizializzazione: usi l'inizializzazione normale o uniforme di He (Kaiming) per qualsiasi rete che utilizzi ReLU o le sue varianti (LeakyReLU, ELU, GELU). Usi l'inizializzazione normale o uniforme di Xavier per le attivazioni tanh o sigmoid. Usi l'inizializzazione ortogonale per i pesi ricorrenti. Imposti i bias a zero in tutti i casi. Per i Transformer con GELU, N(0, 0.02) è lo standard empirico utilizzato in GPT-2 e nei modelli successivi. Si affidi ai valori predefiniti di PyTorch per le architetture standard e li sostituisca solo quando l'addestramento è instabile.
# 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}')Verificare la qualità dell'inizializzazione
Dopo aver applicato l'inizializzazione, la verifichi controllando le statistiche delle attivazioni nel primo forward pass. Una rete in buone condizioni dovrebbe avere deviazioni standard delle attivazioni vicine a 1,0 in tutti i livelli e norme dei gradienti di entità simile tra i livelli. Grandi discrepanze (ad esempio std=10 in un livello e std=0.001 in un altro) indicano un'inizializzazione non adatta. Questo rapido controllo di integrità richiede pochi secondi e può farle risparmiare ore di debug dei problemi nella dinamica dell'addestramento.
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])Verifica rapida
Verifichi la sua comprensione dei concetti di Machine Learning con Python trattati in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che: l'inizializzazione Xavier è progettata per le attivazioni tanh/sigmoid e usa la varianza 2/(fan_in + fan_out), l'inizializzazione He (Kaiming) è progettata per ReLU e usa la varianza 2/fan_in per compensare il fatto che ReLU azzera metà dei suoi ingressi, e model.apply(init_fn) applica un'inizializzazione personalizzata a ogni livello della rete. Ora passeremo alle reti neurali convoluzionali, iniziando dalle operazioni di convoluzione e filtraggio.
Impara Python con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 30
- Lezioni
- 120
Domande Frequenti
La lezione «Inizializzazione dei pesi: inizializzazione Xavier e He» è gratuita?
Sì — il testo completo di «Inizializzazione dei pesi: inizializzazione Xavier e He» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Machine Learning Academy, passa a CoddyKit PRO. Il corso Machine Learning Academy include 4 lezioni in totale.
Cosa imparerò in «Inizializzazione dei pesi: inizializzazione Xavier e He»?
Imparerete ad applicare l’inizializzazione uniforme di Xavier e quella normale di He, osservando come prevengano la scomparsa o l’esplosione dei gradienti nelle reti profonde rispetto all’inizializza… Eserciti Machine Learning Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Machine Learning Academy?
Non è richiesta alcuna esperienza precedente. Machine Learning Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Inizializzazione dei pesi: inizializzazione Xavier e He»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Machine Learning Academy?
Sì. Ogni lezione Machine Learning Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Learning rate: l’iperparametro più importante
- Batch normalization: addestramento stabile e più rapido
- Regolarizzazione con dropout per prevenire l’overfitting
- Inizializzazione dei pesi: inizializzazione Xavier e He