Mục lục
- Mục tiêu bài học
- Transformer block là gì
- Bốn thành phần
- Sơ đồ Pre-Norm
- Post-Norm (Vaswani 2017)
- Pre-Norm (modern)
- Vì sao Pre-Norm thắng
- Feed-Forward Network
- Vì sao cần FFN
- Activation: ReLU, GELU, SwiGLU
- LayerNorm và RMSNorm
- Residual connection
- Position-wise
- Stack nhiều block
- Param count một block
- Decoder block vs Encoder-Decoder block
- Biến thể 2024-2026
- PyTorch implementation
- Mini Transformer stack
- Vị trí trong full Transformer
- Bài tập
- Tóm tắt
Mục tiêu bài học
Sau bài học, bạn sẽ:
- Liệt kê bốn thành phần của Transformer block: Multi-Head Attention, FFN, LayerNorm, residual.
- Vẽ và viết được thứ tự forward cho Post-Norm (Vaswani 2017) và Pre-Norm (modern).
- Giải thích vì sao Pre-Norm ổn định hơn khi stack sâu.
- Viết công thức FFN, biết hidden dim thường là \( 4 d_{\text{model}} \) và vai trò của FFN.
- Phân biệt ReLU, GELU, SwiGLU.
- So sánh LayerNorm và RMSNorm.
- Ước lượng param count một block ~\( 12 d^2 \).
- Biết tên các biến thể modern: MoE, Parallel block, no-bias Llama.
- Implement TransformerBlock Pre-Norm bằng PyTorch.
Bài này ráp các thành phần đã học (B9 attention, B10 self-attention, B11 multi-head, B12 positional encoding) thành một khối lặp lại. Bài 14 sẽ so sánh ba dạng kiến trúc dùng khối này: encoder-only, decoder-only, encoder-decoder.
Transformer block là gì
Transformer block là một module nhận sequence vector \( X \in \mathbb{R}^{n \times d} \) và trả về output cùng shape \( Z \in \mathbb{R}^{n \times d} \). Vì input và output cùng shape, có thể stack nhiều block liên tiếp — output block trước là input block sau.
Một LLM modern thực chất là: embedding + positional encoding → \( N \) Transformer block → một linear head. Toàn bộ "kiến thức" của model phân bố trong tham số của \( N \) block đó.
Số block \( N \) tỉ lệ với capacity:
- GPT-2 small: 12 block, \( d = 768 \).
- GPT-3 175B: 96 block, \( d = 12288 \).
- Llama 3 8B: 32 block, \( d = 4096 \).
- Llama 3 70B: 80 block, \( d = 8192 \).
Mỗi block "tinh chỉnh" representation thêm một lần. Block đầu thường học pattern bề mặt (token co-occurrence); block giữa học cú pháp, vai trò ngữ pháp; block cuối học ngữ nghĩa, suy luận. Mô tả này là quan sát phổ biến từ interpretability, không phải định luật cố định.
Bốn thành phần
Một Transformer block có đúng bốn thành phần:
- Multi-Head Self-Attention (MHA) — đã học ở Bài 11. Vai trò: mix thông tin giữa các token.
- Feed-Forward Network (FFN) — hai linear layer với activation giữa. Vai trò: nonlinear transformation per-token.
- LayerNorm (xuất hiện 2 lần) — chuẩn hoá theo chiều feature. Giữ ổn định scale của activation. Series 3 Bài 23 đã giới thiệu.
- Residual connection (xuất hiện 2 lần) — ý tưởng từ ResNet (Series 3 Bài 33). Cho gradient chảy thẳng qua skip path, giúp train sâu.
Khác biệt giữa các Transformer hiện đại nằm ở: (a) thứ tự LayerNorm vs sublayer, (b) chọn LayerNorm hay RMSNorm, (c) chọn activation cho FFN, (d) có biến thể FFN nào (MoE) không. Phần "khung" thì giống nhau.
Sơ đồ Pre-Norm
Sơ đồ dạng text cho Pre-Norm — variant dùng trong GPT-2+, Llama, Mistral:
Input X
│
├──> LayerNorm > MHA > Add
│ │
│<──────────────────────┘
│
├──> LayerNorm > FFN > Add
│ │
│<──────────────────────┘
↓
Output Z
Hai mũi tên dài bên trái là residual — input được cộng thẳng vào output của mỗi sublayer. Hai sublayer (MHA, FFN) được "ôm" bởi cặp (LayerNorm trước → sublayer → residual sau). Output cùng shape với input để stack được.
Post-Norm (Vaswani 2017)
Bản nguyên thuỷ trong Attention Is All You Need đặt LayerNorm sau residual:
\[ Y = \text{LayerNorm}\!\big( X + \text{MHA}(X) \big) \]
\[ Z = \text{LayerNorm}\!\big( Y + \text{FFN}(Y) \big) \]
Ý tưởng: chuẩn hoá ngay sau khi cộng residual để output mỗi block có cùng phân phối. Cách này hoạt động tốt với Transformer "không quá sâu" (6 layer encoder + 6 layer decoder như paper gốc) nhưng phát sinh vấn đề khi stack sâu hơn — sẽ phân tích ở Bước 7.
Pre-Norm (modern)
Biến thể được phổ biến từ GPT-2 (Radford et al., 2019) và Xiong et al. (2020) đặt LayerNorm trước sublayer:
\[ Y = X + \text{MHA}\!\big( \text{LayerNorm}(X) \big) \]
\[ Z = Y + \text{FFN}\!\big( \text{LayerNorm}(Y) \big) \]
Sự khác biệt nằm ở chỗ residual path giờ "sạch" — chỉ là phép cộng, không qua LayerNorm. Sublayer (MHA / FFN) nhận input đã được chuẩn hoá. Đây là default của GPT-2 trở đi và mọi Llama / Mistral / Qwen / Phi đều dùng.
Một biến thể nhỏ là Sandwich-Norm (Ding et al., 2021) thêm LayerNorm cả trước và sau sublayer, ít phổ biến hơn nhưng dùng trong một số model nội bộ ở Google.
Vì sao Pre-Norm thắng
Xiong et al. (2020), On Layer Normalization in the Transformer Architecture, phân tích lý thuyết và thực nghiệm:
- Post-Norm: gradient ở layer đầu (gần input) có magnitude phụ thuộc số layer \( N \); với \( N \) lớn, gradient có thể bùng nổ hoặc triệt tiêu. Train ổn định cần learning rate warmup dài.
- Pre-Norm: gradient chảy thẳng qua residual path mà không bị giảm bởi LayerNorm. Magnitude ổn định bất kể \( N \). Có thể bỏ warmup hoặc warmup ngắn.
Hệ quả thực tế: Pre-Norm cho phép train Transformer sâu hơn (50+ layer) mà không cần tinh chỉnh learning rate phức tạp. Đây là lý do tại sao mọi LLM lớn (GPT-3 96 layer, Llama 3 70B 80 layer) đều chọn Pre-Norm.
Đánh đổi nhỏ: Pre-Norm có thể cho kết quả hơi kém hơn Post-Norm ở model nhỏ và shallow (Liu et al., 2020) — nhưng khi scale lên, độ ổn định quan trọng hơn vài phần trăm hiệu năng.
Feed-Forward Network
FFN trong Vaswani 2017 là một MLP 2 lớp:
\[ \text{FFN}(x) = W_2 \cdot \text{ReLU}\!\big( W_1 x + b_1 \big) + b_2 \]
Trong đó:
- \( W_1 \in \mathbb{R}^{d_{\text{ff}} \times d_{\text{model}}} \): expand từ \( d_{\text{model}} \) lên \( d_{\text{ff}} \).
- \( W_2 \in \mathbb{R}^{d_{\text{model}}\times d_{\text{ff}}} \): project ngược lại về \( d_{\text{model}} \).
- \( d_{\text{ff}} = 4 \cdot d_{\text{model}} \) là tỉ lệ default.
Ví dụ với \( d = 512 \) (paper gốc): \( 512 \to 2048 \to 512 \). Với Llama 3 8B \( d = 4096 \): \( d_{\text{ff}} \approx 14336 \) (tỉ lệ ~3.5×, đã điều chỉnh để bù SwiGLU thêm tham số).
FFN là per-token: cùng một bộ tham số \( W_1, W_2 \) áp lên từng vector token một cách độc lập. Không có chuyện token này "trộn" vào token khác trong FFN — phần mix đã làm xong ở MHA.
Vì sao cần FFN
Nếu chỉ có attention, Transformer vẫn chạy được — nhưng kém hơn rất nhiều. Có ba lý do FFN không thể thiếu:
- Nonlinearity: attention chỉ là tổ hợp tuyến tính có trọng số. Stack nhiều attention thuần vẫn tương đương một phép tuyến tính lớn. FFN với ReLU / GELU đưa nonlinearity vào, cho model học hàm phi tuyến.
- Per-token transformation: attention trả lời "trộn thông tin từ các token nào", FFN trả lời "biến thông tin đó thành cái gì". Hai vai trò bổ sung.
- Capacity / Memory: Geva et al. (2021), Transformer Feed-Forward Layers Are Key-Value Memories, cho thấy FFN hoạt động như associative memory — \( W_1 \) gồm các "key pattern", \( W_2 \) là các "value" tương ứng. Kiến thức factual của model nằm chủ yếu ở FFN.
Hệ quả param: với \( d_{\text{ff}} = 4d \), FFN chiếm \( 2 \cdot d \cdot 4d = 8 d^2 \) tham số, MHA chiếm \( 4 d^2 \) (Bài 11). Tỉ lệ ~\( 2:1 \) — FFN nhiều tham số gấp đôi MHA. Trong các model như Llama 3 với SwiGLU, FFN có thể chiếm 65-70% tổng tham số của block.
Activation: ReLU, GELU, SwiGLU
Activation giữa hai linear của FFN đã đổi nhiều lần theo thời gian:
- ReLU (Vaswani 2017): \( \text{ReLU}(x) = \max(0, x) \). Đơn giản, nhanh, "tắt" nửa đầu vào về 0. Gradient zero ở vùng âm.
- GELU (BERT, GPT-2): \( \text{GELU}(x) = x \cdot \Phi(x) \) với \( \Phi \) là CDF chuẩn. Smooth approximation của ReLU, không có "kink" cứng tại 0. Hendrycks & Gimpel (2016).
- SwiGLU (PaLM, Llama, Mistral): biến thể của Gated Linear Unit. Shazeer (2020) chứng minh nó cho perplexity tốt hơn GELU ở cùng compute budget.
Công thức SwiGLU:
\[ \text{SwiGLU}(x) = \big( \text{Swish}(x W_1) \odot (x W_3) \big) W_2 \]
Với \( \text{Swish}(x) = x \cdot \sigma(x) \) và \( \odot \) là phép nhân element-wise. Khác FFN cổ điển ở chỗ có ba linear thay vì hai, và một nhánh đóng vai trò "gate" (cổng) điều biến nhánh kia.
Vì SwiGLU dùng 3 ma trận trọng số thay vì 2, để giữ tổng tham số FFN tương đương ReLU/GELU, các model như Llama thường giảm \( d_{\text{ff}} \) từ \( 4d \) xuống ~\( \frac{8}{3} d \). Llama 3 8B: \( d = 4096 \), \( d_{\text{ff}} = 14336 \) (~3.5×, đã làm tròn lên bội số 256 để align tốt trên GPU).
LayerNorm và RMSNorm
LayerNorm (Ba et al., 2016) chuẩn hoá theo chiều feature của từng token:
\[ \text{LN}(x) = \gamma \odot \frac{x - \mu}{\sigma} + \beta, \quad \mu = \frac{1}{d}\sum_i x_i, \quad \sigma = \sqrt{\frac{1}{d}\sum_i (x_i - \mu)^2 + \epsilon} \]
Khác BatchNorm: LayerNorm tính \( \mu, \sigma \) qua chiều feature (\( d \) số), không qua chiều batch — vì vậy hoạt động giống nhau ở train và inference, không phụ thuộc batch size. Phù hợp với sequence model.
RMSNorm (Zhang & Sennrich, 2019) đơn giản hoá: bỏ \( \mu \) và \( \beta \), chỉ scale theo root mean square:
\[ \text{RMSNorm}(x) = \gamma \odot \frac{x}{\text{RMS}(x)}, \quad \text{RMS}(x) = \sqrt{\frac{1}{d}\sum_i x_i^2 + \epsilon} \]
Tại sao Llama / Mistral / Qwen chọn RMSNorm:
- Nhanh hơn ~15-20% so với LayerNorm (ít phép tính hơn).
- Ít tham số (\( d \) thay vì \( 2d \)).
- Thực nghiệm cho perplexity tương đương hoặc tốt hơn ở scale lớn.
Trade-off: với model nhỏ, LayerNorm có thể vẫn tốt hơn vì bias \( \beta \) cho thêm flexibility. Quy ước modern cho LLM ≥ 1B params là RMSNorm.
Residual connection
Residual connection (skip connection) đến từ ResNet (He et al., 2015 — Series 3 Bài 33). Công thức tổng quát:
\[ \text{output} = \text{sublayer}(x) + x \]
Hai lý do quan trọng trong Transformer:
- Gradient flow: \( \frac{\partial \text{output}}{\partial x} = \frac{\partial \text{sublayer}(x)}{\partial x} + I \). Hạng tử \( I \) (identity) đảm bảo gradient luôn có thành phần "chảy thẳng" qua block, không bị làm yếu bởi sublayer. Tránh vanishing gradient ngay cả khi stack rất sâu.
- Sublayer học residual (delta): thay vì học \( x \mapsto Z \) trực tiếp, sublayer chỉ cần học \( x \mapsto Z - x \) — phần thay đổi nhỏ. Học delta dễ hơn học hàm toàn phần.
Trong Pre-Norm block, "residual stream" là một khái niệm hay được nhắc đến trong interpretability (Anthropic, 2022) — đó chính là đường \( X \to Y \to Z \) không qua LayerNorm, nơi tất cả block đọc-ghi vào.
Position-wise
"Position-wise" là một thuật ngữ trong paper gốc dùng cho FFN: cùng một FFN áp lên từng vị trí một cách độc lập. Mỗi vector \( x_i \in \mathbb{R}^{d} \) đi qua \( W_1, W_2 \) tách biệt, không tham chiếu các vị trí khác.
Điều này khác hoàn toàn với MHA — nơi mỗi token query nhìn tất cả token khác. Sự phân vai rõ ràng:
- MHA: trộn thông tin giữa các token (token-mixing).
- FFN: biến đổi thông tin trong mỗi token (channel-mixing).
Mô hình "token-mix + channel-mix" này được trừu tượng hoá rộng hơn trong MLP-Mixer (Tolstikhin et al., 2021) và các kiến trúc khác.
Stack nhiều block
Vì input/output cùng shape, có thể stack \( N \) block:
\[ H_0 = X, \quad H_{\ell+1} = \text{Block}_\ell(H_\ell), \quad \ell = 0, \dots, N-1 \]
Mỗi block có tham số riêng. Số block điển hình theo size:
- BERT-base: 12 block.
- BERT-large: 24 block.
- GPT-2 small / medium / large / XL: 12 / 24 / 36 / 48.
- GPT-3 175B: 96.
- Llama 3: 32 (8B), 80 (70B), 126 (405B).
Có một quy luật scaling lỏng: số block ~ \( O(\sqrt{d}) \) hoặc tăng chậm hơn khi tăng total param. Chiều rộng \( d \) tăng nhanh hơn chiều sâu \( N \) — model 70B thường rộng hơn 8B chứ không sâu gấp 9 lần.
Param count một block
Giả sử Pre-Norm, MHA với \( d_k = d_v = d / h \), FFN với \( d_{\text{ff}} = 4d \), GELU activation, không tính bias:
- MHA: 4 ma trận \( W^Q, W^K, W^V, W^O \), mỗi cái \( d \times d \). Tổng: \( 4 d^2 \).
- FFN: \( W_1 \in d \times 4d \), \( W_2 \in 4d \times d \). Tổng: \( 8 d^2 \).
- LayerNorm (2 lần): \( 2 \times 2d = 4d \). Negligible khi \( d \) lớn.
Tổng: \( \boxed{\approx 12 d^2} \) tham số / block.
Với SwiGLU (3 ma trận FFN), tỉ lệ thực tế là ~\( 12 d^2 \) khi đã điều chỉnh \( d_{\text{ff}} \) như Bước 10.
Ví dụ Llama 3 8B (\( d = 4096 \), \( N = 32 \)):
\[ \text{params/block} \approx 12 \times 4096^2 \approx 2 \times 10^8 = 200\text{M} \]
\[ \text{total blocks} \approx 32 \times 200\text{M} = 6.4\text{B} \]
Cộng thêm embedding (\( V \times d = 128{,}000 \times 4096 \approx 524\text{M} \)) ra ~7B; embedding tying và một số tinh chỉnh đẩy con số lên ~8B. Phép ước lượng "đếm thô" này thường khớp với con số chính thức ±10%.
Decoder block vs Encoder-Decoder block
Cấu trúc block thay đổi nhẹ tuỳ kiến trúc tổng thể (Bài 14 sẽ deep-dive):
- Encoder block (BERT): self-attention bidirectional (không causal mask) + FFN. Mỗi token nhìn toàn bộ sequence.
- Decoder block (GPT, Llama): self-attention với causal mask + FFN. Token thứ \( i \) chỉ nhìn token \( \leq i \) (đã thảo luận ở Bài 9 và Bài 10).
- Encoder-Decoder block (T5, BART, original Transformer): decoder block có 3 sublayer thay vì 2:
- Causal self-attention (như decoder).
- Cross-attention: \( Q \) từ decoder, \( K, V \) từ output encoder. Cho decoder "nhìn" sang encoder.
- FFN.
LLM hiện đại đa phần là decoder-only — đơn giản hơn, cùng một block lặp lại. T5 và BART (encoder-decoder) vẫn dùng cho dịch máy và một số task seq2seq nhưng ít phổ biến trong chat / general assistant.
Biến thể 2024-2026
Một số biến thể block đáng nhớ ở thế hệ model hiện tại — chỉ điểm tên, sẽ chi tiết sau:
- Mixture of Experts (MoE): thay FFN duy nhất bằng \( E \) "expert FFN" + một router. Mỗi token được route tới \( k \) (thường \( k = 2 \)) expert. Tổng param tăng (Mixtral 8x7B có 47B param) nhưng compute mỗi forward chỉ tương đương model dense ~13B. Mixtral 8x7B (Mistral, 2023), GPT-4 (rumor), DeepSeek-V3 (671B param, 37B active, 2024).
- Parallel block (PaLM, Phi): chạy MHA và FFN song song với cùng input đã norm, rồi cộng kết quả thay vì xếp tuần tự. Tiết kiệm latency, tốt cho TPU. \[ Z = X + \text{MHA}(\text{LN}(X)) + \text{FFN}(\text{LN}(X)) \]
- No bias (Llama, PaLM): bỏ tham số bias trong mọi Linear. Giảm tham số nhẹ, tăng độ ổn định khi train ở scale lớn.
- QK-Norm (Henry et al., 2020; Chameleon 2024): thêm RMSNorm cho \( Q, K \) trước khi tính attention score. Giúp ổn định training với rất nhiều head.
Các biến thể này thường không thay đổi cấu trúc cơ bản (MHA + FFN + Norm + Residual) — chỉ thay đổi chi tiết bên trong từng thành phần.
PyTorch implementation
Implementation tối giản Pre-Norm block (PyTorch 2.x):
import torch
import torch.nn as nn
class TransformerBlock(nn.Module):
def __init__(self, d_model, num_heads, d_ff, dropout=0.0):
super().__init__()
self.ln1 = nn.LayerNorm(d_model)
self.attn = nn.MultiheadAttention(
d_model, num_heads, dropout=dropout, batch_first=True
)
self.ln2 = nn.LayerNorm(d_model)
self.ffn = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.GELU(),
nn.Linear(d_ff, d_model),
)
def forward(self, x, attn_mask=None):
# Sublayer 1: MHA với pre-norm + residual
h = self.ln1(x)
a, _ = self.attn(h, h, h, attn_mask=attn_mask, need_weights=False)
x = x + a
# Sublayer 2: FFN với pre-norm + residual
x = x + self.ffn(self.ln2(x))
return x
Một vài lưu ý implementation:
batch_first=Truecho shape \( (B, n, d) \) thay vì \( (n, B, d) \) — thuận hơn khi đọc code.need_weights=Falsebỏ tính attention weight để tiết kiệm; nếu cần visualize, bật True.attn_maskchính là causal mask (Bài 9) — tensor \( n \times n \) giá trị bool hoặc float \( -\infty \) ở vị trí cấm.- Phiên bản Llama thực tế thay
nn.LayerNormbằng RMSNorm,nn.MultiheadAttentionbằng custom MHA + RoPE + GQA, FFN bằng SwiGLU. Đây chỉ là khung tối thiểu để chạy.
Mini Transformer stack
Stack 4 block thành một mini Transformer encoder và chạy forward thử:
import torch
import torch.nn as nn
class MiniTransformer(nn.Module):
def __init__(self, d_model=64, num_heads=4, d_ff=256, num_layers=4):
super().__init__()
self.blocks = nn.ModuleList([
TransformerBlock(d_model, num_heads, d_ff)
for _ in range(num_layers)
])
self.ln_final = nn.LayerNorm(d_model)
def forward(self, x, attn_mask=None):
for block in self.blocks:
x = block(x, attn_mask=attn_mask)
return self.ln_final(x)
torch.manual_seed(0)
model = MiniTransformer(d_model=64, num_heads=4, d_ff=256, num_layers=4)
x = torch.randn(2, 10, 64) # batch=2, seq=10, d_model=64
out = model(x)
print(out.shape) # torch.Size([2, 10, 64])
n_params = sum(p.numel() for p in model.parameters())
print(f"Total params: {n_params:,}")
Output có cùng shape với input — vì stack block không đổi shape. ln_final ở cuối là quy ước phổ biến của Pre-Norm Transformer (GPT-2, Llama) để chuẩn hoá đầu ra trước khi đưa qua LM head.
Đếm tham số bằng tay với công thức \( 12 d^2 \): \( 12 \times 64^2 = 49{,}152 \) / block × 4 block = \( ~196 \)K. Kết quả thực tế từ numel() sẽ lớn hơn vì có thêm bias, LayerNorm — đối chiếu được.
Vị trí trong full Transformer
Kiến trúc GPT-style hoàn chỉnh (decoder-only):
Tokens [t1, t2, ..., tn]
│
↓ (Embedding + Positional Encoding)
│
↓ Block 1
↓ Block 2
↓ ...
↓ Block N
│
↓ Final LayerNorm
│
↓ Linear (LM head, d → vocab_size)
│
↓ Softmax
│
→ next-token probability
Bài 13 phụ trách phần "Block 1 ... Block N". Bài 6 đã làm phần embedding, Bài 12 phần positional encoding, Bài 9-11 đã làm chi tiết phần attention bên trong block. Bài 14 sẽ chỉ rõ ba dạng kiến trúc tổng thể (encoder-only, decoder-only, encoder-decoder) đều dùng block này nhưng theo cách khác nhau.
Bài tập
Bài 1 — Implement Pre-Norm block từ đầu. Không dùng nn.MultiheadAttention, viết MHA bằng tay dựa trên Bài 11 (4 linear projection + scaled dot-product + concat head). Test forward với input random shape \( (2, 8, 64) \), kiểm tra output cùng shape.
Bài 2 — Tính param count. Cho \( d = 512 \), \( d_{\text{ff}} = 2048 \), \( h = 8 \):
- Param của MHA (4 ma trận \( d \times d \) + bias).
- Param của FFN (2 ma trận, bao gồm bias).
- Param của 2 LayerNorm.
- Tổng. So với công thức \( 12 d^2 \).
Bài 3 — Post-Norm vs Pre-Norm. Viết hai class PostNormBlock và PreNormBlock. Stack mỗi loại 10 block, train trên một dataset toy (ví dụ học hàm \( f(x) = \sin(x) \) với input random embedding). So sánh loss curve và độ ổn định.
Bài 4 — Thay FFN GELU bằng SwiGLU. Implement class SwiGLU với 3 linear, dùng F.silu. So sánh số tham số khi giữ tổng tham số FFN tương đương GELU (gợi ý: giảm \( d_{\text{ff}} \) từ \( 4d \) xuống \( \frac{8}{3} d \)).
Bài 5 — RMSNorm. Implement RMSNorm theo công thức Bước 11, không dùng nn.LayerNorm. So sánh tốc độ với nn.LayerNorm bằng %timeit trên tensor \( (32, 1024, 512) \).
Gợi ý đáp án Bài 2
- MHA: \( 4 \times (512 \times 512 + 512) = 4 \times 262{,}656 \approx 1.05 \)M.
- FFN: \( (512 \times 2048 + 2048) + (2048 \times 512 + 512) \approx 2.10 \)M.
- LayerNorm: \( 2 \times 2 \times 512 = 2{,}048 \).
- Tổng: ~3.15M tham số / block.
- Công thức \( 12 d^2 = 12 \times 512^2 = 3.15 \)M — khớp.
Tóm tắt
- Transformer block = MHA + FFN + 2 LayerNorm + 2 residual. Input và output cùng shape \( (n, d) \) để stack được.
- Post-Norm (Vaswani 2017): LayerNorm sau sublayer + residual. Hoạt động tốt ở model nông, khó train sâu.
- Pre-Norm (modern): LayerNorm trước sublayer; residual chảy thẳng. Ổn định ở scale lớn, là default từ GPT-2 trở đi.
- FFN = 2 linear với activation giữa, hidden dim ~\( 4d \). Per-token, vai trò "channel-mixing" và memory. Chiếm ~\( \frac{2}{3} \) param block.
- Activation: ReLU (gốc) → GELU (BERT, GPT-2) → SwiGLU (Llama, PaLM, Mistral). SwiGLU có 3 linear, dùng gate.
- LayerNorm chuẩn hoá theo feature; RMSNorm bỏ mean và bias, nhanh hơn, là default cho LLM ≥ 1B.
- Residual: \( \text{output} = \text{sublayer}(x) + x \). Bảo toàn gradient, giúp stack sâu.
- Param count: ~\( 12 d^2 \) / block. Ví dụ Llama 3 8B (\( d = 4096 \)) ~200M / block × 32 block ~6.4B.
- Decoder block = self-attention causal + FFN. Encoder-decoder block thêm cross-attention.
- Biến thể modern: MoE (Mixtral, DeepSeek-V3), Parallel block (PaLM, Phi), no-bias (Llama), QK-Norm.
- Bài 14 sẽ so sánh ba dạng kiến trúc tổng thể: encoder-only (BERT), decoder-only (GPT), encoder-decoder (T5).
- Vaswani et al. (2017) - Attention Is All You Need
- Xiong et al. (2020) - On Layer Normalization in the Transformer Architecture
- Ba, Kiros, Hinton (2016) - Layer Normalization
- Zhang, Sennrich (2019) - Root Mean Square Layer Normalization
- Hendrycks, Gimpel (2016) - Gaussian Error Linear Units (GELU)
- Shazeer (2020) - GLU Variants Improve Transformer (SwiGLU)
- Geva et al. (2021) - Transformer Feed-Forward Layers Are Key-Value Memories
- He et al. (2015) - Deep Residual Learning for Image Recognition
- Chowdhery et al. (2022) - PaLM: Scaling Language Modeling with Pathways
- Jiang et al. (2024) - Mixtral of Experts
- DeepSeek-AI (2024) - DeepSeek-V3 Technical Report
- Grattafiori et al. (2024) - The Llama 3 Herd of Models
- Anthropic (2021) - A Mathematical Framework for Transformer Circuits
- PyTorch - nn.MultiheadAttention
- PyTorch - nn.LayerNorm
