Skip to content

Họ DeepSeek

This content is not available in your language yet.

Sau bài này, bạn sẽ:

  • Hiểu mixture of experts (MoE, hỗn hợp chuyên gia): bộ định tuyến (router) chọn vài expert cho mỗi token, và hai ý của DeepSeekMoE là chia nhỏ expert (fine-grained expert segmentation) và expert dùng chung (shared expert). Phân biệt được tổng tham số với tham số được kích hoạt.
  • Hiểu MLA (multi-head latent attention) giảm KV cache bằng cách nén, khác attention truy vấn theo nhóm (GQA) giảm bằng cách dùng chung, và tính được KV cache mỗi token.
  • Nắm ba cách DeepSeek-V3 làm huấn luyện rẻ hơn: cân bằng tải (load balancing) không cần loss phụ, dự đoán nhiều token (multi-token prediction, MTP), FP8; và đọc đúng con số “5.576 triệu USD”.
  • Tự dẫn được advantage của GRPO (group relative policy optimization) và hiểu vì sao DeepSeek-R1-Zero học được cách suy luận chỉ từ phần thưởng theo luật (rule-based reward).

Tháng 12/2024, DeepSeek công bố báo cáo kỹ thuật của DeepSeek-V3: 671 tỉ tham số, nhưng mỗi token chỉ đi qua 37 tỉ. Làm sao một mô hình “to” mà mỗi lần tính lại “nhỏ”?

Hình dung một bệnh viện. Không bệnh nhân nào khám qua mọi khoa: lễ tân chuyển bạn tới vài bác sĩ hợp nhất. Bệnh viện có hàng trăm bác sĩ, nhưng mỗi ca chỉ tốn công của vài người.

Trong MoE, bệnh nhân là token, lễ tân là router, bác sĩ là expert. DeepSeek thêm hai ý: nhiều chuyên khoa hẹp thay vì vài khoa lớn, để ca khám ghép được linh hoạt hơn; và một khoa tổng quát ai cũng qua, để các chuyên khoa khỏi tự học lại điều cơ bản.

DeepSeek giữ bộ khung Transformer của bài Họ LLaMA. Mỗi paper nhắm vào một điểm nghẽn:

Điểm nghẽnCách của DeepSeekPaper
Tính toán mỗi tokenMoE có chia nhỏ expert và expert dùng chungDeepSeekMoE, V2, V3
Bộ nhớ KV cache khi sinh văn bảnMLAV2, V3
Chi phí huấn luyệnCân bằng tải bằng bias, MTP, FP8V3
Dạy mô hình suy luậnGRPO, phần thưởng theo luậtDeepSeekMath, R1

Phần lớn các ý này có tiền thân mà chính các paper dẫn nguồn: lớp MoE có router có từ Shazeer và cộng sự (2017), GRPO là biến thể của PPO. Đóng góp của DeepSeek là kết hợp, cải tiến và chạy chúng ở quy mô lớn.

Bài toán của bài này là: làm sao để mô hình có rất nhiều tham số mà mỗi token chỉ tốn một phần nhỏ tính toán, KV cache nhỏ, huấn luyện rẻ, và làm sao dạy nó suy luận khi chỉ biết đáp án cuối đúng hay sai?

Trong khối Transformer thường, sau attention, mỗi token có vectơ u\mathbf{u} đi qua một FFN, cộng kết nối tắt: h=u+FFN(u)\mathbf{h} = \mathbf{u} + \mathrm{FFN}(\mathbf{u}). Lớp MoE thay FFN đó bằng nhiều FFN, mỗi FFN là một expert. Theo cách viết của DeepSeek-V3, có NsN_s expert dùng chung và NrN_r expert định tuyến:

h=u+∑i=1NsFFNi(s)(u)+∑i=1Nrgi FFNi(r)(u)\mathbf{h} = \mathbf{u} + \sum_{i=1}^{N_s} \mathrm{FFN}^{(s)}_i(\mathbf{u}) + \sum_{i=1}^{N_r} g_i\, \mathrm{FFN}^{(r)}_i(\mathbf{u})

Đọc từng số hạng: u\mathbf{u} là kết nối tắt; tổng thứ nhất là các expert dùng chung, luôn chạy, không qua router; tổng thứ hai là các expert định tuyến, mỗi expert nhân với trọng số cổng (gate) gig_i.

Router chấm điểm. Mỗi expert định tuyến có một vectơ học được ei\mathbf{e}_i, như “hồ sơ chuyên môn” của nó. Điểm khớp (affinity) giữa token và expert ii là si=softmaxi(u⊤ei)s_i = \mathrm{softmax}_i(\mathbf{u}^\top \mathbf{e}_i) ở DeepSeekMoE và V2: tích vô hướng lớn thì điểm cao.

Chỉ giữ top-KrK_r. Cổng chỉ khác 0 ở KrK_r expert có điểm cao nhất:

gi={si,si∈TopK({sj∣1≤j≤Nr}, Kr)0,otherwiseg_i = \begin{cases} s_i, & s_i \in \mathrm{TopK}\big(\{s_j \mid 1 \le j \le N_r\},\, K_r\big) \\ 0, & \text{otherwise} \end{cases}

TopK(⋅,Kr)\mathrm{TopK}(\cdot, K_r) là tập KrK_r điểm lớn nhất. Expert có gi=0g_i = 0 không cần chạy, nên mỗi token chỉ chạy Ns+KrN_s + K_r FFN, dù lớp có Ns+NrN_s + N_r FFN. Số tham số tăng theo NrN_r, còn tính toán mỗi token chỉ tăng theo KrK_r.

Với DeepSeek-V3: Ns=1N_s = 1, Nr=256N_r = 256, Kr=8K_r = 8, tức mỗi token chạy 9 trong 257 expert của mỗi lớp MoE. Cả mô hình có 671 tỉ tham số, mỗi token kích hoạt 37 tỉ, khoảng 5.5% (tự tính). Tỉ lệ này lớn hơn 9/257 chủ yếu vì attention, embedding và ba lớp đầu (không phải MoE) thì token nào cũng dùng (giải thích và tự tính của bài). Nhưng cả 671 tỉ tham số vẫn phải nằm trong bộ nhớ, vì token nào cũng có thể chọn bất kỳ expert nào.

Chia nhỏ expert. MoE kiểu GShard (Lepikhin và cộng sự, 2020) chọn 2 trong vài expert cỡ FFN thường. DeepSeekMoE (Dai và cộng sự, 2024) cho rằng khi đó mỗi expert phải ôm nhiều loại kiến thức lẫn lộn. Cách sửa: chia mỗi expert thành 4 expert nhỏ (chiều ẩn còn một phần tư) và chọn gấp 4 số expert. Tổng tham số và tính toán không đổi, nhưng số cách ghép tăng vọt: 16 expert chọn 2 có (162)=120\binom{16}{2} = 120 cách; 64 expert chọn 8 có (648)=4 426 165 368\binom{64}{8} = 4\,426\,165\,368 cách (ví dụ của paper).

Expert dùng chung. Token nào cũng cần một ít kiến thức chung. Không có chỗ riêng cho nó thì nhiều expert cùng học lại phần đó: lãng phí tham số. DeepSeekMoE tách NsN_s expert cho mọi token đi qua, và bớt số expert định tuyến được chọn đi chừng ấy để tính toán như cũ.

Paper báo cáo bản DeepSeekMoE 16B ngang LLaMA2 7B với khoảng 40% tính toán.

Router tự học dễ rơi vào sụp định tuyến (routing collapse): vài expert được chọn mãi, nên học tốt hơn, nên lại càng được chọn, còn các expert khác gần như không được huấn luyện. Khi expert nằm trên nhiều GPU, GPU giữ expert đông khách thành nút thắt.

Cách cũ: loss phụ. DeepSeekMoE và V2 cộng thêm vào hàm mất mát một loss cân bằng (auxiliary loss, loss phụ). Nó lớn khi một expert vừa nhận nhiều token vừa được router chuộng, nên giảm nó kéo tải về đều. Vấn đề, theo báo cáo V3: loss phụ quá lớn làm hại chất lượng mô hình. Wang và cộng sự (2024), paper gốc của cách làm V3 dùng, giải thích rằng loss phụ lớn đưa vào gradient gây nhiễu cho việc dự đoán.

Cách của V3: một bias cho mỗi expert. Mỗi expert có một số bib_i, chỉ cộng vào điểm khi chọn top-KrK_r:

gi′={si,si+bi∈TopK({sj+bj∣1≤j≤Nr}, Kr)0,otherwisegi=gi′∑j=1Nrgj′g'_i = \begin{cases} s_i, & s_i + b_i \in \mathrm{TopK}\big(\{s_j + b_j \mid 1 \le j \le N_r\},\, K_r\big) \\ 0, & \text{otherwise} \end{cases} \qquad g_i = \frac{g'_i}{\sum_{j=1}^{N_r} g'_j}

Ba điều cần đọc ra:

  1. Bias chỉ đổi expert nào được chọn. Trọng số cổng gi′g'_i vẫn là điểm gốc sis_i. bib_i ở đây là một số dùng để xếp hạng, không phải hệ số tự do bb của một lớp tuyến tính.
  2. Cổng được chuẩn hóa trên các expert đã chọn, nên KrK_r cổng cộng lại bằng 1. V3 cũng đổi điểm khớp từ softmax sang sigmoid: si=σ(u⊤ei)s_i = \sigma(\mathbf{u}^\top \mathbf{e}_i).
  3. bib_i không học bằng gradient. Cuối mỗi bước huấn luyện, nhìn tải trên cả lô: expert quá tải thì giảm bib_i đi γ\gamma, expert thiếu tải thì tăng bib_i thêm γ\gamma. γ\gamma gọi là tốc độ cập nhật bias (V3 dùng 0.0010.001).

Như biển chỉ dẫn ở quầy: quầy đông thì hạ biển xuống, quầy vắng thì nâng lên; chỉ đổi người nào vào quầy nào. Hàm mất mát không có số hạng mới, nên gradient chỉ phục vụ việc dự đoán.

V3 vẫn giữ một loss cân bằng theo từng chuỗi với hệ số cực nhỏ, 0.00010.0001, và giới hạn mỗi token chỉ gửi tới tối đa 4 node (máy) để giảm truyền thông.

Bài Họ LLaMA đã tính: KV cache mỗi token là 2⋅Nlayer⋅Hkv⋅d⋅s2 \cdot N_{\text{layer}} \cdot H_{\text{kv}} \cdot d \cdot s byte, với ss là số byte mỗi số (khác điểm khớp sis_i ở trên). GQA giảm HkvH_{\text{kv}}, tức cho các đầu dùng chung K, V. MLA của DeepSeek-V2 đi đường khác: nén.

Gọi ht∈RD\mathbf{h}_t \in \mathbb{R}^{D} là đầu vào attention của token thứ tt (khác h\mathbf{h} là đầu ra lớp MoE ở trên), với HH đầu, mỗi đầu dd chiều. MLA chiếu ht\mathbf{h}_t xuống một vectơ ẩn (latent vector) ct\mathbf{c}_t có dcd_c chiều, rồi từ đó dựng lại khóa và giá trị của mọi đầu:

ct=WDKVht,kt=WUKct,vt=WUVct\mathbf{c}_t = \mathbf{W}^{DKV}\mathbf{h}_t, \qquad \mathbf{k}_t = \mathbf{W}^{UK}\mathbf{c}_t, \qquad \mathbf{v}_t = \mathbf{W}^{UV}\mathbf{c}_t

WDKV∈Rdc×D\mathbf{W}^{DKV} \in \mathbb{R}^{d_c \times D} là ma trận nén (“D” là down), WUK,WUV∈RHd×dc\mathbf{W}^{UK}, \mathbf{W}^{UV} \in \mathbb{R}^{Hd \times d_c} là hai ma trận mở rộng (“U” là up), và dcd_c nhỏ hơn nhiều so với HdHd. Khi sinh văn bản, chỉ cần lưu ct\mathbf{c}_t. Nhờ tính kết hợp của phép nhân ma trận, có thể gộp WUK\mathbf{W}^{UK} vào ma trận truy vấn và WUV\mathbf{W}^{UV} vào ma trận đầu ra, nên không cần dựng lại K, V đầy đủ.

Vướng RoPE. RoPE xoay khóa theo vị trí. Ma trận xoay đứng giữa truy vấn và WUK\mathbf{W}^{UK} thì không gộp WUK\mathbf{W}^{UK} đi được nữa, vì nhân ma trận không giao hoán. V2 giải bằng RoPE tách riêng (decoupled RoPE): thêm một khóa nhỏ dRd^R chiều chỉ để mang vị trí, dùng chung cho mọi đầu, lưu vào cache cùng ct\mathbf{c}_t. Vậy KV cache mỗi token là:

(dc+dR)⋅Nlayer⋅s byte(d_c + d^R) \cdot N_{\text{layer}} \cdot s \ \text{byte}

So với GQA, 2Hkvd2 H_{\text{kv}} d được thay bằng dc+dRd_c + d^R. Paper V2 chọn dc=4dd_c = 4d, dR=d/2d^R = d/2, nên mỗi lớp lưu 4.5d4.5d số, bằng GQA với chỉ 2.25 nhóm. Paper cũng báo cáo chất lượng của MLA mạnh hơn MHA trong thí nghiệm của họ.

Áp vào số của V3 (H=128H = 128, d=128d = 128, dc=512d_c = 512, dR=64d^R = 64, 61 lớp; tự tính):

  • MLA: (512+64)⋅61=35 136(512 + 64) \cdot 61 = 35\,136 số mỗi token. Lưu 2 byte mỗi số thì khoảng 69 KiB, còn nhỏ hơn 128 KiB mỗi token của Llama 3 8B ở bài trước.
  • Nếu dùng MHA thường với cùng 128 đầu: 2⋅128⋅128⋅61=1 998 8482 \cdot 128 \cdot 128 \cdot 61 = 1\,998\,848 số, lớn hơn khoảng 57 lần.

Đó là phép so trên giấy với cùng số đầu. Con số “giảm KV cache 93.3%” trong tóm tắt của V2 là phép so khác: DeepSeek-V2 so với DeepSeek 67B, mô hình dày (dense, không MoE) trước đó của họ.

Huấn luyện rẻ hơn: MTP, FP8 và con số chi phí

Phần tiêu đề “Huấn luyện rẻ hơn: MTP, FP8 và con số chi phí”

MTP. Bình thường, mỗi vị trí chỉ học đoán token kế tiếp. V3 thêm một mô-đun MTP (một khối Transformer, dùng chung embedding và lớp đầu ra với mô hình chính) để mỗi vị trí đoán thêm token sau nữa. Theo báo cáo, việc này làm tín hiệu huấn luyện dày hơn và có thể giúp mô hình “tính trước” xa hơn. Khi dùng thật, có thể bỏ mô-đun MTP, hoặc dùng nó làm bản nháp cho speculative decoding (giải mã suy đoán): báo cáo ghi token thứ hai được chấp nhận 85–90% số lần, tốc độ sinh tăng 1.8 lần.

FP8. Phần lớn phép nhân ma trận lớn chạy ở FP8, số thực 8 bit, một số phép nhạy cảm vẫn giữ độ chính xác cao hơn. Để số nhỏ không bị mất, mỗi ô nhỏ của ma trận có hệ số co giãn riêng. Trên hai mô hình nhỏ hơn, báo cáo đo sai số tương đối của loss so với BF16 luôn dưới 0.25%. (Lượng tử hóa nói chung có ở bài Đánh giá mô hình và PEFT.)

Đọc con số chi phí. Bảng 1 của báo cáo V3:

Chỉ sốPre-trainMở rộng ngữ cảnhHậu huấn luyệnTổng
Giờ GPU H8002 664K119K5K2 788K
USD, giả định 2 USD mỗi giờ GPU5.328M0.238M0.01M5.576M

Hai điều phải đi kèm con số này: 2 USD mỗi giờ là giá thuê giả định, và báo cáo nói rõ con số chỉ tính lần huấn luyện chính thức của V3, không gồm chi phí nghiên cứu và các thí nghiệm trước đó. Nó không phải tổng số tiền làm ra DeepSeek-V3.

Vấn đề của PPO. Advantage AA (giữ nguyên tiếng Anh) là phần thưởng cao hơn hay thấp hơn mức kỳ vọng bao nhiêu: dương thì tăng xác suất câu trả lời, âm thì giảm. Ở bài RLHF, PPO cần thêm một hàm giá trị (value function), còn gọi là critic, để ước lượng mức kỳ vọng đó. Critic thường là một mô hình cỡ ngang chính sách, nên tốn thêm rất nhiều bộ nhớ và tính toán. DeepSeekMath (Shao và cộng sự, 2024) nêu thêm một lý do: phần thưởng thường chỉ chấm ở token cuối, nên khó học một critic đúng ở từng token.

Ý của GRPO. Với mỗi câu hỏi x\mathbf{x}, lấy mẫu một nhóm GG câu trả lời y1,…,yG\mathbf{y}_1, \dots, \mathbf{y}_G từ chính sách cũ πold\pi_{\text{old}}, chấm được r1,…,rGr_1, \dots, r_G. Mức kỳ vọng không do critic đoán nữa, mà lấy ngay từ nhóm:

Ai=ri−mean(r1,…,rG)std(r1,…,rG)A_i = \frac{r_i - \mathrm{mean}(r_1, \dots, r_G)}{\mathrm{std}(r_1, \dots, r_G)}

Như chấm điểm theo lớp: không hỏi “bạn được mấy điểm” mà hỏi “bạn hơn trung bình lớp bao nhiêu độ lệch chuẩn”.

Advantage khi phần thưởng là đúng/sai. Giả sử ri∈{0,1}r_i \in \{0, 1\} và tỉ lệ câu đúng trong nhóm là pp, với 0<p<10 < p < 1. Ta dẫn từng bước:

Bước 1: trung bình. Trung bình của các số 0 và 1 là tỉ lệ số 1: μ=p\mu = p.

Bước 2: độ lệch chuẩn. Phương sai là trung bình của r2r^2 trừ μ2\mu^2. Vì r∈{0,1}r \in \{0, 1\} nên r2=rr^2 = r, trung bình của r2r^2 cũng là pp. Vậy phương sai là p−p2=p(1−p)p - p^2 = p(1-p), và σ=p(1−p)\sigma = \sqrt{p(1-p)}.

Bước 3: thay vào. Gọi A+A_{+} là advantage của câu đúng (r=1r = 1), A−A_{-} là advantage của câu sai (r=0r = 0):

A+=1−pp(1−p)=1−ppA−=0−pp(1−p)=−p1−p\begin{aligned} A_{+} &= \frac{1 - p}{\sqrt{p(1-p)}} = \sqrt{\frac{1-p}{p}} \\ A_{-} &= \frac{0 - p}{\sqrt{p(1-p)}} = -\sqrt{\frac{p}{1-p}} \end{aligned}

Mỗi dòng rút gọn bằng cách viết tử số thành 1−p⋅1−p\sqrt{1-p}\cdot\sqrt{1-p} (dòng đầu) hay p⋅p\sqrt{p}\cdot\sqrt{p} (dòng sau) rồi giản ước với mẫu. Với G=8G = 8 và 3 câu đúng, p=3/8p = 3/8: câu đúng được 5/3≈1.291\sqrt{5/3} \approx 1.291, câu sai được −3/5≈−0.775-\sqrt{3/5} \approx -0.775. Câu đúng càng hiếm, thưởng càng lớn. Còn p=0p = 0 hay p=1p = 1 (cả nhóm cùng sai hay cùng đúng) thì tử số bằng 0 với mọi câu: không có tín hiệu học.

Mục tiêu. Theo paper R1, chính sách πϕ\pi_{\boldsymbol{\phi}} được cập nhật để cực đại:

J(ϕ)=E[1G∑i=1G(min⁡(ρiAi, clip(ρi,1−ϵ,1+ϵ) Ai)−β ki)],ρi=πϕ(yi∣x)πold(yi∣x)\mathcal{J}(\boldsymbol{\phi}) = \mathbb{E}\left[\frac{1}{G}\sum_{i=1}^{G}\Big(\min\big(\rho_i A_i,\ \mathrm{clip}(\rho_i, 1-\epsilon, 1+\epsilon)\, A_i\big) - \beta\, k_i\Big)\right], \qquad \rho_i = \frac{\pi_{\boldsymbol{\phi}}(\mathbf{y}_i \mid \mathbf{x})}{\pi_{\text{old}}(\mathbf{y}_i \mid \mathbf{x})}

Kỳ vọng lấy theo câu hỏi x\mathbf{x} và nhóm câu trả lời sinh từ πold\pi_{\text{old}}. ρi\rho_i cho biết chính sách mới làm câu ii dễ ra hơn chính sách cũ bao nhiêu lần, ϵ\epsilon là độ rộng của kẹp, β\beta là hệ số phạt KL. Lấy min⁡\min để khi Ai>0A_i > 0, ρi\rho_i vượt 1+ϵ1+\epsilon không được lợi thêm; khi Ai<0A_i < 0, ρi\rho_i dưới 1−ϵ1-\epsilon cũng không được lợi thêm. Phần min⁡(⋅,clip)\min(\cdot, \mathrm{clip}) chính là cái kẹp của PPO ở bài RLHF; chỗ khác PPO là AiA_i lấy từ nhóm. DeepSeekMath viết cùng công thức ở mức từng token, và mọi token của câu ii nhận cùng một AiA_i.

Phạt KL nằm thẳng trong mục tiêu. Ở RLHF, phạt KL bị trừ vào phần thưởng. GRPO trừ thẳng vào mục tiêu, nên không làm rối phép tính advantage. Số hạng kik_i là một ước lượng KL từ một mẫu (theo Schulman, 2020):

ki=πref(yi∣x)πϕ(yi∣x)−ln⁡πref(yi∣x)πϕ(yi∣x)−1k_i = \frac{\pi_{\text{ref}}(\mathbf{y}_i \mid \mathbf{x})}{\pi_{\boldsymbol{\phi}}(\mathbf{y}_i \mid \mathbf{x})} - \ln\frac{\pi_{\text{ref}}(\mathbf{y}_i \mid \mathbf{x})}{\pi_{\boldsymbol{\phi}}(\mathbf{y}_i \mid \mathbf{x})} - 1

Hai tính chất làm nó dùng được. Không âm: đặt zz là tỉ số trong phân số, hàm z−ln⁡z−1z - \ln z - 1 có đạo hàm 1−1/z1 - 1/z, âm khi z<1z < 1, dương khi z>1z > 1, nên nhỏ nhất tại z=1z = 1, giá trị nhỏ nhất là 1−0−1=01 - 0 - 1 = 0. Không chệch (chính xác khi mẫu lấy từ chính πϕ\pi_{\boldsymbol{\phi}}): lấy kỳ vọng theo y∼πϕ\mathbf{y} \sim \pi_{\boldsymbol{\phi}}, số hạng đầu cho ∑yπref(y∣x)=1\sum_{\mathbf{y}} \pi_{\text{ref}}(\mathbf{y} \mid \mathbf{x}) = 1; số hạng giữa đổi dấu thành E[ln⁡πϕπref]=DKL(πϕ ∥ πref)\mathbb{E}\big[\ln\frac{\pi_{\boldsymbol{\phi}}}{\pi_{\text{ref}}}\big] = D_{\mathrm{KL}}(\pi_{\boldsymbol{\phi}} \,\|\, \pi_{\text{ref}}); trừ 1 thì còn đúng DKLD_{\mathrm{KL}}.

So với DPO: DPO bỏ hẳn vòng học tăng cường, còn GRPO giữ học tăng cường nhưng bỏ critic. Hai cách bỏ hai thứ khác nhau.

R1-Zero. Paper R1 lấy DeepSeek-V3-Base (bản mới pre-train) rồi chạy GRPO ngay, không qua fine-tune có giám sát (SFT) trước. Mẫu prompt chỉ ép cấu trúc: suy nghĩ trong cặp thẻ <think>, rồi mới ghi đáp án. Phần thưởng hoàn toàn theo luật:

  • Đúng hay sai. Bài toán có đáp án xác định phải ghi đáp án theo định dạng quy định để chương trình kiểm được. Bài lập trình thì biên dịch và chạy các ca kiểm thử.
  • Định dạng. Có đặt phần suy nghĩ đúng trong cặp thẻ không.

Hai phần cộng với trọng số bằng nhau. Paper nói họ không dùng mô hình phần thưởng thần kinh cho bài suy luận, vì nó dễ bị reward hacking khi RL quy mô lớn. Luật kiểm đáp án khó bị lợi dụng hơn một mô hình phần thưởng học từ dữ liệu (như mô hình “thích câu dài” ở bài RLHF), nhưng chỉ dùng được cho bài kiểm tra được.

Kết quả paper báo cáo: pass@1 (tỉ lệ đúng trung bình của một lần trả lời) trên AIME 2024 tăng từ 15.6% lên 77.9% trong quá trình RL; trong lúc đó, mô hình tham chiếu được thay bằng chính sách mới nhất sau mỗi 400 bước. Câu trả lời dài dần, mô hình tự kiểm tra lại và thử cách khác dù không ai dạy cách suy luận; paper gọi khoảnh khắc một phiên bản trung gian tự dừng lại để xem lại lời giải là “aha moment”.

Vì sao còn cần R1. R1-Zero khó đọc, hay trộn tiếng Anh và tiếng Trung trong một chuỗi suy luận, và yếu ở việc ngoài suy luận như viết hay hỏi đáp mở. DeepSeek-R1 đi qua nhiều giai đoạn:

  1. SFT trên vài nghìn mẫu “khởi động lạnh” (cold start) có lối suy nghĩ dễ đọc.
  2. RL hướng suy luận, thêm phần thưởng nhất quán ngôn ngữ: tỉ lệ từ thuộc ngôn ngữ đích trong chuỗi suy luận.
  3. Lấy mẫu từ chối (rejection sampling): sinh nhiều câu trả lời, giữ câu tốt, rồi SFT lần nữa trên cả dữ liệu suy luận lẫn không suy luận.
  4. RL lần hai để mô hình hữu ích và vô hại hơn, có thêm phần thưởng theo sở thích do mô hình phần thưởng chấm.

Paper còn chắt lọc (distill) năng lực sang các mô hình nhỏ dựa trên Qwen và Llama, không phải MoE của R1. Trọng số của V3 và R1 có trên Hugging Face; giấy phép của mã, của trọng số và của mô hình nền (với bản chắt lọc) có thể khác nhau, nên đọc thẻ mô hình trước khi dùng.

Ngày là ngày nộp bản đầu lên arXiv.

NgàyPaperĐiểm mới chính
11/1/2024DeepSeekMoEChia nhỏ expert, expert dùng chung
5/2/2024DeepSeekMathGRPO
7/5/2024DeepSeek-V2MLA, định tuyến giới hạn thiết bị
27/12/2024DeepSeek-V3Cân bằng tải bằng bias, MTP, huấn luyện FP8
22/1/2025DeepSeek-R1R1-Zero học bằng RL thuần, quy trình nhiều giai đoạn
2/12/2025DeepSeek-V3.2Bài không đi vào nội dung

Số liệu R1 trong bài lấy từ bản sửa ngày 4/1/2026 của paper (bản đăng trên Nature, 2025).

  • Bài chỉ đi tới mức ý tưởng. Song song chuyên gia (expert parallelism), chồng tính toán với truyền thông và chi tiết FP8 nằm ngoài phạm vi; chạy mô hình trên nhiều GPU thuộc bài Deploy LLM: nhiều GPU, phân tán. Số benchmark là của paper, đo theo cách của tác giả, tại thời điểm công bố.
  • Phần thưởng theo luật chỉ hợp với bài kiểm tra được. Viết văn, hội thoại mở vẫn cần mô hình phần thưởng hay người đánh giá (bài RLHF). Chính paper R1 cũng ghi R1 còn kém ở đầu ra có cấu trúc, chưa dùng được công cụ, và có lúc suy nghĩ quá dài với câu hỏi đơn giản.

Hình dưới vẽ một lớp MoE kiểu DeepSeek với một token. Hãy nhìn hai nhóm expert: nhóm dùng chung luôn sáng, còn nhóm định tuyến chỉ vài ô được router tô sáng.

uTokenRouter scoresSharedexpertalways runs012345670.4540.546ShortcutWeighted sumhOutputRouted experts:PickedNot runDeepSeek-V31 shared + 8 of 256 routed
The MoE layer computes h=u+∑iFFNi(s)(u)+∑igi FFNi(r)(u)\mathbf{h} = \mathbf{u} + \sum_{i} \mathrm{FFN}^{(s)}_i(\mathbf{u}) + \sum_{i} g_i\,\mathrm{FFN}^{(r)}_i(\mathbf{u}), with gi=0g_i = 0 for every expert not picked; the figure draws 8 routed experts and picks 2, as in the first code cell.

Bảng dưới đặt ba mô hình có paper cạnh nhau. Hãy nhìn hàng tỉ lệ kích hoạt: ở ba mô hình này, mô hình càng lớn, phần tham số mỗi token dùng tới càng nhỏ. R1 không có cột riêng vì dùng đúng kiến trúc V3.

Thông sốDeepSeekMoE 16B (2024)DeepSeek-V2 (2024)DeepSeek-V3 (2024)
Tổng tham số16.4B236B671B
Kích hoạt mỗi token2.8B21B37B
Tỉ lệ kích hoạt (tự tính)17.1%8.9%5.5%
Số lớp286061
Expert dùng chung + định tuyến2 + 642 + 1601 + 256
Expert định tuyến chọn mỗi token668
Attentionnhiều đầu (MHA)MLAMLA
Token pre-train2T8.1T14.8T

Code trong bài chạy thử lần cuối tháng 10/2026, với Python 3.14 và NumPy 2.4 (bản có trong Pyodide). Cả hai ô chạy ngay trên trang, độc lập, không cần mô hình thật.

Định tuyến top-K và cân bằng tải bằng bias

Phần tiêu đề “Định tuyến top-K và cân bằng tải bằng bias”

Ô dưới đây tạo một lô B=64B = 64 token và Nr=8N_r = 8 expert định tuyến, mỗi token chọn Kr=2K_r = 2. Điểm khớp là sigmoid của các số ngẫu nhiên (hạt giống 0), riêng expert 0 được cộng thêm 1.0 trước sigmoid để router cố ý “chuộng” nó. Hàm route chọn top-KrK_r theo si+bis_i + b_i nhưng lấy cổng từ sis_i gốc, như V3. Sau đó 200 bước chỉnh bias với γ=0.01\gamma = 0.01.

Đây là mô phỏng đồ chơi: “quá tải” được hiểu là nhận nhiều hơn trung bình của lô, và điểm khớp giữ nguyên qua mọi bước (huấn luyện thật thì điểm đổi theo mô hình).

Định tuyến top-K và cân bằng tải

# Định tuyến top-K kiểu DeepSeek-V3 và cân bằng tải bằng bias
import numpy as np
rng = np.random.default_rng(0)
B, N, K = 64, 8, 2 # số token trong lô, số expert định tuyến, số expert chọn
logits = rng.normal(size=(B, N)) # u^T e_i của từng token với từng expert
logits[:, 0] += 1.0 # cố ý cho expert 0 được router "chuộng" hơn
s = 1 / (1 + np.exp(-logits)) # điểm khớp bằng sigmoid, như V3
def route(s, bias, k):
# Chọn top-k theo s + bias, nhưng trọng số cổng lấy từ s gốc
picked = np.argsort(-(s + bias), axis=1)[:, :k]
mask = np.zeros_like(s, dtype=bool)
np.put_along_axis(mask, picked, True, axis=1)
gate = np.where(mask, s, 0.0)
return mask, gate / gate.sum(axis=1, keepdims=True)
bias = np.zeros(N)
gamma = 0.01 # tốc độ cập nhật bias (paper dùng 0.001)
for step in range(200):
mask, gate = route(s, bias, K)
load = mask.sum(axis=0) # số token mỗi expert nhận
if step in (0, 199):
print(f"step {step:3d} load:", load)
# Bản đơn giản: quá tải (trên trung bình) thì giảm, thiếu tải thì tăng
bias -= gamma * np.sign(load - load.mean())
print("bias:", np.round(bias, 2))
print("gates of token 0:", np.round(gate[0][mask[0]], 3))
print("experts per token:", mask.sum(axis=1).min(), mask.sum(axis=1).max())

The first run downloads Python, about 10 MB.

Đọc kết quả:

  • step 0: 128 lượt chọn, chia đều thì mỗi expert nhận 16. Chưa có bias, expert 0 nhận 42 lượt, expert 2 chỉ nhận 6.
  • step 199: tải còn [18 16 18 16 15 16 15 14], dao động quanh 16 vì bias nhảy từng bước cố định γ\gamma.
  • bias: expert 0 bị hạ xuống −0.17-0.17; expert vắng khách được nâng lên, cao nhất là expert 2 với 0.130.13.
  • gates of token 0: 0.4540.454 và 0.5460.546, cộng lại bằng 1, tính từ điểm gốc chứ không từ điểm đã cộng bias.
  • experts per token: 2 2: token nào cũng vẫn đúng 2 expert, nên tính toán mỗi token giữ nguyên.

Ô dưới đây tính advantage cho một nhóm G=8G = 8 câu trả lời, phần thưởng 1 nếu đúng, 0 nếu sai. Mẫu số được cộng thêm eps = 1e-8 để không chia cho 0 (paper không nói tới chi tiết này). np.std mặc định chia cho GG, khớp phép dẫn ở mục Lý thuyết.

Advantage của GRPO

# Advantage của GRPO: chuẩn hóa phần thưởng trong một nhóm G câu trả lời
import numpy as np
def advantages(r, eps=1e-8):
r = np.asarray(r, dtype=float)
# eps để không chia cho 0 khi cả nhóm cùng điểm (paper không nói tới)
return (r - r.mean()) / (r.std() + eps)
# G = 8 câu trả lời cho cùng một câu hỏi; 1 là đúng, 0 là sai
group = [1, 0, 0, 1, 0, 0, 0, 1]
a = advantages(group)
print("rewards :", group)
print("advantages:", np.round(a, 3))
print("mean, std :", round(a.mean(), 6), round(a.std(), 3))
# Câu đúng càng hiếm trong nhóm thì advantage của nó càng lớn
for n_ok in (1, 3, 7):
r = [1] * n_ok + [0] * (8 - n_ok)
a_ok, a_bad = advantages(r)[[0, -1]]
print(f"{n_ok} of 8 ok : right {a_ok:+.3f}, wrong {a_bad:+.3f}")
# Cả nhóm cùng điểm: không có tín hiệu học
print("all wrong :", np.round(advantages([0] * 8), 3))
# Nhân mọi phần thưởng với 10: advantage không đổi
scaled = advantages([10 * x for x in group])
print("scaled x10 same:", np.allclose(a, scaled))

The first run downloads Python, about 10 MB.

Đọc kết quả:

  • Nhóm có 3 câu đúng: câu đúng được 1.2911.291, câu sai được −0.775-0.775, đúng như 5/3\sqrt{5/3} và −3/5-\sqrt{3/5} ở mục Lý thuyết. Advantage có trung bình 0.0 và độ lệch chuẩn 1.0.
  • Câu đúng càng hiếm, thưởng càng lớn: 1 trên 8 đúng thì câu đúng được +2.646+2.646 (7\sqrt{7}); 7 trên 8 đúng thì chỉ được +0.378+0.378, còn câu sai duy nhất bị −2.646-2.646.
  • Cả nhóm sai: mọi advantage bằng 0, không có tín hiệu học.
  • Nhân phần thưởng với 10: advantage không đổi (True), vì cả tử lẫn mẫu cùng nhân 10. Chỉ thứ bậc trong nhóm là có nghĩa.
Question 1 of 4 Một lớp MoE có 8 expert, mỗi token chọn 2. Bạn chia mỗi expert thành 4 expert nhỏ (chiều ẩn còn một phần tư) và cho mỗi token chọn 8. Điều gì thay đổi?
Question 2 of 4 Mô hình A dùng GQA với 8 đầu K/V, mỗi đầu d=128d = 128 chiều. Mô hình B dùng MLA với dc=512d_c = 512 và dR=64d^R = 64. Hai mô hình cùng số lớp và cùng lưu 2 byte mỗi số. KV cache mỗi token của B so với A thế nào?
Question 3 of 4 Trong DeepSeek-V3, expert 5 bị quá tải nên bias b5b_5 giảm đi γ\gamma. Giả sử điểm khớp sis_i của token chưa đổi. Một token ở bước sau vẫn chọn đúng hai expert như trước, trong đó có expert 5. Trọng số cổng g5g_5 của token này thế nào?
Question 4 of 4 Bạn huấn luyện bằng GRPO với G=8G = 8. Một câu hỏi quá dễ: cả 8 câu trả lời đều đúng và được thưởng 1. Câu hỏi này đóng góp gì vào lần cập nhật?

Ý chính:

  • MoE: mỗi token chạy NsN_s expert dùng chung và KrK_r trong NrN_r expert định tuyến. DeepSeekMoE chia nhỏ expert để ghép linh hoạt hơn và tách expert dùng chung cho kiến thức chung. Tham số theo NrN_r, tính toán theo KrK_r, bộ nhớ vẫn phải chứa hết.
  • V3 cân bằng tải bằng bias bib_i chỉ dùng khi chọn top-KrK_r, thay cho loss phụ lớn; thêm MTP và FP8. 5.576 triệu USD là giá thuê giả định cho riêng lần huấn luyện chính thức.
  • MLA chỉ lưu vectơ nén ct\mathbf{c}_t và một khóa RoPE nhỏ: (dc+dR)(d_c + d^R) số mỗi lớp, so với 2Hkvd2 H_{\text{kv}} d của GQA.
  • GRPO bỏ critic, lấy mức kỳ vọng từ nhóm. R1-Zero học suy luận dài chỉ từ phần thưởng theo luật; R1 thêm khởi động lạnh và nhiều giai đoạn để dễ đọc, dùng được cho việc khác.

Đọc thêm:

Content licensed under CC BY-NC-SA 4.0. Code under the MIT license.About