🍐 nguyen
Overview

Một chút về Transformers (Phần 2): Transformers

June 20, 2025
11 min read
index

Nếu các bạn chưa đọc phần 1 thì hãy đọc qua nó nhé (đọc sơ thôi cũng được), phần 1 ở đây

1. Transformers (Optimus biến hình)

Cuối cùng, ta sẽ đến ý tưởng thay đổi hoàn toàn AI nói chung và ngành NLP nói riêng (thay đổi cả thế giới luôn, kể cả mình), đó chính là kiến trúc Transformers []. Ý tưởng ở đây là thay vì dùng cơ chế Attention như một add-on cho Encoder-Decoder model, sao ta không sử dụng luôn cơ chế Attention cho mô hình và quăng RNN vào sọt rác (không có ý gì đâu đấy). Và cơ chế chính của Transformers chính là Self-Attention.

Ngoài ra, việc loại bỏ RNN giải quyết được hai vấn đề lớn:

  1. Tốc độ training: RNN phải xử lý tuần tự, không thể song song hóa. Mô hình chỉ dựa trên Attention có thể xử lý tất cả các từ trong câu cùng một lúc, nhanh hơn rất nhiều.
  2. Vanishing Gradients: Vấn đề “trí nhớ ngắn hạn” của RNN trên các chuỗi dài được giải quyết hoàn toàn.
Transformers
Kiến trúc của mô hình Transformers, bao gồm 3 phần: Embedding Layer, các Transformers Block và Unembedding Layer. Kiến trúc phía trên còn được gọi Decoder-Only Transformesr, bởi vì trong bài báo gốc, Transformers bao gồm 2 phần là Encoder và Decoder. Các Decoder-Only Transformers còn nổi bật bởi các tính chất sau gồm Autoregressive (tức là tác vụ chính sẽ là dùng các từ trước đó dự đoán từ tiếp theo) và Masked Attention.

2. Self-Attention: Một câu tự “nhìn lại” chính mình

Thay vì Attention giữa Decoder và Encoder, Self-Attention cho phép các từ trong cùng một câu tương tác với nhau. Để hiểu được nghĩa của từ “nó” trong câu “Con mèo nằm trên tấm thảm vì đã mệt”, cơ chế self-attention của từ “nó” sẽ học cách “chú ý” vào các từ trước và từ “mèo” sẽ được chú ý nhiều nhất (có score cao nhất). Đây là cách mà Transformers xây dựng biểu diễn (representation) cho mỗi từ trong câu (một ứng dụng gián tiếp của distributional hypothesis).

Một cách formal hơn, Self-attention sẽ lấy input là xi\mathbf{x}_i tương ứng với input token tại vị trí ii (hay bước thời gian ii), một context gồm i1i-1 từ trước đó, tương ứng với x1,...,xi1\mathbf{x}_1, ...,\mathbf{x}_{i-1} và sinh ra output ai\mathbf{a}_i. Vì vậy với một câu gồm x1,...,xNx_1, ..., x_N, đưa qua lớp self-attention, ta sẽ có các output là a1,..,aNa_1, .., a_N.

Tương tự như ở Encoder-Decoder, ở mức cơ bản nhất, giá trị attention chính là weighted sum của các context vector (các vector của từ trước đó) và quan trọng nhất đó là tính được weight αij\alpha_{ij}:

Simplified version:ai=jiαijxj\text{Simplified version:} \hspace{5pt} \mathbf{a}_{i} = \sum_{j \leq i} \alpha_{ij}\mathbf{x}_{j}

Tiếp theo, làm sao để tính được weight αij\alpha_{ij}, ta sẽ dùng hàm score gọi là score\text{score}, hàm này sẽ cho biết độ liên quan hay độ tương đồng giữa token ii hiện tại với các token trước jj, cách dễ nhất là dùng hàm dot-product làm score hay còn gọi là dot-product attention:

