English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

gäst
1 / ?

Attention plus MLP, upprepat

Transformer Block Pre-Norm Structure


Två underlager

En transformer-block innehåller exakt två underlager, var och ett som arbetar på en token-sekvens med formen [batch, seq_len, d_model]:


1. Multi-head attention-sublager. Tokenerna tittar på varandra. Aktivitet 68 täckte detta i detalj. Utformning av utdata matchar indatans form.

2. Feed-forward MLP-sublager. Varje token transformeras oberoende genom en tvålagrig perceptron. Ingen informationsflöde mellan token. Utformning av utdata matchar indatans form.


Båda sublager bevarar formen [batch, seq_len, d_model]. Denna bevarande tillåter att blocken staplas: lager N:s utdata matar lager N+1:s indata utan formakrobatik.


Vad varje sublager bidrar med

Attention flyttar information över positioner: en token på position 17 kan hämta information från positioner 1 till 16. MLP:n transformerar information inom varje position: en tokens representation omformas genom inlärda icke-linjära funktioner, men ser aldrig sina grannar.


Stapling av block varvar dessa två operationer. Lager 1 attention blandar positioner. Lager 1 MLP omformar per position. Lager 2 attention blandar igen, nu över de omformade representationerna. Denna varvning ökar den uttrycksfulla kraften med djupet.


ANDREAs Stapel


Variantn_layern_headd_modelmlp_dim
ANDREA-12M6123841536
ANDREA-120M12127683072
ANDREA-480M162415366144

Observera mlp_dim = 4 × d_model över hela familjen. Den ratio håller i nästan varje modern transformer. Avsnitt 3 går igenom varför.

Benämna de två underlagren

En transformerblock innehåller två underlager. Namnge dem i ordning, & för varje ett ange om det flyttar information över positioner (token-till-token) eller transformerar information inom en enda position (oberoende per token). En mening per underlager.

Varför hopkopplingar är viktiga

Residualmönstret

Varje sublayer omsluter sin beräkning i en residualkoppling. Utgången lägger till indata igen:


x = x + Attention(LayerNorm(x))     # attention sublayer
x = x + MLP(LayerNorm(x))           # MLP-sublager

Inne i varje sublayer producerar funktionen Attention(...) eller MLP(...) en delta. Blocket ersätter inte indata; det lägger till en inlärd korrigering.


Varför detta är viktigt

Tre skäl till varför residualanslutningar dominerar djupa arkitekturer:


1. Gradientflöde. Under backpropagering ger additionen gradienterna en direkt väg från utgången tillbaka till ingången, och kringgår delskiktet. En 12-lagers stapel utan residualer skulle förlora gradientsignalen långt innan den når inbäddningarna; med residualer förblir gradientens magnitud användbar genom hundratals lager.


2. Identitetsinitialisering. Vid initialisering producerar delskiktets vikter små utdata. Residualanslutningen innebär att lager N initialt passerar igenom nästan oförändrat. Träningen lär sig delta progressivt från en fungerande startpunkt.


3. Kompositionell inlärning. Varje block lär sig en förfining, inte en ersättning. Lager 1 kanske lägger till positionsinformation. Lager 2 kanske lägger till syntaktisk struktur. Lager 7 kanske lägger till semantiska relationer. Residualströmmen ackumuleras.


Lager-normalisering

Före varje delskikt skalar LayerNorm varje tokens representation till noll medelvärde & enhetsvarians, och applicerar sedan inlärd per-funktion gain & bias:


y = gamma * (x - mean(x)) / sqrt(var(x) + epsilon) + beta

Medelvärde & varians beräknas över d_model-dimensionen, separat för varje token. Två inlärda vektorer (gamma, beta, varje form [d_model]) återställer expressiv skala. Normalisering håller aktiveringar i ett numeriskt stabilt intervall; utan den snöbollar små träningsinstabiliteter till NaN-gradienter.

Pre-Norm vs Post-Norm

Ett subtilt men kritiskt val

Två sätt att koppla in layer norm i ett residualt sublager:


Post-norm (originalartikel från 2017):

