Learn Mode

How does Qwen actually work?

From text to the next token, then how the weights were learned. Real values come from Qwen3-8B-Base and are marked as measured; small worked examples are marked as toys.

2Learn

Follow one token through Qwen

Choose a stage. Each one is explained the same way: intuition, exact mechanism, tensor shapes, why it exists, and a common confusion. Panels marked Recorded Qwen measurement come from one real forward pass of the sentence "The researcher opened the notebook".

Text

1Intuition
The model never sees letters directly; it starts from a string that must be turned into integers.
2Exact mechanism
A Python string, for example "The researcher opened the notebook". Nothing has been computed yet.
3Tensor shapes
one string
4Why it exists
Language models are trained on text, but neural networks compute on numbers.
5Common confusion
The model does not read words one character at a time. Its unit of input is the token.

The running example

"The researcher opened the notebook"


3Learn

Transformer block microscope

One complete Qwen3 block, drawn from the order of operations verified in the installed implementation. The vertical rail on the left is the residual stream; it is only ever added to. Click any box.
  1. Attention sub-layer (mixes positions)
  2. MLP sub-layer (each position separately)

Block RMSNorm #1

input_layernorm
1Intuition
Rescale each position's vector to a standard size before attention reads it.
2Exact mechanism
Per position: divide by the root-mean-square over all 4096 coordinates, then multiply by a learned gain vector g (4096 numbers). Computed in float32. No mean subtraction, no bias.
RMSNorm(x) = g * x / sqrt((1/4096) sum_i x_i^2 + 1e-6)
3Tensor shapes
[B, T, 4096] -> [B, T, 4096]
4Why it exists
Keeps the input to attention on a stable scale no matter how large the residual stream has grown.
5Common confusion
This normalizes over hidden_size. The Q/K RMSNorm inside attention normalizes 128-dimensional head vectors: a different operation.

4Learn

RMSNorm lab

LayerNorm centers a vector and rescales it. RMSNorm only rescales it, by its root-mean-square magnitude, and then multiplies by a learned gain. Qwen3 uses RMSNorm everywhere, in two different roles that must not be confused.

RMSNorm step by step

Toy calculation· Toy vector, d = 4
x =gain g =
  1. 1. squares [4, 1, 16, 1]
  2. 2. mean squared magnitude (1/4) · 22 = 5.5
  3. 3. square root (with eps = 1e-6) RMS = sqrt(5.5 + 1e-6) = 2.3452
  4. 4. divide by RMS x / RMS = [0.853, -0.426, 1.706, 0.426] (its RMS is now 1)
  5. 5. learned gain g ⊙ (x / RMS) = [0.853, -0.426, 1.706, 0.426]
RMS(x) = sqrt( (1/d) Σ x_i² + ε )
RMSNorm(x) = g ⊙ x / RMS(x)
LayerNorm on the same x (gain 1, bias 0)
mean = 1.5
x - mean = [0.5, -2.5, 2.5, -0.5]
std = 1.8028
output = [0.277, -1.387, 1.387, -0.277]
What changed and what was kept
cosine(x, RMSNorm(x)) = 1 (direction kept exactly when the gain is uniform)
cosine(x, LayerNorm(x)) = 0.7687 (mean subtraction changes the direction)
Try the two buttons: scaling x leaves both outputs unchanged; adding a constant changes the RMSNorm output but not the LayerNorm output.
Recorded Qwen measurement
The stream grows by orders of magnitude; the normalized copy follows the learned gain
0.11105101520253035blockRMS (log)residual entering…RMSNorm #1 output

Last token of "The researcher opened the notebook". The residual stream entering each block grows by orders of magnitude; the input that attention actually reads has RMS set by the learned gain of that block (compare the gain chart), not by the size of the stream. The stream itself is never normalized between blocks.

Recorded Qwen measurement· Stored weights
Learned gain g, mean over its 4096 entries
0.511.522.533.55101520253035blockmean gaininput_layernormpost_attention_la…

The gains are learned, not fixed at 1. Block 1's input gain averages 0.0114; the final norm's gain averages 2.01. Because the gain is a vector, RMSNorm can change the relative sizes of coordinates; a negative gain entry would flip a coordinate's sign. The smallest input_layernorm gain entry in any block is -0.13672.

Block RMSNorm and Q/K RMSNorm are different operations

