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

un

gast
1 / ?
terug naar lessen

Attention Plus MLP, Herhaald

Transformer Block Pre-Norm Structure


Twee Sublayers

Een transformerblok bevat precies twee sublayers, elk opererend op een tokenvolgorde van vorm [batch, seq_len, d_model]:


1. Multi-head attention sublaag. Tokens kijken naar elkaar. Activiteit 68 behandelde dit in detail. Output-vorm komt overeen met invoervorm.

2. Feed-forward MLP sublaag. Elk token transformeert onafhankelijk via een tweelaags perceptron. Geen informatiestroom tussen tokens. Output-vorm komt overeen met invoervorm.


Beide sublagen behouden de [batch, seq_len, d_model]-vorm. Die behoud laat blokken stapelen: output van laag N voedt invoer van laag N+1 zonder vormacrobatiek.


Wat Elke Sublag Bijdraagt

Attention verplaatst informatie over posities heen: een token op positie 17 kan informatie ophalen van posities 1 tot en met 16. De MLP transformeert informatie binnen elke positie: de representatie van een token wordt gevormd door geleerde niet-lineaire functies, maar ziet nooit zijn buren.


Het stapelen van blokken wisselt deze twee operaties af. Attention van laag 1 mixt posities. MLP van laag 1 herschaapt per positie. Attention van laag 2 mixt opnieuw, nu over de herschaapte representaties. Deze afwisseling vergroot de expressieve kracht met de diepte.


ANDREA's Stapel


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

Let op dat mlp_dim = 4 × d_model in de hele familie geldt. Die verhouding geldt in bijna elke moderne transformer. Sectie 3 legt uit waarom.

De Sublayers Benennen

Een transformerblok bevat twee sublayers. Noem ze in volgorde, & voor elke sublayer geef aan of het informatie tussen posities verplaatst (token-naar-token) of informatie transformeert binnen een enkele positie (onafhankelijk per token). Eén zin per sublayer.

Waarom Skip Connections Belangrijk Zijn

Het Residual Patroon

Elke sublayer wikkelt zijn berekening in een residual connection. De output voegt de input weer toe:


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

Binnen elke sublaag produceert de functie Attention(...) of MLP(...) een delta. Het blok vervangt de invoer niet; het voegt een geleerde correctie toe.


Waarom Dit Belangrijk Is

Drie redenen waarom residual connecties domineren in diepe architecturen:


1. Gradientenstroom. Tijdens backpropagation geeft de optelling gradiënten een direct pad van uitvoer terug naar invoer, waarbij de sublaag wordt omzeild. Een stack van 12 lagen zonder residuals zou het gradiëntsignaal verliezen lang voordat het de embeddings bereikt; met residuals blijft de gradiëntmagnitude bruikbaar door honderden lagen heen.


2. Identiteitsinitialisatie. Bij initialisatie produceren sublaaggewichten kleine uitvoerwaarden. De residual connectie betekent dat laag N aanvankelijk bijna onveranderd doorgeeft. Training leert deltas progressief vanaf een werkend startpunt.


3. Compositief leren. Elke block leert een verfijning, geen vervanging. Laag 1 voegt mogelijk positionele informatie toe. Laag 2 voegt mogelijk syntactische structuur toe. Laag 7 voegt mogelijk semantische relaties toe. De residual stream accumuleert.


Laag Normalisatie

Voor elke sublaag rescaleert LayerNorm de representatie van elk token naar nul gemiddelde & unit variantie, en past vervolgens geleerde per-feature gain & bias toe:


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

Gemiddelde & variantie worden berekend over de d_model dimensie, apart voor elk token. Twee geleerde vectoren (gamma, beta, elk vorm [d_model]) herstellen de expressieve schaal. Normalisatie houdt activaties in een numeriek stabiel bereik; zonder dit rollen kleine trainingsinstabiliteiten uit tot NaN-gradienten.

Pre-Norm vs Post-Norm

Een subtiele maar cruciale keuze

Twee manieren om layer norm in een residual sublayer te integreren:


Post-norm (origineel 2017 paper):

x = LayerNorm(x + Attention(x))