score(xi,xj)=xixjαij=exp(score(xi,xj))kiexp(score(xi,xk))\begin{aligned} \text{score}(\mathbf{x}_{i}, \mathbf{x}_{j}) &= \mathbf{x}_{i} \cdot \mathbf{x_{j}} \\ \alpha_{ij} &= \frac{\exp(\text{score}(\mathbf{x}_{i}, \mathbf{x}_{j}))}{\sum_{k \leq i} \exp(\text{score}(\mathbf{x}_{i}, \mathbf{x}_{k}))} \end{aligned}

Việc tính attention bao gồm luôn tính cả score giữa cả token hiện tại ii và chính nó.

3. Attention Head

Ở transformer, ta sẽ gọi giá trị của Attention mechanism là head và gọi chung là attention head. Trước tiên, thay vì sử dụng thẳng input xi\mathbf{x}_{i}, input sẽ được “phân chia” thành 3 role là Query, KeyValue (tương tự, các từ trước đó hay context word xj\mathbf{x}_j cũng được chia thành 3 role).

qi=xiWQki=xiWKvi=xiWV\begin{aligned} \mathbf{q}_{i} &= \mathbf{x}_{i}\mathbf{W}^Q \\ \mathbf{k}_{i} &= \mathbf{x}_{i}\mathbf{W}^K \\ \mathbf{v}_{i} &= \mathbf{x}_{i} \mathbf{W}^V \\ \end{aligned}

Trong đó WQ,WK\mathbf{W}^Q, \mathbf{W}^KWV\mathbf{W}^V là ba ma trận tham số tương ứng của 3 role là Query, Key và Value. Còn qi,ki\mathbf{q}_i, \mathbf{k}_ivi\mathbf{v}_i là các vector embedding tương ứng với 3 role. Ngoài ra ta còn một ma trận dùng để đưa output của attention sang output cuối cùng là WO\mathbf{W}^O.

Thêm 3 gia vị Query, Key, Value vào self-attention đơn giản phía trên (tuy nhiên ta thấy dot-product giữa query và key có thể rất lớn do đó ta sẽ scale với factor là nghịch đảo căn của dkd_k, với dkd_k là chiều của vector key, do đó ta còn gọi là Scaled Dot Product Attention):

score(qj,ki)=qjkidkαij=exp(score(qj,ki))kexp(score(qk,ki))jiheadi=jiαijvjai=headiWO\begin{aligned} \text{score}(\mathbf{q}_{j}, \mathbf{k}_{i}) &= \frac{{\mathbf{q}_{j} \cdot \mathbf{k}_{i}}}{\sqrt{ d_{k} }} \\ \alpha_{ij} &= \frac{\exp(\text{score}(\mathbf{q}_{j}, \mathbf{k}_{i}))}{\sum_{k} \exp(\text{score}(\mathbf{q}_{k}, \mathbf{k}_{i}))} \hspace{5pt} \forall j \leq i \\ \text{\textbf{head}}_{i} &= \sum_{j \leq i} \alpha_{ij} \mathbf{v}_{j} \\ \mathbf{a}_{i} &= \textbf{head}_{i} \mathbf{W}^O \end{aligned}
Important (Vai trò của Query, Key, và Value: Một ví dụ)

Để hiểu rõ vai trò của Q,K,VQ, K, V, hãy dùng một ví dụ như sau: bạn là một nhà nghiên cứu (token hiện tại) cần thu thập thông tin.

  • Query (Q) - Câu hỏi bạn đặt ra:
    Bạn có một chủ đề nghiên cứu cụ thể (ví dụ: “ảnh hưởng của AI đến kinh tế”). Bạn viết nó ra một tấm thẻ để đi tìm kiếm. Vector Query chính là “câu hỏi” mà token hiện tại đặt ra cho tất cả các token khác trong chuỗi.
  • Key (K) - Nhãn của thông tin:
    Mỗi cuốn sách trong thư viện (mỗi token khác) đều có một cái nhãn (title) trên gáy sách tóm tắt nội dung của nó (ví dụ: “Lịch sử AI”, “Kinh tế học vĩ mô”). Vector Key của một token đóng vai trò như một “nhãn dán”, quảng cáo về loại thông tin mà nó chứa.
  • Value (V) - Nội dung thực sự:
    Nội dung chi tiết bên trong mỗi cuốn sách chính là Value. Đây là thông tin thực chất, đầy đủ mà token đó có thể cung cấp.