Recorded Qwen measurement· Layer 1, last token
Block RMSNormQ / K RMSNorm
Modulesinput_layernorm, post_attention_layernorm, model.normself_attn.q_norm, self_attn.k_norm
Normalizesthe whole hidden vector of a positionone head vector (Q or K) of a position
Dimension4096128
Wherebefore attention, before the MLP, after the last blockinside attention, after q_proj/k_proj and reshape, before RoPE
Gain shared acrossnothing (one 4096-vector per norm)all 32 query heads (q_norm) or all 8 KV heads (k_norm) of a layer
V normalized?No. Values are neither normalized nor rotated.
Measured, block 1residual RMS 0.0268 → normalized input RMS 0.0115query head RMS 0.023 to 0.092 → 0.88 to 1.96 across the 32 heads
RMSNorm is applied to a copy of the stream that feeds a sub-layer. In a pre-norm block, x' = x + Attn(RMSNorm(x)): the unnormalized x is what gets added to. That is why the stream can keep growing while every sub-layer still sees a well-scaled input.

5Learn

Attention, GQA and RoPE

Attention is the only computation that moves information between positions. Qwen3 adds two details to the textbook version: Q/K RMSNorm and grouped-query attention.

Q, K and V are three linear projections of the same normalized input

Q = X W_q    K = X W_k    V = X W_v
Q, query. "What am I looking for?"
K, key. "What do I contain or advertise?"
V, value. "What should be passed on if I am selected?"

These phrases are intuitive analogies, not literal semantics. The model learns three matrices that make the computation below useful for predicting the next token.

ProjectionWeight shapeOutput per positionAfter reshape and transpose
q_proj[4096, 4096]4096[B, 32, T, 128]
k_proj[4096, 1024]1024[B, 8, T, 128]
v_proj[4096, 1024]1024[B, 8, T, 128]

A linear projection is a matrix multiply: each output number is a weighted sum of the 4096 inputs. Reshape splits the 4096 query numbers of each position into 32 heads of 128; transpose moves the head axis before the position axis so that each head can be processed as its own [T, 128] matrix. No biases (attention_bias = false).

Grouped-query attention

Recorded Qwen measurement· Head counts verified
K/V 0
K/V 1
K/V 2
K/V 3
K/V 4
K/V 5
K/V 6
K/V 7

32 query heads; 8 key/value heads; 4 query heads per KV head. KV cache per token (all 36 layers, bf16): 144 KiB. Qwen3-8B's verified value is 144 KiB, 4x smaller than full multi-head attention.

Why: during generation the K and V of every past token are stored. Fewer KV heads means less memory and less memory bandwidth per generated token, while keeping 32 distinct query heads, each with its own attention pattern.

Where Q/K RMSNorm sits

  1. q = q_proj(RMSNorm₁(x)) → view [B, T, 32, 128]
  2. q = q_norm(q) over the last 128 dims, per head
  3. k = k_norm(k_proj(...).view(...)) same for keys
  4. v = v_proj(...).view(...) no norm
  5. q, k = RoPE(q, k)
  6. scores = q kᵀ · 0.0884 (= 1/sqrt(128))

Order verified in the installed transformers source. Normalizing q and k bounds the size of their dot products.

Rotary position embedding (RoPE)

Toy calculation· 2D toy, angle 0.5 rad per position
q at position 3k at position 1

Position 3 rotates q by 3 × θ = 1.5 rad; position 1 rotates k by 0.5 rad (dashed: before rotation).

Score q·k after rotation: 0.815. Move both positions forward by 4: 0.815, the same, because the score depends only on t - s = 2.

RoPE does not add a position vector to the token. It rotates Q and K, so the attention score carries their relative position. V and the residual stream are never rotated.
In the real model (verified): each 128-dimensional Q and K head vector is split into 64 pairs, dimension i paired with i + 64 ("rotate half"). Pair i rotates at frequency θi = 1,000,000-2i/128, so wavelengths range from 6.28 tokens (fastest pair) to about 5,063,256 tokens (slowest). It is applied after Q/K RMSNorm.

Causal attention on four tokens

Toy calculation· Toy Q, K, V with d_head = 2
query \ keyABCD
A0.70700.7070.283
B0.3540.707-0.3540.566
C1.0610.7070.3540.849
D0-0.7070.707-0.424

The visible pattern is lower-triangular: at position t the model cannot use positions after t. Training predicts every next token in parallel, so without the mask position t could simply read token t+1. A masked score of -infinity becomes a softmax weight of exactly 0.

Real attention weights

