Residualkopplingar
Kunna förklara varför skip-kopplingar gör djupa nät tränbara.
Förkunskaper
Intuition
Före 2015 gick det inte att träna riktigt djupa nät. Ett 56-lagers nät var sämre än ett 20-lagers — inte på grund av överanpassning, utan för att det inte gick att optimera. Det var ett förbryllande resultat: det djupare nätet kan ju i princip härma det grundare genom att låta de extra lagren göra ingenting.
Problemet var att «göra ingenting» — identitetsavbildningen — är förvånansvärt svårt att lära sig med en stapel viktmatriser.
Residualkopplingens lösning är att bygga in den:
Lagret lär sig skillnaden i stället för hela avbildningen. Ska lagret inte göra något räcker det att , vilket är trivialt: sätt vikterna nära noll.
Resultatet var omedelbart. ResNet från 2015 tränade 152 lager där tidigare nät kvävdes vid 20.
Formellt
Gradientflödet är den matematiska förklaringen. Med :
Genom lager blir gradienten en produkt av sådana termer. Ettan i varje faktor garanterar en väg där gradienten inte skalas ner. Utan residualen är produkten av jakobianer, och är var och en i genomsnitt mindre än 1 dör gradienten exponentiellt med djupet.
En residualstapel kan också ses som en ensemble av grunda vägar: det finns olika sätt att gå genom nätet (ta eller hoppa över varje block), och de flesta effektiva vägarna är korta. Det förklarar varför nätet fungerar även om man tar bort ett helt block — något som slår ut ett vanligt djupt nät fullständigt.
Pre-norm mot post-norm — en detalj som avgör om stora transformerar går att träna alls:
| Variant | Formel | Egenskap |
|---|---|---|
| Post-norm (original) | bättre slutresultat, men behöver uppvärmning och är känslig | |
| Pre-norm | stabil, tränar utan uppvärmning, standard i dag |
Skillnaden: i pre-norm finns en ren, onormaliserad väg från ingång till utgång. I post-norm passerar residualen genom LayerNorm i varje lager, vilket skalar om den och bryter den raka gradientvägen. Vid 50+ lager är skillnaden avgörande, och det är därför i stort sett alla moderna språkmodeller använder pre-norm.
Två praktiska detaljer:
- Dimensionsmatchning. Ändrar blocket antalet kanaler behövs en projektion i genvägen — en 1×1-faltning eller ett linjärt lager.
- Nollinitialisering av sista lagret i blocket gör att blocket startar som exakt identitet. Det stabiliserar början av träningen märkbart och används i många moderna recept.
Kod
import torch, torch.nn as nn
class ResidualBlock(nn.Module):
def __init__(self, kanaler):
super().__init__()
self.f = nn.Sequential(
nn.Conv2d(kanaler, kanaler, 3, padding=1, bias=False),
nn.BatchNorm2d(kanaler), nn.ReLU(),
nn.Conv2d(kanaler, kanaler, 3, padding=1, bias=False),
nn.BatchNorm2d(kanaler),
)
nn.init.zeros_(self.f[-1].weight) # blocket börjar som exakt identitet
def forward(self, x):
return torch.relu(x + self.f(x))
# Pre-norm-blocket i en transformer
class PreNormBlock(nn.Module):
def __init__(self, d, huvuden):
super().__init__()
self.n1, self.n2 = nn.LayerNorm(d), nn.LayerNorm(d)
self.attn = nn.MultiheadAttention(d, huvuden, batch_first=True)
self.mlp = nn.Sequential(nn.Linear(d, 4 * d), nn.GELU(), nn.Linear(4 * d, d))
def forward(self, x):
x = x + self.attn(self.n1(x), self.n1(x), self.n1(x), need_weights=False)[0]
return x + self.mlp(self.n2(x)) # ren väg genom x, oförändrad av LN
# Mät gradientflödet: med och utan residual
def gradient_i_forsta_lagret(med_residual, djup=40, d=64):
lager = nn.ModuleList([nn.Sequential(nn.Linear(d, d), nn.Tanh()) for _ in range(djup)])
x = torch.randn(8, d, requires_grad=True)
h = x
for lg in lager:
h = h + lg(h) if med_residual else lg(h)
h.sum().backward()
return float(x.grad.norm())
torch.manual_seed(0)
print(f"utan residual: {gradient_i_forsta_lagret(False):.3e}")
print(f"med residual: {gradient_i_forsta_lagret(True):.3e}")
# utan residual: 1.4e-06 ← gradienten har praktiskt taget dött på vägen
# med residual: 2.6e+01 ← kommer fram
Skillnaden i sista utskriften är sju tiopotenser genom fyrtio lager. Det är exakt det som gjorde djupa nät möjliga, och nn.init.zeros_ på blockets sista lager är en rad som stabiliserar träningens första hundra steg gratis.
Behärskning innebär
- Förklarar hur en residualkoppling påverkar gradientflödet
- Vet skillnaden mellan pre-norm och post-norm
- Känner till varför identitetsavbildningen är lätt att lära
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — Deep Residual Learning for Image Recognition — arXiv (öppen åtkomst; licens per artikel)
- arXiv — On Layer Normalization in the Transformer Architecture — arXiv (öppen åtkomst; licens per artikel)
- Dive into Deep Learning (CC BY-SA 4.0) — CC BY-SA 4.0