x = LayerNorm(x + Attention(x))

Layer norm sitter efter den residuala additionen. Den residuala strömmen normaliseras i varje lager.


Pre-norm (modern standard, används i ANDREA):

x = x + Attention(LayerNorm(x))

Layer norm sitter före sublager, inuti den residuala grenen. Den residuala strömmen förblir onormaliserad; endast inmatningen till sublager skalas om.


Varför Pre-Norm Vann

Post-norm tränar dåligt utan LR-uppvärmning & noggrann hyperparameterjustering. Gradienterna exploderar i tidiga lager eftersom varje layer norm scramblar den residuala strömmens ackumulerade tillstånd. Den ursprungliga artikeln från 2017 använde post-norm med omfattande justering; efterföljande arbete (GPT-2, LLaMA, ANDREA) standardiserade på pre-norm.


Pre-norm tränar stabilt. Residualströmmen ackumuleras rent över alla lager; endast underlagsinmatningar normaliseras för numerisk stabilitet. Moderna transformatorer använder som standard pre-norm, & ANDREA ärver det valet.


Slutlig blockekvation

Kombinera residualer, layer norm i pre-norm-position & båda underlagen ger ANDREA:s fullständiga block:


def block_forward(x):
x = x + Attention(LayerNorm(x))   # attention-sublager
x = x + MLP(LayerNorm(x))         # MLP-sublager
return x

Två sublager, två residuala additioner, två layer norms (notera: varje sublayer har sin egen layer norm; ANDREA-120M har 24 layer norms över 12 block plus en final vid utgången, så 25 totalt). Upprepa 12 gånger. Det är stommen i ANDREA-120M.

Varför Pre-Norm Stabiliserar Träning

ANDREA använder pre-norm: `x = x + Attention(LayerNorm(x))`. Jämför mot post-norm: `x = LayerNorm(x + Attention(x))`. Ge ett skäl från ett gradientflödesperspektiv varför pre-norm tränar stabilare än post-norm i djupa staplar. Referera till residualströmmen i ditt svar.

Två Linjära Lager, En Aktivering

Tre Operationer

MLP-underrlaget är en tvålager perceptron med en icke-linjär aktivering mellan lagren:


def mlp_forward(x):
h = x · W_1 + b_1        # expandera: d_model → mlp_dim
h = GELU(h)              # icke-linjär aktivering
y = h · W_2 + b_2        # komprimera: mlp_dim → d_model
return y

Tre operationer. Två linjära, en icke-linjär. Den första linjära expanderar bredden; den andra drar ihop tillbaka.


4× Expansionsförhållandet

Moderna transformatorer ställer in mlp_dim = 4 × d_model. ANDREA-120M:


d_model = 768
mlp_dim = 4 × 768 = 3072
W_1 form = [768, 3072]      # ~2,36M parametrar
W_2 form = [3072, 768]      # ~2,36M parametrar
MLP-parametrar per block = 4,72M (ignorerar bias)

Två MLP:er sitter mellan varje par uppmärksamhetssublager (en per block). Tolv block × 4,72M ≈ 56,6M MLP-parametrar totalt i ANDREA-120M, ungefär hälften av alla parametrar.


Varför 4×

4×-förhållandet uppstod empiriskt. Mindre förhållanden minskar modellkapaciteten. Större förhållanden ger avtagande avkastning per parameter som spenderas. Under årtionden av arkitektursökningar har 4× hållit sig; det förekommer i GPT, BERT, T5, LLaMA & ANDREA.


Nylig forskning (PaLM, Chinchilla) fann att gating-mekanismer (SwiGLU) kan använda 8/3×-expansion med jämförbar kapacitet till lägre kostnad; ANDREA håller sig till klassisk GELU + 4× för enkelhet.

GELU: En mjuk aktivering

Vad GELU beräknar

GELU (Gaussian Error Linear Unit) är den standardaktiveringen mellan MLP-lager i moderna transformatorer. Dess formel:


GELU(x) = x · Φ(x)

Φ(x) är kumulativa fördelningsfunktionen för standardnormalfördelningen: sannolikheten att en standardnormalfördelad slumpvariabel hamnar på eller under x. Beräknas numeriskt:


Φ(x) ≈ 0.5 × (1 + tanh(sqrt(2/π) × (x + 0.044715 × x³)))

Beteende efter region

- För stora positiva x: Φ(x) ≈ 1, så GELU(x) ≈ x. Liksom ReLU.

- För stora negativa x: Φ(x) ≈ 0, så GELU(x) ≈ 0. Liksom ReLU.

- Nära x = 0: Φ(x) ≈ 0.5, så GELU(0) = 0 exakt. Mjuk övergång genom origo.


Till skillnad från ReLU låter GELU vissa negativa inmatningar passera, viktade av Φ(x). En liten negativ inmatning bidrar fortfarande med en liten negativ utmatning, bara mindre än den fulla inmatningen skulle göra.


Varför GELU överträffade ReLU

Empiriskt når transformatorer tränade med GELU lägre förlust än transformatorer tränade med ReLU vid samma parameterantal. Mjukheten runt noll är viktig: ReLU:s hårda avskärning vid noll producerar gradientavbrott; GELU:s mjuka kurva ger renare gradienter för bakåtpropagering.


ANDREA:s träningsmotor microgpt_cuda.cu levererar en handskriven GELU CUDA-kärna. Kärnan använder tanh-approximationen ovan; moderna GPU:er inkluderar tanh som en enkelinstruktionsoperation.

Beräkna MLP-parametrar

ANDREA-120M har `d_model=768`, `mlp_dim=3072` och `n_layer=12`. Beräkna det totala antalet parametrar i MLP-viktmatrixerna (`W_1` och `W_2`) över alla 12 block. Ignorera bias. Visa din aritmetik. Säg sedan vilken bråkdel av ANDREA-120M:s ~120M totala parametrar detta motsvarar (avrunda till en decimal).

Tolv block bildar ANDREA-120M

Från block till modell

ANDREA-120M:s fullständiga forward pass:


def model_forward(token_ids):
x = token_embed(token_ids) + position_embed(positions)
for block_idx in range(n_layer):       # 12 block
x = block_forward(x)               # attention + MLP med residualer
x = LayerNorm(x)                       # slutnorm
logits = x · token_embed.T             # delade vikter för utdata-projektion
return logits

Sex rader. Huvudmassan finns inuti block_forward, som anropas tolv gånger. Embeddings startar pipelinen; bunden unembedding (samma matris som används för inmatningssökning, transponerad för utdataprojektion) avslutar den.


Djup som komposition

Varje block läser residualströmmen, beräknar en delta och lägger till den igen. Efter tolv pass innehåller strömmen ackumulerade bidrag från varje block. Internt tenderar lagren att specialisera sig:


- Tidiga lager (1-3): syntaktiska mönster, positionell struktur

- Mellersta lager (4-8): ordrelationer, frasgränser

- Sena lager (9-12): semantiskt innehåll, faktisk återkallelse


Denna specialisering uppstår från träningstryck, inte från arkitektoniska val. Samma enhetliga blockdesign producerar specialiserade lager när den tränas på språk.


Totala blockparametrar


KomponentPer blockÖver 12 block
Attention-projektioner (4×W)2,36M28,3M
MLP-vikter (W_1 + W_2)4,72M56,6M
Lagernormaliseringar (gamma, beta)~3K (försumbar)~37K
Totalt per block~7,1M~85M

85M parametrar i stammen. Lägg till ~13M i tokeninbäddningar (8449 vocab × 768 d_model × 2 för bunden in/ut) plus en final lagernormalisering, & ANDREA-120M:s parametrar landar på ungefär 120M. Blockdesignen står för två tredjedelar; inbäddningar resten.

Spårning av en token genom ett block

En 768-dim tokenvektor kommer in i block 7 av ANDREA-120M. Gå igenom vad som händer med den inuti blocket (i pre-norm-struktur). Nämn: båda lagernormaliseringarna, båda underlagren, båda residualtilläggen, & den slutliga formen. Ange minst en plats där residualströmmen lämnas orörd & en plats där den modifieras.