Recorded Qwen measurement· Qwen3-8B-Base, eager attention
Block 9, head 0: "The researcher opened the notebook"
query \ key<eot>The␣researcher␣opened␣the␣notebook
<eot>1.00
The0.910.09
␣researcher0.830.150.02
␣opened0.390.200.030.38
␣the0.180.030.050.640.11
␣notebook0.270.030.030.460.190.02

Each row sums to 1. Hatched cells are future positions the causal mask hides.

In block 9, 12 of 32 heads put more than half of their weight (averaged over query positions 1 to 5) on position 0, the document-start token. Weight concentrating on the first position is a commonly reported pattern (often called an attention sink); reading it as "the head ignores the sentence" would be an over-interpretation. Only the blocks listed were exported.

From head outputs to residual addition #1

  1. 1. Each head returns a weighted sum of values: [B, 32, T, 128]
  2. 2. Transpose and concatenate the heads: [B, T, 4096]
  3. 3. Output projection o_proj: [B, T, 4096] → [B, T, 4096]
  4. 4. Residual addition #1: x' = x + attention update

Recorded Qwen measurement Block 1, last token: ‖x‖ = 1.71, ‖attention update‖ = 3.61, RMS of x' = 0.065.

Attention(Q, K, V) = softmax( Q Kᵀ / sqrt(d_head) + M_causal ) V

6Learn

SwiGLU MLP and the residual stream

After attention has moved information between positions, the MLP transforms what each position holds. Its update is added to the stream: residual addition #2.

The exact path in Qwen3MLP

Recorded Qwen measurement· Dimensions verified
  1. gate = gate_proj(x) [B, T, 4096] → [B, T, 12288]
  2. up = up_proj(x) [B, T, 4096] → [B, T, 12288]
  3. activated_gate = SiLU(gate) elementwise
  4. combined = activated_gate * up elementwise
  5. output = down_proj(combined) [B, T, 12288] → [B, T, 4096]
MLP(x) = W_down ( SiLU(W_gate x) ⊙ (W_up x) )

Three weight matrices, no biases: 150,994,944 parameters per block, 78% of the block.

The distinction to remember

ThecatsatdownATTENTION mixes information ACROSS positions
MLPTheMLPcatMLPsatMLPdownMLP transforms EACH position independently
Why can the MLP change the meaning of a token if it never looks at other positions? Because by the time it runs, attention has already copied information from earlier positions into this position's vector. The MLP then transforms that combined vector. Mixing (attention) and transforming (MLP) alternate 36 times.

One gate unit

Toy calculation

SiLU(gate) = gate · sigmoid(gate) = 1.2264;   combined = SiLU(gate) · up = 0.9811

A strongly negative gate gives SiLU near 0 and switches the feature off, whatever up says. That multiplicative gate is the "GLU" in SwiGLU; down_proj then mixes all intermediate features back into the hidden size.

Recorded Qwen measurement
Size of each update, last token, every block
101001,0005101520253035blockL2 norm (log)‖MLP update‖‖residual enterin…‖attention update‖

"The researcher opened the notebook", last token "notebook". Updates are added, so the stream after block k is the embedding plus the sum of all 2 × k updates so far.

Residual addition #2 in block 36

Recorded Qwen measurement
‖x′‖ after attention1716.3
‖MLP update‖2180.1
‖x″ = x′ + update‖2101.2
cosine(block input, block output)0.338

In this sentence the last block's MLP update is larger than the stream it is added to, so the final block changes the direction of the last token's vector substantially. One sentence is an illustration, not a general finding.

Shapes: [B, T, 4096] in and out; the 12288-wide intermediate exists only inside the MLP.


7aLearn · inference

Final RMSNorm, LM head, logits and decoding

After the last block, one more RMSNorm and a linear layer turn each position's 4,096-number vector into 151,936 scores.
  1. h = model.norm(x) [B, T, 4096] → [B, T, 4096]
  2. z = lm_head(h) [B, T, 4096] → [B, T, 151,936] (separate weights, not tied)
  3. p = softmax(z) over the last axis
p_i = exp(z_i) / Σ_j exp(z_j)
LOGIT ≠ PROBABILITY. In the table below the top logit is 32.3 but its probability is 0.162. Adding the same constant to every logit would leave every probability unchanged.

Decoding lab

