Transformer
Kiến trúc Transformer
Câu "Tôi ăn phở bò ở quán quen" — từ "quán" liên quan nhất đến từ nào?
Liên tưởng 1 — Cuộc họp hội đồng quản trị: Trong một cuộc họp 20 người, mỗi người lắng nghe khác nhau. Khi CEO nói, phòng kế toán chú ý chi tiết số liệu, phòng nhân sự chú ý phần chính sách. Self-attention giống vậy: mỗi từ "lắng nghe" các từ khác với trọng số riêng, tuỳ vào vai trò của nó trong câu.
Liên tưởng 2 — Google search thời cổ điển vs hiện đại: Google cũ: bắt chính xác từ khoá. Google hiện đại: hiểu ý bạn — "quán cà phê yên tĩnh gần hồ" trả về đúng quán dù không có cụm từ này trong mô tả. Đây là "attention" ở cấp độ truy vấn — đo mức độ liên quan ngữ nghĩa, không phải trùng lặp từ.
Liên tưởng 3 — Người phiên dịch ở Hội nghị APEC: Khi dịch tiếng Việt sang tiếng Anh, người phiên dịch không dịch từng từ tuần tự — họ "nhìn lại" ngữ cảnh toàn câu trước khi chọn từ dịch. Transformer encoder-decoder mô phỏng đúng quá trình này: encoder hiểu toàn bộ câu nguồn, decoder dùng attention để tham chiếu phần liên quan khi sinh từ đích.
Liên tưởng 4 — Đọc hiểu tiếng Việt của học sinh giỏi: Khi đọc "Con mèo con của mẹ chạy mất rồi", bạn biết "con" đầu là danh từ (mèo con), "con" sau là tính từ sở hữu. Cách duy nhất để phân biệt là nhìn ngữ cảnh hai bên. Self-attention chính là cơ chế đó: mỗi từ được hiểu lại tuỳ theo các từ xung quanh — khác hoàn toàn với word embedding cố định Word2Vec.
Hình minh họa
Đây là Attention Mapcho câu tiếng Việt. Mỗi ô (i,j) cho biết từ ở hàng i "chú ý" bao nhiêu đến từ ở cột j. Nhấn vào ô để tăng attention — quan sát cách ngữ cảnh mỗi từ thay đổi.
Output cho từ "mèo" — ngữ cảnh nhận được từ mỗi từ:
Ma trận bạn vừa điều chỉnh chính là Attention Map — trái tim của kiến trúc Transformer!
Mỗi từ "hỏi" mọi từ khác: "Bạn quan trọng với tôi bao nhiêu?" Attention score càng cao = ảnh hưởng càng lớn đến nghĩa của từ đó.
Xây dựng kiến trúc Transformer
Input Tokens
Mỗi từ được tách thành token — đơn vị nhỏ nhất mà mô hình xử lý
RNN xử lý từ tuần tự (từ 1 → 2 → 3 → ...). Transformer xử lý thế nào?
Bạn huấn luyện Transformer cho câu tiếng Việt: "Tôi ăn phở ở quán." và "Ở quán, tôi ăn phở." Nếu bỏ Positional Encoding, mô hình xử lý hai câu này như thế nào?
Ngữ cảnh GPT-3 175B tham số, n=2048 tokens. Nếu bạn tăng context lên n=32000, độ phức tạp attention tăng bao nhiêu lần?
Giải thích
Transformer (Vaswani et al., 2017) là kiến trúc cách mạng hoàn toàn dựa trên self-attention — loại bỏ hoàn toàn cơ chế hồi quy (recurrence) và tích chập (convolution). Ba đổi mới then chốt:
Mỗi từ tạo ra 3 vector: Query (câu hỏi), Key (danh tính), Value(nội dung). Attention(Q,K,V) = softmax(QKᵀ / √d) × V. Cho phép mỗi từ "nhìn" trực tiếp đến mọi từ khác, bất kể khoảng cách. Xem chi tiết ở self-attention và phiên bản mở rộng multi-head attention.
Vì attention xử lý song song (không có thứ tự), cần thêm vector vị trí vào embedding. Dùng hàm sin/cos ở các tần số khác nhau: PE(pos,2i) = sin(pos/10000^(2i/d)). Xem sâu hơn tại positional encoding.
RNN xử lý n từ trong O(n) bước tuần tự. Transformer xử lý tất cả cùng lúc trong O(1) bước (mỗi bước tốn O(n²) cho attention), tận dụng tối đa GPU song song.
import numpy as np
def self_attention(X, Wq, Wk, Wv):
"""X: (n_tokens, d_model)"""
Q = X @ Wq # Query: mỗi từ hỏi gì?
K = X @ Wk # Key: mỗi từ có gì?
V = X @ Wv # Value: nội dung trả về
d_k = K.shape[-1]
scores = Q @ K.T / np.sqrt(d_k) # Attention scores
weights = softmax(scores, axis=-1) # Chuẩn hóa → xác suất
output = weights @ V # Tổng có trọng số
return output # Mỗi từ giờ chứa ngữ cảnh từ mọi từ khác
def softmax(x, axis=-1):
e = np.exp(x - np.max(x, axis=axis, keepdims=True))
return e / e.sum(axis=axis, keepdims=True)Vaswani et al. (Google Brain, 2017) — bài báo mở đầu kỷ nguyên Transformer. Tiêu đề nói lên tất cả: chỉ cần attention là đủ, không cần RNN hay CNN. Đến nay đã được trích dẫn hơn 100.000 lần và là nền tảng của GPT, BERT, LLaMA, Claude, và mọi LLM hiện đại.
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import Trainer, TrainingArguments
from datasets import load_dataset
import torch
# 1. PhoBERT — Transformer encoder-only cho tiếng Việt (VinAI)
MODEL_NAME = "vinai/phobert-base"
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=False)
model = AutoModelForSequenceClassification.from_pretrained(
MODEL_NAME, num_labels=3 # negative / neutral / positive
)
# 2. Load dataset UIT-VSFC (feedback sinh viên về giảng viên)
ds = load_dataset("uit-nlp/UIT_VSFC")
# 3. Pre-segment tiếng Việt trước khi token hoá (PhoBERT yêu cầu)
from pyvi import ViTokenizer
def preprocess(batch):
texts = [ViTokenizer.tokenize(t) for t in batch["sentence"]]
enc = tokenizer(texts, padding="max_length", truncation=True, max_length=128)
enc["labels"] = batch["sentiment"]
return enc
ds = ds.map(preprocess, batched=True)
# 4. Fine-tune — attention + FFN học từ dữ liệu cảm xúc có nhãn
args = TrainingArguments(output_dir="./phobert-vsfc", num_train_epochs=3,
per_device_train_batch_size=16, learning_rate=2e-5)
trainer = Trainer(model=model, args=args,
train_dataset=ds["train"], eval_dataset=ds["validation"])
trainer.train()
# 5. Suy luận trên câu mới
inputs = tokenizer("Giảng viên dạy rất hay và tâm huyết", return_tensors="pt")
with torch.no_grad():
logits = model(**inputs).logits
print(["negative", "neutral", "positive"][logits.argmax().item()])
# → positiveỨng dụng thực tế của Transformer trong các lĩnh vực:
- Dịch máy (Google Translate, DeepL): encoder-decoder Transformer đã thay thế hoàn toàn RNN/LSTM trong sản phẩm thương mại từ 2018. Chất lượng dịch Việt-Anh tăng đột phá — gần mức "human parity" cho các domain phổ biến.
- Chatbot & LLM (ChatGPT, Claude, Gemini): decoder-only Transformer với quy mô hàng trăm tỷ tham số. Đã định hình lại ngành AI từ cuối 2022.
- Thị giác máy tính (Vision Transformer — ViT): chia ảnh thành các patch nhỏ rồi xử lý như token. Hiện đã vượt CNN trong nhiều benchmark nhận dạng ảnh.
- Sinh học tính toán (AlphaFold 2): dùng attention để dự đoán cấu trúc 3D của protein từ chuỗi amino acid — đoạt giải Nobel Hoá học 2024.
- Âm thanh (Whisper, AudioLM): transcription và synthesis âm thanh đều được Transformer-ize. Whisper hỗ trợ tiếng Việt khá tốt.
- Mã nguồn (GitHub Copilot, Code Llama): sinh code từ prompt — hoạt động tốt trên cú pháp bất kỳ ngôn ngữ lập trình nào.
Tiến hoá của positional encoding: Bài báo gốc (Vaswani 2017) dùng sin/cos positional encoding cố định. Các phát triển sau:
- Learned position embedding (BERT): mỗi vị trí có một vector học được. Đơn giản nhưng không mở rộng được cho chuỗi dài hơn training.
- Relative position encoding (T5, Transformer-XL): dựa trên khoảng cách tương đối giữa các token thay vì vị trí tuyệt đối — tổng quát hoá tốt hơn.
- RoPE (Rotary Position Embedding — LLaMA, GPT-NeoX): xoay vector query/key theo góc phụ thuộc vị trí. Tốt cho cả trích xuất khoảng cách tuyệt đối và tương đối, mở rộng được nhờ kỹ thuật interpolation.
- ALiBi (Attention with Linear Biases): không thêm vector vị trí vào embedding, thay vào đó thêm bias tuyến tính vào attention score. Mở rộng tốt lên context 32K+ mà không retrain.
import numpy as np
def softmax(x, axis=-1):
x = x - x.max(axis=axis, keepdims=True)
e = np.exp(x)
return e / e.sum(axis=axis, keepdims=True)
def multi_head_attention(X, n_heads=8):
"""X: (seq_len, d_model) — input embeddings
Trả output cùng kích thước sau khi đã tích hợp ngữ cảnh."""
seq_len, d_model = X.shape
d_k = d_model // n_heads # kích thước mỗi head
# Các ma trận học được (ở đây random cho ví dụ)
rng = np.random.default_rng(0)
Wq = rng.normal(scale=0.02, size=(d_model, d_model))
Wk = rng.normal(scale=0.02, size=(d_model, d_model))
Wv = rng.normal(scale=0.02, size=(d_model, d_model))
Wo = rng.normal(scale=0.02, size=(d_model, d_model))
# Projection
Q = X @ Wq # (seq_len, d_model)
K = X @ Wk
V = X @ Wv
# Tách thành heads: (n_heads, seq_len, d_k)
Q = Q.reshape(seq_len, n_heads, d_k).transpose(1, 0, 2)
K = K.reshape(seq_len, n_heads, d_k).transpose(1, 0, 2)
V = V.reshape(seq_len, n_heads, d_k).transpose(1, 0, 2)
# Scaled dot-product attention cho mỗi head
scores = Q @ K.transpose(0, 2, 1) / np.sqrt(d_k) # (heads, seq, seq)
weights = softmax(scores, axis=-1)
heads = weights @ V # (heads, seq, d_k)
# Gộp heads và project ra
out = heads.transpose(1, 0, 2).reshape(seq_len, d_model)
return out @ Wo # (seq_len, d_model)
# Demo: 5 token, d_model=64
X = np.random.randn(5, 64)
out = multi_head_attention(X, n_heads=8)
print("Output shape:", out.shape) # (5, 64)Các loại mask quan trọng trong Transformer:
- Padding mask: khi batch có câu ngắn hơn, các vị trí padding không được tham gia vào attention. Mask đặt -∞ cho các cặp (i, padding_j) → softmax ra 0.
- Causal mask (triangular): trong decoder/GPT, token vị trí i chỉ nhìn được token 0..i (không nhìn tương lai). Đây là điều đảm bảo mô hình autoregressive — khi sinh text, không "gian lận" bằng cách nhìn token chưa có.
- Custom mask: một số biến thể (Longformer, BigBird) dùng pattern mask sparse để giảm complexity từ O(n²) xuống O(n·w).
Ba case study Transformer tại Việt Nam
1. VinAI — PhoBERT & ViT5
VinAI Research phát hành PhoBERT (2020) — BERT pretrain trên 20GB corpus tiếng Việt. Kết quả: state-of-the-art cho UIT-VSFC (cảm xúc), PhoNER-COVID19 (NER), ViQuAD (QA). ViT5 (2022) là encoder-decoder Transformer cho các task sinh text tiếng Việt — tóm tắt, dịch, trả lời dạng paragraph. Cả hai đều mở trên Hugging Face, là nền tảng cho 100+ ứng dụng downstream.
2. Zalo AI — GPT tiếng Việt quy mô công nghiệp
Zalo triển khai Transformer cho: phát hiện nội dung vi phạm, dịch tự động trong Zalo OA, gợi ý tin nhắn thông minh, và chatbot CSKH. Đội VinBigData cũng phát hành PhoGPT — LLM decoder-only tiếng Việt với 7.5B tham số, được train trên 300GB dữ liệu.
3. Bộ Y tế & các bệnh viện — AI chẩn đoán ảnh y khoa
Vision Transformer (ViT) được dùng để phân tích ảnh X-quang phổi, CT, siêu âm. Ưu điểm so với CNN: nắm bắt tốt hơn các mẫu toàn cục trên ảnh (lesion phân tán), giải thích được bằng attention map. VinLab và Bệnh viện Bạch Mai là hai trong những nơi đầu tiên áp dụng ViT trong chẩn đoán thực tế tại Việt Nam.
- Self-Attention cho mỗi từ nhìn trực tiếp đến mọi từ khác — nắm bắt quan hệ xa tốt hơn RNN.
- Xử lý song song toàn bộ câu cùng lúc — nhanh hơn RNN nhiều lần trên GPU.
- Positional Encoding thêm thông tin vị trí, vì attention không phân biệt thứ tự.
- Kiến trúc gồm: Embedding → (Self-Attention + FFN + Add&Norm) × N lớp → Output.
- Ba biến thể: Encoder-only (BERT), Decoder-only (GPT), Encoder-Decoder (T5) — nền tảng mọi LLM hiện đại.
- Attention là O(n²) — long-context cần Flash Attention / sparse / SSM; tiếng Việt có PhoBERT, ViT5, UIT-VSFC làm nền.
Kiểm tra hiểu biết
Trong self-attention, mỗi từ tạo ra ba vector. Chúng là gì?