Layer norm zit na de residual optelling. De residual stream zelf wordt genormaliseerd in elke laag.


Pre-norm (moderne standaard, gebruikt in ANDREA):

x = x + Attention(LayerNorm(x))

Layer norm zit vóór de sublaag, binnen de residual branch. De residual stream blijft niet-genormaliseerd; alleen de input naar de sublaag wordt geschaald.


Waarom Pre-Norm Won

Post-norm traint slecht zonder LR warmup & zorgvuldige hyperparameter-afstemming. Gradienten exploderen in vroege lagen omdat elke layer norm de geaccumuleerde toestand van de residual stream door elkaar schudt. Het originele 2017 paper gebruikte post-norm met uitgebreide afstemming; vervolgwerk (GPT-2, LLaMA, ANDREA) standaardiseerde op pre-norm.


Pre-norm traint stabiel. De residual stream hoopt schoon op over alle lagen; alleen sublaag-ingangen worden genormaliseerd voor numerieke stabiliteit. Moderne transformers gebruiken standaard pre-norm, & ANDREA erft die keuze.


Eindblokvergelijking

Het combineren van residuals, layer norm in pre-norm positie, & beide sublagen geeft ANDREA's volledige blok:


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

Twee sublayers, twee residual toevoegingen, twee layer norms (opmerking: elke sublayer heeft zijn eigen layer norm; ANDREA-120M heeft 24 layer norms over 12 blokken plus een finale aan de output, dus 25 totaal). Herhaal 12 keer. Dat is de stam van ANDREA-120M.

Waarom Pre-Norm Training Stabiliseert

ANDREA gebruikt pre-norm: `x = x + Attention(LayerNorm(x))`. Vergelijk met post-norm: `x = LayerNorm(x + Attention(x))`. Geef één reden vanuit een gradient-flow perspectief waarom pre-norm stabieler traint dan post-norm in diepe stacks. Verwijs naar de residual stream in je antwoord.

Twee Lineaire Lagen, Eén Activatiefunctie

Drie Operaties

De MLP sublayer is een tweelaags perceptron met een niet-lineaire activatie tussen de lagen:


def mlp_forward(x):
h = x · W_1 + b_1        # uitbreiden: d_model → mlp_dim
h = GELU(h)              # niet-lineaire activatie
y = h · W_2 + b_2        # inkrimpen: mlp_dim → d_model
return y

Drie operaties. Twee lineair, één niet-lineair. De eerste lineaire vergroot de breedte; de tweede trekt deze weer samen.


De 4× Uitbreidingsverhouding

Moderne transformers stellen mlp_dim = 4 × d_model. ANDREA-120M:


d_model = 768
mlp_dim = 4 × 768 = 3072
W_1 vorm = [768, 3072]      # ~2.36M params
W_2 vorm = [3072, 768]      # ~2.36M params
MLP params per blok = 4.72M (bias negerend)

Twee MLPs zitten tussen elk paar attention-sublagen (één per blok). Twaalf blokken × 4.72M ≈ 56.6M MLP-parameters totaal in ANDREA-120M, ruwweg de helft van alle parameters.


Waarom 4×

De 4× ratio ontstond empirisch. Kleinere ratios verminderen de modelcapaciteit. Grotere ratios leveren afnemende rendementen per bestede parameter. Over decennia van architectuuronderzoek heeft 4× standgehouden; het verschijnt in GPT, BERT, T5, LLaMA, & ANDREA.


Recent werk (PaLM, Chinchilla) ontdekte dat gating-mechanismen (SwiGLU) een 8/3× expansie kunnen gebruiken met vergelijkbare capaciteit tegen lagere kosten; ANDREA blijft bij klassieke GELU + 4× voor eenvoud.

GELU: Een Vloeiende Activering

Wat GELU Berekent

GELU (Gaussian Error Linear Unit) is de standaard activering tussen MLP-lagen in moderne transformers. De formule:


GELU(x) = x · Φ(x)

Φ(x) is de cumulatieve verdelingsfunctie van de standaard normale verdeling: de kans dat een standaard Gaussische willekeurige variabele op of onder x valt. Numeriek berekend:


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