Recorded Qwen measurement· Real top-50 logits; exact normalizers
temperature T
tokenlogitp (T=1)sampling p
.32.250.1620.162
.↵31.750.0980.098
,31.630.0870.087
␣and31.630.0870.087
↵31.380.0670.067
␣to31.380.0670.067
␣The30.630.0320.032
↵↵30.500.0280.028
␣the30.500.0280.028
␣for30.500.0280.028
.↵↵30.380.0250.025
␣on29.880.0150.015
's29.880.0150.015
␣opened29.750.0130.013
␣notebook29.500.0100.010

Logits are divided by T before softmax. T < 1 sharpens the distribution, T > 1 flattens it. The 50 exported tokens hold 86.5% of the probability at T = 1; the rest is spread over the other 151,886 rows. These are inference-time decoding strategies. They are not how the model was pretrained.

Intermediate diagnostic projection of the last position ("␣notebook")

Recorded Qwen measurement

Each row applies Qwen's own final RMSNorm and LM head to the residual stream after a block. This is a diagnostic, not "Qwen's prediction at layer k": the final norm and LM head were trained to read only the last residual. The model's actual prediction is the last row.

depthtop projected tokens (diagnostic probability)rank of final choice "."
0 (embeddings)␣circ 0.251 emm 0.195 阐明 0.03274,658
1切れ 0.103 艇 0.031 scopes 0.028110,413
2␣advisers 0.040 公共服务 0.040 ␣sergeant 0.03356,690
3公共服务 0.163 services 0.099 ␣vouchers 0.03459,733
4方式进行 0.232 时代的 0.059 奎 0.05262,167
5-scripts 0.047 acher 0.039 -span 0.03434,068
6-record 0.053 式的 0.032 -span 0.02325,817
7edImage 0.071 aja 0.059 里的 0.03044,957
8ypad 0.056 /screen 0.036 ␣Ink 0.02534,178
9-span 0.204 /screen 0.102 aud 0.08531,211
10电脑 0.067 folders 0.052 ipt 0.03482,355
11电脑 0.155 袋 0.065 里的 0.03526,220
12袋 0.072 限り 0.068 bag 0.03911,777
13限り 0.222 iesz 0.041 /email 0.03021,808
14限り 0.153 iesz 0.053 _ang 0.04715,966
15党工委 0.072 iesz 0.056 限り 0.03952,454
16党工委 0.069 iesz 0.034 /Table 0.03255,131
17�� 0.053 iesz 0.021 ês 0.01477,325
18␣Bible 0.037 /lab 0.027 .old 0.01793,247
19�� 0.069 acci 0.037 _reading 0.03594,468
20/language 0.053 限り 0.034 itian 0.01580,270
21ator 0.248 /Table 0.017 限り 0.010112,231
22ator 0.039 ␣([[ 0.032 _hp 0.030139,140
23限り 0.054 _reading 0.033 _question 0.03388,564
24_reading 0.060 _visible 0.053 /lab 0.03243,987
25扉 0.059 ␣containing 0.046 写字 0.03810,977
26电脑 0.077 /book 0.064 ␣containing 0.0445,146
27␣lid 0.137 ␣drawer 0.083 扉 0.0655,894
28␣halfway 0.255 ␣containing 0.069 ␣drawer 0.0394,511
29␣halfway 0.173 ␣lid 0.077 ␣containing 0.0725,296
30␣notebook 0.691 ␣opened 0.057 ␣opener 0.0422,601
31␣notebook 0.862 ␣opened 0.062 -opening 0.0142,725
32␣notebook 0.531 ␣opened 0.322 ␣opening 0.0721,062
33␣notebook 0.583 ␣opened 0.243 ␣open 0.079332
34␣notebook 0.557 ␣opened 0.383 ␣opening 0.01732
35␣notebook 0.171 ␣opened 0.118 .↵ 0.0988
36 · actual output. 0.162 .↵ 0.098 ␣and 0.0871

KV cache

Recorded Qwen measurement· Sizes computed from the verified config

Without a cache, generating token n+1 would rerun the whole prefix: every previous position's K and V would be recomputed in every layer, for every new token.

With a cache, K and V of past positions are stored once per layer. A new token computes only its own Q, K and V, appends its K and V, and attends over cached + new keys.

  1. prompt → compute K, V for all positions → cache
  2. new token → its Q, K, V → append K, V
  3. attend: Q_new against [K_cache; K_new], weights on [V_cache; V_new]

Queries are never cached: only the newest position asks a question. Keys are cached after RoPE.

variantKV headsper tokenat 4,096 tokens
GQA (Qwen3-8B)8144 KiB576 MiB
MHA32576 KiB2.25 GiB
MQA118.0 KiB72.0 MiB
2 (K and V) × 8 × 128 × 36 layers × 2 bytes = 147,456 bytes

Per sequence, bfloat16. Fewer KV heads means a proportionally smaller cache.


7bLearn · training, kept separate from inference

How Qwen learns

Training and inference use the same forward pass but differ in everything around it. This section is only about training.
  1. tokens
  2. forward pass
  3. logits
  4. cross-entropy
  5. loss
  6. backpropagation
  7. gradients
  8. optimizer
  9. weight update
L = −(1/T) Σ_t log p_θ(x_(t+1) | x_≤t)

All 8,190,735,360 parameters change during pretraining. The model does not store documents in a database: what it learns is spread across these weights, which is why it can sometimes reproduce famous text (see the Recall Microscope) without holding a copy that can be looked up.

Teacher forcing

Toy calculation· Toy sequence
position0123
input (true tokens)ABCD
target (next token)BCDE

All four predictions are made in one parallel forward pass. Each position sees the TRUE previous tokens (never its own earlier guesses), and the causal mask stops it from seeing its own target.

The training objective on our sentence

Recorded Qwen measurement· Forward pass only, no weights changed
contexttargetp(target)rankloss −log pmodel's top 3
<|endoftext|>The0.014104.29Human What How
The␣researcher2.3e-856,55017.59The ↵ 的
The␣researcher␣opened2.1e-51,41510.78's ␣is ␣will
The␣researcher␣opened␣the0.19211.65␣the ␣a ␣their
The␣researcher␣opened␣the␣notebook9.5e-4996.96␣door ␣researcher ␣discussion

Cross-entropy averaged over the 5 targets: 8.254 nats. During pretraining this number, averaged over trillions of tokens, is what gradient descent pushes down. A surprising word ("␣researcher") costs the most.

Backprop explorer

Toy calculation· Two-weight network

Network: h = w₁ · x, ŷ = w₂ · h, loss = (ŷ − y)². Input x = 1.5, target y = 3, learning rate 0.05.

  1. forward h = 0.5 × 1.5 = 0.75
  2. forward ŷ = 0.8 × 0.75 = 0.6
  3. loss (0.6 − 3)² = 5.76
  4. derivative ∂L/∂ŷ = 2(ŷ − y) = -4.8
  5. chain rule ∂L/∂w₂ = ∂L/∂ŷ · h = -3.6
  6. chain rule ∂L/∂w₁ = ∂L/∂ŷ · w₂ · x = -5.76
  7. update w ← w − lr · ∂L/∂w → w₁ = 0.788, w₂ = 0.98

Loss after each step: 5.76

A gradient says how the loss would change if a parameter were nudged. Training Qwen3-8B applies the same chain rule to all 8,190,735,360 parameters at once (automatic differentiation), and an optimizer such as AdamW turns gradients into updates.

Training vs inference

TrainingInference
Weightsupdatedfrozen
Inputstrue tokens (teacher forcing)the model's own previous outputs
Positionsall at once, in parallelone new token per step
Output usedloss on every positionlast position only, then a decoding rule
KV cachenot neededused to avoid recomputation

Base model vs instruction model

Base: trained mainly by causal language modeling (the loss above) on a large corpus. The checkpoint card lists its training stage as "Pretraining". Instruct: the base model plus post-training (instruction tuning, preference or reinforcement learning).

LatentLens starts with the base model because we want representations of the pretrained language model without making assistant alignment the main confounder. This does not mean the base model is "neutral": its pretraining data and recipe also shape what it represents.

Decoding rules (greedy, temperature, top-k, top-p) and the KV cache belong to inference. Teacher forcing, the loss, gradients and the optimizer belong to training.

Learn · teach-back

Test my understanding

Answer out loud first, then reveal the explanation. If an answer surprises you, return to the section it came from.
residual

What is the residual stream?

rmsnorm

Why does Qwen normalize before each sub-layer?

rmsnorm

What is the difference between LayerNorm and RMSNorm?

attention

What does Q represent?

attention

What does K represent?

attention

What does V represent?

attention

Why does Qwen3-8B have fewer KV heads than query heads?

rope

Where is RoPE applied?

attention

Why is causal masking needed?

mlp

Does the MLP mix different token positions?

residual

Why use residual connections at all?

output

What does the LM head output?

output

What is the difference between a logit and a probability?

inference

What is cached during autoregressive generation?

training

What changes during training?

training

Why is inference different from training?