Quá trình Attention:

  1. Tìm kiếm: Lấy Query (chủ đề cần nghiên cứu) và so sánh nó với từng Key (nhãn của mỗi cuốn sách) để xem cuốn nào liên quan nhất. Phép so sánh này (dot product) tạo ra attention score.
  2. Tổng hợp: Dựa trên điểm số, lấy một chút nội dung từ mỗi cuốn sách hay Value. Cuốn nào càng liên quan, ta càng lấy nhiều nội dung hơn. Output cuối cùng là tổng hợp có trọng số của tất cả các Value.

Chiều của input xi\mathbf{x}_i cùng chiều với output ai\mathbf{a}_i[1×d][1 \times d] và ta gọi ddmodel dimension. Ta sẽ có chiều với query bằng nhau tức là dq=dkd_q = d_k và từ giờ ta sẽ sử dụng dkd_k cho cả query với key, khi ấy WQ\mathbf{W}^QWK\mathbf{W}^K sẽ có chiều là [d×dk][d \times d_k]. Còn WV\mathbf{W}^V sẽ có chiều là [d×dv][d \times d_v] với dvd_v là chiều của value. Vậy, chiều của attention-head headi\textbf{head}_i sẽ là [1×dv][1 \times d_v]. Để có được chiều của output là [1×d][1 \times d], ta cần ma trận output WO\mathbf{W}^O có chiều là [dv×d][d_v \times d]. Trong bài báo gốc [], dd là 512 và dkd_k cùng dvd_v là 64.

4. Multi-Head Attention, siêu sức mạnh của Transformers

Ở phía trên ta chỉ dùng single attention head thế nhưng trong Transformers Block thì ta sẽ dùng multi-head attention, tức là sẽ gồm nhiều attention head được đặt song song với nhau, mỗi attention head sẽ có bộ tham số của riêng mình.

Vậy attention head thứ ii sẽ có WiQ,WiK\mathbf{W}^Q_i, \mathbf{W}^K_iWiV\mathbf{W}^V_i. Ta sẽ cho input x\mathbf{x} đi ta qua từng attention head để có được output headi\textbf{head}_iconcat các attention head lại để có được output cuối cùng, sau đó đưa output đó sang ma trận output (WO\mathbf{W}^O) để có được output cuối cùng.

Việc sử dụng nhiều attention-head mục đích là ta muốn chú ý (hay học) được nhiều relationship giữa từ hiện tại với context, ví dụ như các linguistic relationship hay semantic relationship, …

