Scaling Laws
Định luật tỷ lệ
GPT-3 có 175 tỷ tham số. GPT-4 có ~1.700 tỷ (gấp 10 lần). GPT-4 giỏi hơn GPT-3 bao nhiêu lần (theo loss)?
Hãy tưởng tượng bạn có một ngân sách xây nhà. Bạn có thể dồn tiền vào diện tích (rộng nhưng sơ sài), hoặc vào nội thất (nhỏ nhưng sang trọng). Với cùng ngân sách, luôn có một điểm cân bằng cho chất lượng sống cao nhất.
Trong LLM, "diện tích" là số tham số N, "nội thất" là lượng dữ liệu D, và "ngân sách" là compute C ≈ 6·N·D. Chinchilla (Hoffmann et al., 2022) đã tìm ra điểm cân bằng đó: D* ≈ 20 · N*. Dưới đây là biểu đồ log-log cho bạn thấy các model thực tế nằm ở đâu so với đường compute-optimal.
Hình minh họa
Tự chọn compute budget của bạn
Kéo thanh trượt theo log10(C) — từ 10^20 FLOPs (model đồ chơi) đến 10^26 FLOPs (siêu cluster). Xem N*, D* tối ưu.
Model lịch sử gần nhất: GPT-3 (2020)
Ratio D/N ≈ 1.7 — quá ít data so với model lớn.
Tỷ lệ D*/N* = 20.0 (Chinchilla rule: ~20)
Nếu bạn chọn D/N < 20 → model đói data (undertrained). Nếu D/N > 20 → overtrained — vẫn ổn nếu bạn tối ưu cho inference.
Hiệu suất của LLM không phải là nghệ thuật huyền bí — nó tuân theo một công thức toán học mà bạn có thể viết lên bảng. Biết công thức này, các lab AI có thể tính trước loss cho model trị giá nhiều triệu đô trước khi bỏ một đồng đầu tư.
Chinchilla đã đảo ngược niềm tin "càng to càng tốt": với cùng ngân sách compute, model 70B train trên 1.4T token đánh bại model 280B train trên 300B token. Cân bằng > to đùng.
Chinchilla (70B tham số, 1.4T token) vs GPT-3 (175B tham số, 300B token). Ai có loss thấp hơn trên benchmark chung?
Meta train LLaMA 3 8B trên 15T token — tỷ lệ D/N ~1875, cao hơn nhiều mức Chinchilla 20. Tại sao họ lại 'lãng phí' compute như vậy?
Giải thích
Scaling laws là tập hợp các quy luật toán học, xác định bằng thực nghiệm, mô tả cách loss của LLM thay đổi khi ta thay đổi số tham số N, lượng dữ liệu D, và compute C. Kết quả chính: loss giảm theo power law (lũy thừa âm) đối với cả N và D, có một thành phần irreducible loss không thể giảm được.
Công thức Chinchilla (Hoffmann et al., 2022):
Với các hằng số thực nghiệm: E ≈ 1.69, A ≈ 406.4, B ≈ 410.7, α ≈ 0.34, β ≈ 0.28. Ba số hạng có ý nghĩa riêng biệt:
- E — irreducible loss: giới hạn dưới lý thuyết, tương ứng entropy Shannon của văn bản tự nhiên. Dù có vô hạn N và D, bạn không giảm loss xuống dưới E được.
- A/N^α — model-size term: giảm khi tăng N. Với α ≈ 0.34, gấp đôi N giảm term này ~22%.
- B/D^β — data-size term: giảm khi tăng D. Với β ≈ 0.28, gấp đôi D giảm term này ~18%.
Compute budget xấp xỉ bằng FLOPs — hằng số 6 đến từ: 2 FLOPs/param cho forward × 3 (forward + backward qua Transformer tiêu chuẩn). Đây là công thức giúp ta biến bài toán tối ưu L(N, D) với ràng buộc C thành một bài toán Lagrange đơn giản.
Kaplan et al. (OpenAI) phát hiện ra scaling laws trước Chinchilla 2 năm. Công thức đơn giản hơn vì chỉ xét N, giả định D luôn dồi dào. Tuy nhiên kết luận của Kaplan — "tăng N quan trọng hơn tăng D" — đã bị Chinchilla chứng minh là sai ở chế độ compute hữu hạn.
Với α ≈ 0.34 và β ≈ 0.28, hai số mũ gần bằng nhau → cả N* và D* đều ∝ C^0.5. Hệ số tỷ lệ cho ra ratio D*/N* ≈ 20 — đây chính là "Chinchilla rule" được lặp lại khắp mọi bài blog về LLM.
Cách các lab AI xác định các hằng số E, A, B, α, β: họ train hàng chục model với (N, D) khác nhau, đo loss, và fit least-squares vào công thức. Dưới đây là code thực tế:
"""
Fit hàm L(N, D) = E + A/N^alpha + B/D^beta vào các điểm thực nghiệm.
Dữ liệu thực tế thường có dạng:
runs = [
(N_params_in_billions, D_tokens_in_billions, final_loss),
...
]
Mỗi điểm là một lần huấn luyện riêng biệt — rất tốn kém, nên các lab
thường chỉ fit với 30–100 điểm trải trên vài quy mô.
"""
import numpy as np
from scipy.optimize import curve_fit
def chinchilla_loss(X, E, A, B, alpha, beta):
"""
X: mảng (2, n) với hàng đầu là N (tham số), hàng sau là D (tokens).
Trả về loss dự đoán.
"""
N, D = X
return E + A / np.power(N, alpha) + B / np.power(D, beta)
def fit_scaling_law(runs):
"""
runs: list of (N_in_billions, D_in_billions, loss)
Trả về các hệ số đã fit.
"""
# Chuyển về đơn vị tuyệt đối (N và D tính theo 'đơn vị' — ở đây là B).
N_arr = np.array([r[0] for r in runs], dtype=float)
D_arr = np.array([r[1] for r in runs], dtype=float)
L_arr = np.array([r[2] for r in runs], dtype=float)
X = np.vstack([N_arr, D_arr])
# Khởi tạo gần đúng (lấy từ Chinchilla paper)
p0 = [1.69, 406.4, 410.7, 0.34, 0.28]
# curve_fit dùng Levenberg-Marquardt theo mặc định — ổn với
# bài toán này vì Jacobian tính được analytical.
popt, pcov = curve_fit(
chinchilla_loss, X, L_arr, p0=p0, maxfev=10000
)
E, A, B, alpha, beta = popt
return {
"E": E, "A": A, "B": B, "alpha": alpha, "beta": beta,
"covariance": pcov,
}
def optimal_N_D_for_compute(C_flops, alpha=0.34, beta=0.28):
"""
Given compute budget C (FLOPs), return compute-optimal N, D.
Giả sử C ≈ 6 * N * D.
"""
# Tỷ lệ tối ưu: N ∝ C^(beta/(alpha+beta)), D ∝ C^(alpha/(alpha+beta))
ratio_N = beta / (alpha + beta)
ratio_D = alpha / (alpha + beta)
# Chuẩn hóa sao cho N * D = C / 6
# → dùng hệ số từ paper; ở đây rút gọn bằng sqrt khi alpha ≈ beta.
N = (C_flops / 6) ** ratio_N
D = (C_flops / 6) ** ratio_D
# Áp rule thực nghiệm D ≈ 20 * N
return N, D
if __name__ == "__main__":
# Ví dụ giả lập 5 điểm dữ liệu
runs_demo = [
(1, 5, 3.10), # model nhỏ, data ít
(1, 50, 2.60), # model nhỏ, nhiều data
(10, 50, 2.30),
(10, 500, 1.95),
(70, 1400, 1.75), # giống Chinchilla
]
fit = fit_scaling_law(runs_demo)
print("Fitted coefficients:", fit)
# Dự đoán loss cho model mới
N_new, D_new = 100, 2000 # 100B params, 2T tokens
pred = chinchilla_loss(
np.array([[N_new], [D_new]]),
fit["E"], fit["A"], fit["B"], fit["alpha"], fit["beta"],
)
print(f"Predicted loss for 100B/2T: {pred[0]:.3f}")
Khi đã fit được L(N, D), ta có thể phân bổ compute budget một cách tối ưu. Dưới đây là hàm chọn N*, D* để loss thấp nhất với ràng buộc C:
"""
Cho compute budget C (FLOPs) và ràng buộc C = 6·N·D,
tìm (N*, D*) cực tiểu L(N, D) = E + A/N^alpha + B/D^beta.
Dùng Lagrange multiplier:
∂L/∂N + λ · 6 · D = 0
∂L/∂D + λ · 6 · N = 0
Giải ra: A·alpha / N^(alpha+1) = B·beta / D^(beta+1) · (N/D)
→ tỷ lệ D/N phụ thuộc (A, B, alpha, beta) nhưng gần 20 với
hằng số Chinchilla.
"""
import numpy as np
from scipy.optimize import minimize
# Hằng số Chinchilla
E, A, B = 1.69, 406.4, 410.7
alpha, beta = 0.34, 0.28
def loss_at(N, D):
return E + A / N ** alpha + B / D ** beta
def optimal_allocation(compute_flops):
"""
Trả về (N*, D*) tối ưu cho compute budget C.
Ràng buộc: 6 * N * D = C → D = C / (6 * N).
Tối ưu trên một biến (N).
"""
C = compute_flops
def neg_objective(logN):
N = np.exp(logN)
D = C / (6 * N)
return loss_at(N, D)
# Khởi tạo tại N ≈ sqrt(C/120)
N0 = np.sqrt(C / 120)
res = minimize(
neg_objective,
x0=[np.log(N0)],
method="Nelder-Mead",
options={"xatol": 1e-6, "fatol": 1e-8},
)
N_opt = np.exp(res.x[0])
D_opt = C / (6 * N_opt)
return N_opt, D_opt, loss_at(N_opt, D_opt)
def compare_allocations(compute_flops, tried=None):
"""
So sánh cách phân bổ khác nhau với cùng compute budget.
"""
N_opt, D_opt, L_opt = optimal_allocation(compute_flops)
print(f"Compute: {compute_flops:.2e} FLOPs")
print(f" Compute-optimal: N={N_opt/1e9:.1f}B, D={D_opt/1e9:.1f}B, L={L_opt:.3f}")
if tried:
for name, N, D in tried:
L = loss_at(N, D)
overhead_pct = (L - L_opt) / L_opt * 100
print(f" {name}: N={N/1e9:.1f}B, D={D/1e9:.1f}B, L={L:.3f} (+{overhead_pct:.1f}%)")
if __name__ == "__main__":
# Budget giống Chinchilla paper
C = 5.76e23
compare_allocations(C, tried=[
("GPT-3-like", 175e9, 300e9),
("Chinchilla", 70e9, 1.4e12),
("LLaMA 3 8B-like", 8e9, 15e12),
])
Một số bài báo (Wei et al. 2022) cho rằng ở quy mô đủ lớn (thường > 10^23 FLOPs), LLM "đột nhiên" có khả năng chain-of-thought, few-shot, cộng số nhiều chữ số — gọi là emergent abilities. Nhưng Schaeffer et al. (2023) phản biện: "emergence" chủ yếu là ảo giác do chọn metric gián đoạn (accuracy); đổi sang metric liên tục thì scaling vẫn smooth. Dù tranh cãi, hiện tượng khả năng phi tuyến khi tăng quy mô vẫn là một lý do quan trọng để scale.
- Chinchilla chỉ tối ưu cho training cost. Với inference lớn, overtrain là lựa chọn tốt hơn.
- Các hằng số E, A, B phụ thuộc vào kiến trúc (dense vs MoE vs SSM), dữ liệu (code vs web vs textbook), và tokenizer. Không có "universal" law.
- Dữ liệu chất lượng cao có thể chạm giới hạn trong vài năm tới (Villalobos et al. 2022). Khi đó scaling bằng D thuần không còn hoạt động.
- Các Mixture of Experts thay đổi phương trình: số tham số "active" ≠ số tham số tổng. Cần scaling laws riêng.
Khi model được phục vụ N_requests lần, tổng chi phí là:
Với N_req rất lớn (tỷ request), term thứ hai chiếm ưu thế. Tối ưu Ctotal → chọn model nhỏ hơn (inference rẻ) + train lâu hơn. Đây là lý do LLaMA 3, Mistral 7B, Phi-3 mini ra đời với tỷ lệ D/N cực cao.
Ba chế độ scaling bạn sẽ gặp trong thực tế:
| Chế độ | Tỷ lệ D/N | Tối ưu cho | Ví dụ model |
|---|---|---|---|
| Undertrained | < 10 | (Lịch sử) — hạn chế data | GPT-3 (1.7), Gopher (1.1) |
| Balanced (Chinchilla) | ~20 | Chi phí training thấp nhất | Chinchilla (20), LLaMA 1 (21) |
| Overtrained | > 30 | Chi phí inference thấp | LLaMA 3 8B (1875), Phi-3 (≫100) |
Các sai lầm thường gặp khi áp dụng scaling laws:
- Dùng hằng số Chinchilla cho mọi kiến trúc: MoE, SSM (Mamba), state-space hybrid đều có α, β khác. Không ngoại suy mù quáng.
- Bỏ qua chất lượng data: scaling law giả định data phân phối đều. Filter data kém → A/N^α term bị lệch. Model training on "nguyên liệu tốt" vượt xa model training on data thô cùng D.
- Quên overhead giao tiếpkhi scale lên cluster 10.000+ GPU: C thực tế < 6·N·D một đáng kể do all-reduce, gradient sync.
- Fit scaling law chỉ trên 3–5 điểm: quá ít để tin cậy. Nên > 30 điểm trải trên 3+ bậc N, D.
- Áp Chinchilla khi chi phí inference đáng kể: với product phục vụ hàng tỷ request, dùng inference-aware allocation thay vì Chinchilla thuần.
Ứng dụng thực tế của scaling laws:
- Quyết định compute budget trước khi đầu tư: Anthropic, OpenAI dùng scaling laws để ước lượng loss của GPT-4, Claude 3 trước khi chi hàng trăm triệu đô.
- Thiết kế kiến trúc mới: khi ra MoE, người ta fit scaling law để chứng minh tiết kiệm compute so với dense.
- Báo cáo tiến bộ học thuật: paper LLM mới thường báo cáo "scaling law của chúng tôi có alpha tốt hơn" — kiểu đo lường chuẩn mực.
- Định giá compute: AWS/GCP dựa vào scaling laws để dự báo nhu cầu GPU cho năm tới.
- Lựa chọn model để fine-tune: với budget fine-tune cố định, bạn nên chọn base model ở đúng điểm compute-optimal thay vì model lớn hơn bạn cần.
Scaling laws kết nối với nhiều chủ đề khác: LLM overview để hiểu mô hình mà scaling laws mô tả; cost optimization để áp dụng scaling laws vào quyết định ngân sách thực tế; training optimization để giảm hằng số C thực tế (FlashAttention, ZeRO, activation checkpointing).
- Scaling laws là power law: L(N, D) = E + A/N^α + B/D^β. Loss giảm dự đoán được khi tăng N, D, C.
- Diminishing returns: gấp 10× tham số chỉ giảm loss vài chục phần trăm — không bao giờ là 10×.
- Chinchilla rule: D* ≈ 20 · N* cho compute-optimal. GPT-3 và Gopher là undertrained vì D/N quá thấp.
- C ≈ 6·N·D là công thức vàng để biến tối ưu hai biến thành một biến duy nhất.
- LLaMA 3 và xu hướng hiện đại: overtrain có chủ đích để tiết kiệm inference — đánh đổi training cost lấy serving cost.
- Scaling laws không phải định luật vật lý: hằng số phụ thuộc kiến trúc, data, tokenizer. Kiểm chứng bằng thực nghiệm.
Kiểm tra hiểu biết
Theo scaling laws của Kaplan et al., gấp đôi số tham số N (giữ nguyên data và compute phân bổ) sẽ giảm loss bao nhiêu?
Sandbox bổ sung — so sánh hai chiến lược phân bổ compute
Hai model dưới đây dùng chung compute (~5.76 · 10²³ FLOPs — cỡ Chinchilla paper). Phía trái là "kiểu GPT-3", phía phải là "kiểu Chinchilla". Xem sự khác biệt về loss.
N = 175B, D = 300B (D/N ≈ 1.7)
Loss dự đoán: 2.002
Compute: 3.15 · 10²³ FLOPs
→ Undertrained. Data term B/D^β rất lớn.
Chênh lệch loss nhỏ về mặt số học nhưng đáng kể về chất lượng downstream: Chinchilla vượt Gopher 280B trên hầu hết benchmark.