Gedrag Per Regio

- Voor grote positieve x: Φ(x) ≈ 1, dus GELU(x) ≈ x. Net als ReLU.

- Voor grote negatieve x: Φ(x) ≈ 0, dus GELU(x) ≈ 0. Net als ReLU.

- Rond x = 0: Φ(x) ≈ 0.5, dus GELU(0) = 0 precies. Vloeiende overgang door de oorsprong.


In tegenstelling tot ReLU laat GELU sommige negatieve inputs door, gewogen door Φ(x). Een kleine negatieve input draagt nog steeds een kleine negatieve output bij, alleen minder dan de volledige input zou doen.


Waarom GELU ReLU overtrof

Empirisch bereiken transformers getraind met GELU een lagere loss dan transformers getraind met ReLU bij hetzelfde aantal parameters. De vloeiendheid rond nul doet ertoe: ReLU's harde afkap punt bij nul produceert gradiëntdiscontinuïteiten; GELU's vloeiende kromme biedt schonere gradiënten voor backpropagation.


ANDREA's training engine microgpt_cuda.cu bevat een handgeschreven GELU CUDA-kernel. De kernel gebruikt de tanh-benadering hierboven; moderne GPU's bevatten tanh als een single-instruction-op.

Berekenen van MLP-parameters

ANDREA-120M heeft `d_model=768`, `mlp_dim=3072`, & `n_layer=12`. Bereken het totale aantal parameters in MLP-gewichtsmatrices (`W_1` & `W_2`) over alle 12 blokken. Negeer biases. Toon je rekenwerk. Stel vervolgens wat fractie van ANDREA-120M's ~120M totale parameters dit vertegenwoordigt (afronden op één decimaal).

Twaalf Blokken Samenstellen ANDREA-120M

Van Blok naar Model

De volledige forward pass van ANDREA-120M:


def model_forward(token_ids):
x = token_embed(token_ids) + position_embed(positions)
for block_idx in range(n_layer):       # 12 blocks
x = block_forward(x)               # attention + MLP w/ residuals
x = LayerNorm(x)                       # final norm
logits = x · token_embed.T             # tied weights for output projection
return logits

Zes lijnen. De kern zit in block_forward, twaalf keer aangeroepen. Embeddings starten de pijplijn; gekoppelde unembedding (dezelfde matrix gebruikt voor input-opzoeking, getransponeerd voor output-projectie) sluit hem af.


Diepte Als Compositie

Elk blok leest de residual stream, berekent een delta, & voegt het terug toe. Na twaalf passes bevat de stream geaccumuleerde bijdragen van elk blok. Intern specialiseren lagen zich:


- Vroege lagen (1-3): syntactische patronen, positionele structuur

- Middenlagen (4-8): woordrelaties, frasegrenzen

- Late lagen (9-12): semantische inhoud, feitelijke herinnering


Deze specialisatie ontstaat door trainingsdruk, niet door architectonische keuzes. Hetzelfde uniforme blokontwerp produceert gespecialiseerde lagen wanneer het op taal wordt getraind.


Totale Blokparameters


ComponentPer blokOver 12 blokken
Attention-projecties (4×W)2.36M28.3M
MLP-weights (W_1 + W_2)4,72M56,6M
Laagnormalisaties (gamma, beta)~3K (verwaarloosbaar)~37K
Totaal per blok~7,1M~85M

85M parameters in de trunk. Voeg ~13M toe in token-embeddings (8449 vocab × 768 d_model × 2 voor gebonden input/output) plus een finale laagnormalisatie, & ANDREA-120M's parameterenaantal komt op ruwweg 120M. Het blokontwerp telt voor twee-derde; embeddings de rest.

Een token traceren door één blok

Een 768-dim tokenvector komt block 7 van ANDREA-120M binnen. Loop door wat er binnen het blok met het gebeurt (in pre-norm structuur). Noem: beide laagnormalisaties, beide sublayers, beide restantaddities, & de finale vorm. Noem minstens één plek waar de residual stream onaangeraakt blijft & één plek waar deze wordt gewijzigd.