qic=xiWcQ, kic=xiWcK, vic=xiWcVscorec(qjc,kic)=qjckicdkαijc=exp(scorec(qjc,kic))kexp(scorec(qkc,kic))headic=jiαijcvjcai=(headi1headih)WOMultiHeadAttention[xi,[x1,,xn]]=ai\begin{aligned} \mathbf{q}^c_{i} = \mathbf{x}_{i} \mathbf{W}^Q_{c}, \ \mathbf{k}_{i}^c &= \mathbf{x}_{i}\mathbf{W}^K_{c}, \ \mathbf{v}_{i}^c = \mathbf{x}_{i}\mathbf{W}^V_{c} \\ \text{score}^{c}(\mathbf{q}_{j}^c, \mathbf{k}_{i}^c) &= \frac{{\mathbf{q}_{j}^c \cdot \mathbf{k}_{i}^c}}{\sqrt{ d_{k} }} \\ \alpha_{ij}^{c} &= \frac{\exp(\text{score}^{c}(\mathbf{q}^c_{j}, \mathbf{k}^c_{i}))}{\sum_{k} \exp(\text{score}^{c}(\mathbf{q}^c_{k}, \mathbf{k}^c_{i}))} \\ \textbf{head}_{i}^c &= \sum_{j \leq i} \alpha_{ij}^c \mathbf{v}_{j}^c \\ \mathbf{a}_{i} &= (\mathbf{head}_{i}^1 \oplus \dots \oplus \mathbf{head}^h_{i})\mathbf{W}^O \\ \text{MultiHeadAttention}[\mathbf{x}_{i}, [\mathbf{x_{1}, \dots, \mathbf{x}_{n}}]] &= \mathbf{a}_{i} \end{aligned}

Trong bài báo gốc, số lượng head là 88.

Trong đó qic\mathbf{q}_i^c là vector query của input time ii tại head thứ cc, trong đó vector query sẽ có chiều là dkd_k, tương tự với kic\mathbf{k}_i^c, còn vic\mathbf{v}_i^c cũng tương tự nhưng có chiều là dvd_v. Trong đó input x\mathbf{x} sẽ có chiều là [1×d][1 \times d] với dd là model dimension. Ma trận WO\mathbf{W}^O sẽ có chiều là [hdv×d][hd_{v} \times d] với hh là tổng số attention head và \oplus nghĩa là concat vector.

5. Transformers Block

Transformers Block
Transformers Block

Một Transformers Block đầy đủ sẽ bao gồm các component sau:

  • Một MultiHead Attention, cũng có thể gọi là Attention Layer.
  • Một Feedforward Layer (bao gồm một MLP), cũng còn được gọi là MLP Layer.
  • Các Layer Normalization sau mỗi component phía trên (ở hình trên, ta dùng prenorm do đó layer norm nằm trước, thật ra trong bài báo gốc, họ dùng postnorm, tức là các layer norm nằm sau các component).
  • Residual stream (dựa trên ý tưởng của residual connection của ResNet). Sau khi giá trị input qua mỗi component, nó sẽ được cộng lại với chính nó xi=xi+component(xi)x_i = x_i + \text{component}(x_i).

Residual Stream là một trong những concept quan trọng nhất của Mechanistic Interpretability và sẽ được nói đến rất nhiều ở phần 3.

Feedforward layer:
Là một mạng fully-connected 2 layer, activation là ReLU (hoặc là GeLU trong các mô hình mới hơn) và hidden dimension là dffd_{ff} (trong bài báo gốc dff=2048d_{ff} = 2048) và chiều của input là d=512d = 512 (model dimension).

FFN(xi)=ReLU(xiW1+b1)W2+b2FFN(\mathbf{x}_{i}) = \text{ReLU}(\mathbf{x}_{i}\mathbf{W}_{1} + \mathbf{b}_{1})\mathbf{W}_{2} + \mathbf{b}_{2}

Layer Norm:

  • Tại mỗi component của Transformers Block, ta đều có LayerNorm (đứng trước hoặc sau, theo bài báo gốc là sau). LayerNorm sẽ normalize các giá trị của input dùng để improve training performance đồng thời giữ giá trị của hidden layer trong khoảng (tránh quá nhỏ hoặc quá to).
  • LayerNorm là một variation của z-score và apply trên một single vector trong hidden layer (chứ không phải toàn bộ transformer block layer). Đầu tiên ta tính mean μ\mathbf{\mu}σ\sigma của từng phần tử trong vector (xem vector như một phân phối), xét một vector input x={x1,...,xd}\mathbf{x} = \{x_1, ..., x_d\}, ta có:
μ=1di=1dxiσ=1di=1d(xiμ)2\begin{aligned} \mu &= \frac{1}{d}\sum_{i=1}^d x_{i} \\ \sigma &= \sqrt{\frac{1}{d}\sum_{i=1}^d (x_{i} - \mu)^2} \\ \end{aligned}
  • Sau đó, vector normalize của vector gốc (chú ý, μ\muσ\sigma là scalar, do đó ta sẽ trừ từng phần tử cho μ\muchia từng phần tử cho σ\sigma) sẽ là:
x^=(xμ)σ\hat{\mathbf{x}} = \frac{(\mathbf{x} - \mu)}{\sigma}
  • Cuối cùng LayerNorm được tính như sau (γ\gammaβ\beta là hai tham số học được):
LayerNorm(x)=γx^+β=γ(xμ)σ+β\text{LayerNorm}(\mathbf{x}) = \gamma \hat{\mathbf{x}} + \beta = \gamma\frac{ (\mathbf{x} - \mu)}{\sigma} + \beta

Kết hợp lại với nhau:

Xét vector input ti\mathbf{t}_{i} có chiều là [1×d][1 \times d] khi đó:

  • Attention Component:
ti1=LayerNorm(xi)ti2=MultiHeadAttention(ti1,[t11,,tn1])ti3=ti2+xi\begin{aligned} \mathbf{t}^1_{i} &= \text{LayerNorm}(\mathbf{x}_{i}) \\ \mathbf{t}^2_{i} &= \text{MultiHeadAttention}(\mathbf{t}^1_{i}, [\mathbf{t}^1_{1}, \dots, \mathbf{t}^1_{n}]) \\ \mathbf{t}^3_{i} &= t^2_{i} + \mathbf{x}_{i} \end{aligned}
  • Feedforward Component:
ti4=LayerNorm(ti3)ti5=FFN(ti4)hi=ti5+ti3\begin{aligned} \mathbf{t}^4_{i} &= \text{LayerNorm}(\mathbf{t}^3_{i}) \\ \mathbf{t}^5_{i} &= FFN(\mathbf{t}^4_{i}) \\ \mathbf{h}_{i} &= \mathbf{t}^5_{i} + \mathbf{t}^3_{i} \end{aligned}

6. Song song hoá Transformers

Thay vì đưa từng token xi\mathbf{x}_i có chiều là [1×d][1 \times d], ta đưa input là cả ma trận input X\mathbf{X} gồm NN token và có chiều là [N×d][N \times d]. Các LLM thường có NN từ 1000 đến 32000, có những LLM có thể handle cao hơn như 128k hay 1M (Gemini) bằng kỹ thuật nâng cao hơn [].

Song song hoá Attention:

Q\mathbf{Q} là ma trận với dòng là các query vector và có size là [N×dk][N \times d_k], tương tự ma trận K\mathbf{K} có dòng là các key vector, V\mathbf{V} có dòng là các value vector, với size tương ứng là [N×dk][N \times d_k][N×dv][N \times d_v].

Q=XWQ,K=XWK,V=XWV\mathbf{Q} = \mathbf{X}\mathbf{W}^Q, \qquad \mathbf{K} = \mathbf{X}\mathbf{W}^K, \qquad \mathbf{V} = \mathbf{X}\mathbf{W}^V

Khi đó để tính tích trong của từng query và key vector ta chỉ cần tính QKT\mathbf{Q}\mathbf{K}^T.

Sau khi đã có QKT\mathbf{Q}\mathbf{K}^T ta chỉ cần scale ma trận (scale từng phần tử ma trận) và tính softmax cho từng dòng trong ma trận:

head=softmax(mask(QKTdk))V\begin{aligned} \textbf{head} = \text{softmax}\left( \text{mask}\left( \frac{\mathbf{Q}\mathbf{K}^T}{\sqrt{ d_{k} }} \right) \right)\mathbf{V} \end{aligned}

Thế nhưng điều đặc biệt là ta có thêm hàm mask\text{mask}, có thể thấy phép nhân ma trận QKT\mathbf{Q}\mathbf{K}^T tính luôn tích vô hướng giữa một query hiện tại với các key phía sau nó và điều này đi ngược lại ý tưởng của Transformer khi tính attention dựa trên query và các key (hay từ) đứng trước nó. Vì vậy ta sẽ thực hiện mask những phần tử “phía sau” này đi.

Ta có thể dùng mask thông qua một ma trận tam giác trên với Mij=,j<iM_{ij} = - \infty, \forall j <i (khi ta để -\infty, softmax sẽ tự đưa các giá trị ấy về 00). Do việc “mask” này, ta còn gọi nó là Masked Self Attention hay Causal Attention.

Parallel Attention
Cách tính Attention Layer song song (nguồn: chương 9 của https://web.stanford.edu/~jurafsky/slp3/)

Hình như vẫn còn thiếu lớp Embedding và Unembedding nhỉ, thật ra những lớp này rất quan trọng nhưng mình sẽ để các bạn tự tìm hiểu, thật ra mình cũng viết hết nổi rồi hẹ hẹ.

References

  1. Speech and Language Processing: An Introduction to Natural Language Processing, Computational Linguistics, and Speech Recognition with Language Models, Daniel Jurafsky and James H. Martin
    2025
    https://web.stanford.edu/~jurafsky/slp3/
  2. Mechanistic Interpretability for AI Safety -- A Review, Leonard Bereska and Efstratios Gavves
    2024
    https://arxiv.org/abs/2404.14082
  3. Distributed representations, simple recurrent networks, and grammatical structure, Elman, Jeffrey L.
    Machine Learning, 1991
    https://doi.org/10.1007/BF00114844
  4. Effective Approaches to Attention-based Neural Machine Translation, Minh-Thang Luong and Hieu Pham and Christopher D. Manning
    2015
    https://arxiv.org/abs/1508.04025
  5. Neural Machine Translation by Jointly Learning to Align and Translate, Dzmitry Bahdanau and Kyunghyun Cho and Yoshua Bengio
    2016
    https://arxiv.org/abs/1409.0473
  6. Attention Is All You Need, Ashish Vaswani and Noam Shazeer and Niki Parmar and Jakob Uszkoreit and Llion Jones and Aidan N. Gomez and Lukasz Kaiser and Illia Polosukhin
    2023
    https://arxiv.org/abs/1706.03762
  7. Advancing Transformer Architecture in Long-Context Large Language Models: A Comprehensive Survey, Yunpeng Huang and Jingwei Xu and Junyu Lai and Zixu Jiang and Taolue Chen and Zenan Li and Yuan Yao and Xiaoxing Ma and Lijuan Yang and Hao Chen and Shupeng Li and Penghao Zhao
    2024
    https://arxiv.org/abs/2311.12351
  8. A Mathematical Framework for Transformer Circuits, Elhage, Nelson and Nanda, Neel and Olsson, Catherine and Henighan, Tom and Joseph, Nicholas and Mann, Ben and Askell, Amanda and Bai, Yuntao and Chen, Anna and Conerly, Tom and DasSarma, Nova and Drain, Dawn and Ganguli, Deep and Hatfield-Dodds, Zac and Hernandez, Danny and Jones, Andy and Kernion, Jackson and Lovitt, Liane and Ndousse, Kamal and Amodei, Dario and Brown, Tom and Clark, Jack and Kaplan, Jared and McCandlish, Sam and Olah, Chris
    Transformer Circuits Thread, 2021
    https://transformer-circuits.pub/2021/framework
  9. Zoom In: An Introduction to Circuits, Olah, Chris and Cammarata, Nick and Schubert, Ludwig and Goh, Gabriel and Petrov, Michael and Carter, Shan
    Distill, 2020
    https://distill.pub/2020/circuits/zoom-in