Moe
Dense 跟 MoE
Prerequisite knowledge 先備知識:知道「參數(parameters)大致代表模型容量」「一次前向推論需要的計算量(FLOPs)」「Transformer 區塊裡常見的 Attention 與前饋網路(FFN)」「訓練 vs 推論」即可。
1. 故事背景
1-1 把模型想成一間餐廳的廚房
你可以把一個大語言模型想成餐廳後場:
- 有人負責讀懂客人的點單(理解輸入)
- 有人負責把菜做出來(產生輸出) 而「模型的參數」就像廚房裡的廚師、鍋具、流程與食譜的總和。參數越多,通常越有機會把更多菜色與技巧學進來,但也更難伺候。
1-2 Dense 時代:每一單都叫全體廚師一起上
Dense(稠密)模型的直覺是:不管客人點什麼,每次出餐都讓同一套完整廚房流程跑一遍,也就是「每次輸入都會動到幾乎全部參數」。在 Transformer 這類架構裡,常見做法是每一層都固定有 Attention + FFN,FFN 也固定是一套「所有輸入都會經過」的計算。這種「全部都算」的方式很直接、工程上也好做,但一旦模型越做越大,每次出餐的成本也會跟著膨脹。
1-3 變大的代價:強但很貴
研究與實務都觀察到,把模型做大(參數更多、資料更多、算力更多)往往能帶來更強的效果;但代價是訓練與推論會變得非常吃計算資源。Switch Transformer 論文就直接點出:把「densenly-activated Transformer」做大雖有效,但「極度昂貴」;因此他們把目標改成「更高的計算效率」。
1-4 轉念:能不能「店面變超大」,但每次只動用一小部分人力
這時候就出現了關鍵想法:條件式計算(conditional computation)。不要每次都全員出動,而是「看點單內容派出合適的少數人」。2017 年 Shazeer 等人把這件事做成可落地的 Sparsely-Gated MoE:用一個可學的 gate(分派員)決定每次只叫少數幾個 expert(專家小廚房)出來做事,讓模型容量暴增但計算量不要等比例暴增。(arXiv)
2. 解決的痛點
2-1 Dense 的核心痛點:品質要上去,就得每次全員出動
用一句話說 Dense: 「你想要更懂更多、更會做更多菜,就得把整間廚房擴建;而每一單都要把更大的廚房完整跑一遍。」
用非常粗略的計算觀念表示(只抓核心直覺): $\(\text{Dense 的每次計算量} \propto P_{\text{dense}}\)$ 也就是參數規模 \(P_{\text{dense}}\) 變大,單次推論/訓練前向所需的 FLOPs 通常也跟著上升。
2-2 MoE 的做法:多間「專家小廚房」+ 一個「派單員」
MoE(Mixture of Experts)的直覺是把 FFN 這個最「吃參數、吃計算」的部分,改成好幾個「專家版本」,再用 router/gate 來決定某個 token(或某筆輸入)要丟給哪些專家處理。Hugging Face 的整理就用很直白的方式說:MoE layer 由一個 router(gate)和多個 experts 組成,並常用來取代 Transformer 裡的 dense FFN。(Hugging Face)
概念上可以寫成(以 top-\(k\) 路由為例): $\(y = \sum_{i \in \text{Top-}k(G(x))} g_i(x),E_i(x)\)$ 其中 \(G(x)\) 是 gate/router 給每個 expert 的分數,\(E_i(x)\) 是第 \(i\) 個 expert 的輸出,\(k\) 通常很小(例如 1 或 2)。(Hugging Face)
2-3 MoE 解掉的痛點:把「總容量」和「每次成本」拆開
把參數拆成「共享部分」+「很多套專家」後,你可以讓總參數變得非常大,但每次只啟動 \(k\) 個專家,讓單次計算接近固定。
用簡化的參數記號表示: $\(P_{\text{total}} \approx P_{\text{shared}} + E\cdot P_e,\quad P_{\text{active}} \approx P_{\text{shared}} + k\cdot P_e\)$
- \(E\):專家數量
- \(P_e\):每個專家的參數量
- \(k\):每次實際啟動的專家數(通常 \(k \ll E\))
Switch Transformer 把這件事講得很清楚:它追求「在保持每個樣本 FLOPs 幾乎不變的情況下增加參數數量」,做法就是「每次只啟動一部分權重」。
用生活化比喻:
- Dense 是「全能型大廚一個人做完所有菜」或「每單全體同時參與」
- MoE 是「你開了 50 間專門店(壽司、牛排、甜點…),但每位客人只會被導到其中 1~2 間店出餐」 因此「店的總菜單」變超厚,但「每次出餐動用的人力」仍可控。
2-4 MoE 為了做到這件事,還得處理哪些新麻煩
MoE 雖然解了「Dense 太貴」這個大痛點,但要真的跑得順,還會遇到一些典型的系統與訓練挑戰(也就是 MoE 系列工作持續在解的點):
- 分流塞車(load balancing):如果 router 老是把 token 都丟給少數幾個熱門專家,就會造成有的專家爆滿、有的專家閒著,整體效率反而變差,因此常需要額外的平衡機制。(Hugging Face)
- 通訊與工程複雜度:專家可能分散在不同裝置上,token 路由會帶來跨裝置傳輸與實作難度;Switch Transformer 也明說 MoE 的廣泛採用過去常被「複雜度、通訊成本、訓練不穩」卡住,並以簡化設計來改善。
- 記憶體壓力:雖然一次只算少數專家,但推論時通常仍需要把所有專家權重載入(或以其他方式管理),因此「算得比較少」不等於「一定更省顯存」。(Hugging Face)
總結一句:Dense 像「每次都用整台大機器」,MoE 像「把能力拆成很多模組,靠派單員只啟動需要的那幾個」。它最大的價值,就是把「模型總容量」做大,同時讓「每次處理的計算量」不必跟著等比例爆掉。

3(實際案例運算)
3-1 真實場景與輸入(把一句話變成模型吃得下的矩陣)
3-1-1 場景設定
電商客服模型收到一句話:「我要退款,進度呢?」
為了示範 MoE 的「分流到不同 expert」如何省計算、提升專注度,我們只取兩個關鍵 token:
- token 1:「退款」(偏規則/政策)
- token 2:「進度」(偏查詢/流程)
3-1-2 兩個 token 的向量(embedding)組成輸入矩陣 \(X\)
3-2 Router(派單員)先算「每個 token 該找哪個 expert」
3-2-1 Router 權重(把 token 向量投影成「對每個 expert 的分數」)
MoE 的關鍵是「每個 token 經過一個 router,選少數 expert 來處理」,常見做法是線性層輸出對每個 expert 的 logits,再做 softmax 得機率。
3-2-2 計算 logits:\(Z = X\cdot W_r\)
3-3 Softmax 變成路由機率,並做 top-1(每個 token 只選 1 個 expert)
3-3-1 路由機率(每列對應一個 token,兩欄對應 expert 1 與 expert 2)
這裡我們有 2 個 experts: - expert 1:偏「退款規則/政策」處理 - expert 2:偏「進度查詢/流程」處理
3-3-2 top-1 選擇(每個 token 只派給機率最大的 expert)
- token「退款」選 expert 1(\(0.982014\))
- token「進度」選 expert 2(\(0.731059\))
痛點:避免每個 token 都跑完整的大 FFN,改成「按需派工」,把每次推論的計算量壓住(稀疏啟動)。
3-4 Dispatch(分流):只把 token 送去被選到的 expert
3-4-1 用選擇矩陣把 token 切出去(真實系統會做 token-to-expert 的 dispatch)
我們用兩個選擇矩陣代表「挑第 1 個 token」與「挑第 2 個 token」。
3-4-2 分別得到送進 expert 的輸入
token「退款」送 expert 1:
token「進度」送 expert 2:
痛點:把不同意圖的 token 分到不同路徑,降低「所有資料擠同一條計算管線」造成的浪費與干擾。
3-5 Expert 1(退款規則 expert)的前向傳播(兩層 FFN:Linear -> ReLU -> Linear)
在 Transformer 裡,MoE 常用來取代 dense FFN:把原本「一套 FFN」換成「多套 FFN experts + router」。
3-5-1 Expert 1 的第一層線性:\(H^{(1)}_{\text{pre}} = X^{(1)}\cdot W^{(1)}_1 + b^{(1)}_1\)
3-5-2 啟用函數 ReLU:\(H^{(1)}=\text{ReLU}(H^{(1)}_{\text{pre}})\)
3-5-3 Expert 1 的第二層線性:\(Y^{(1)}=H^{(1)}\cdot W^{(1)}_2 + b^{(1)}_2\)
3-5-4 乘上 router 給的權重(top-1 的 gate 值)
token「退款」對 expert 1 的 gate 值是 \(0.982014\):
痛點:讓「退款」相關訊息走一條更專注的子網路,減少不同任務互相拉扯,提升表達的針對性。
3-6 Expert 2(進度查詢 expert)的前向傳播(兩層 FFN:Linear -> ReLU -> Linear)
3-6-1 Expert 2 的第一層線性:\(H^{(2)}_{\text{pre}} = X^{(2)}\cdot W^{(2)}_1 + b^{(2)}_1\)
3-6-2 啟用函數 ReLU:\(H^{(2)}=\text{ReLU}(H^{(2)}_{\text{pre}})\)
3-6-3 Expert 2 的第二層線性:\(Y^{(2)}=H^{(2)}\cdot W^{(2)}_2 + b^{(2)}_2\)
3-6-4 乘上 router 給的權重(top-1 的 gate 值)
token「進度」對 expert 2 的 gate 值是 \(0.731059\):
痛點:把「進度」查詢的訊息交給另一條子網路,讓模型用更少計算做到「分工處理不同型態訊息」。
3-7 Gather(回填):把各 expert 的輸出放回原本 token 位置並合併
3-7-1 先把 expert 輸出散回到 \(2\times 2\)(沒被該 expert 處理的 token 位置補 0)
需要用轉置的選擇矩陣 \(D^{(1)T}, D^{(2)T}\):
3-7-2 合併成 MoE 輸出:\(Y_{\text{moe}}=\tilde{Y}^{(1)}_{\text{full}}+\tilde{Y}^{(2)}_{\text{full}}\)
痛點:把「分工後的結果」安全地合回同一條序列表示,讓後續層可以像處理一般 Transformer 一樣繼續運算。 :contentReference[oaicite:6]{index=6}
3-8 殘差連接(像 Transformer FFN 一樣把新訊息加回去)
3-8-1 計算 block 輸出:\(O = X + Y_{\text{moe}}\)
痛點:保留原始輸入資訊並讓更新是「加法微調」,降低表示被破壞的風險,使推論更穩定。
4 面試考題
4-1 基礎觀念:什麼是 MoE?它和 Dense 最大差異在哪?
題目
請用一句話定義 MoE(Mixture of Experts),並說明它和 Dense Transformer 的最大差異。
解答
MoE 是一種「條件式計算」架構:對每個輸入(常見到 token 粒度)只啟動少數幾個 expert 子網路來計算,而不是每次都啟動全部參數。最大差異在於 Dense 是「每個 token 都走同一套 FFN」,MoE 是「每個 token 先被 router 分流,走少數 expert」。
4-2 Router / Gating:logits 與 softmax 機率代表什麼?
題目
MoE router 輸出 logits,再做 softmax 得到機率。請說明 logits 與 softmax 後機率各代表什麼。
解答
logits 是「token 對每個 expert 的偏好分數(未正規化)」;softmax 後是「在該 token 的 expert 候選集合中,各 expert 被選用的相對機率」,通常用來做 top-\(k\) 選擇與加權。
4-3 張量形狀:為什麼 softmax 後常是矩陣而不是一維向量?
題目
若 \(Z\) 的 shape 是 \((T, E)\)(\(T\) 個 token,\(E\) 個 experts),對 \(Z\) 做 softmax 後的結果 shape 是什麼?為什麼不是一維?
解答
softmax 後仍是 \((T, E)\)。因為對每個 token(每一列)各自把 \(E\) 個 expert 分數正規化成一個機率分佈,所以每個 token 都有自己的 \(E\) 維機率向量,堆疊起來就是矩陣。:contentReference[oaicite:2]{index=2}
4-4 top-1 與 top-2:差別與取捨
題目
top-1 routing 與 top-2 routing 的差別是什麼?請說出至少兩個取捨點(效果/成本/穩定性皆可)。
解答
- top-1:每個 token 只給 1 個 expert;計算與通訊更省,工程更簡單,但可能降低表達彈性與容錯。
- top-2:每個 token 給 2 個 experts;通常更有彈性、效果可能更好,但計算量與通訊量增加、負載更難平衡。
4-5 前向公式:請寫出 MoE layer 的核心計算
題目
請寫出常見 top-\(k\) MoE 的輸出公式(token 級),並說明各符號意義。
解答
常見形式:
$$
y=\sum_{i\in \text{Top-}k(G(x))} p_i(x)\,E_i(x)
$$
- \(x\):token 表示
- \(G(\cdot)\):router/gate,輸出對各 expert 的分數或機率
- \(p_i(x)\):softmax 後對 expert \(i\) 的權重(機率或經正規化權重)
- \(E_i(\cdot)\):第 \(i\) 個 expert(多為 FFN 子網路)
- Top-\(k\):只啟動權重最大的 \(k\) 個 experts(稀疏啟動)
4-6 計算量:MoE 為什麼能「總參數很大但每 token FLOPs 近似固定」?
題目
請用「總參數量」與「每 token 啟動參數量」解釋 MoE 的計算效率直覺。
解答
若有 \(E\) 個 experts、每次只啟動 \(k\) 個(\(k\ll E\)),則總參數大致為:
$$
P_{\text{total}}\approx P_{\text{shared}}+E\cdot P_e
$$
但每 token 實際參與計算的參數更接近:
$$
P_{\text{active}}\approx P_{\text{shared}}+k\cdot P_e
$$
因此可以把「容量(總參數)」做很大,同時維持「每 token 計算量」不隨 \(E\) 線性爆增。
4-7 系統瓶頸:為什麼算術 FLOPs 變少,不代表端到端一定更快?
題目
MoE 把每 token 計算量壓低後,為什麼實務上速度可能沒有同比提升?請列出兩個常見原因。
解答
1. 通訊成本:token 需要 dispatch 到各 expert、再 gather 回來,常涉及 all-to-all 類型通訊,可能吃掉大量時間。:contentReference[oaicite:6]{index=6}
2. 負載不均:router 若偏向少數 experts,某些 GPU/experts 壅塞、其他閒置等待,導致利用率下降。
4-8 負載平衡:什麼是 load balancing?為什麼需要?
題目
在 MoE 中什麼是 load balancing?如果不做會發生什麼事?
解答
load balancing 是讓 token 分配到 experts 更平均的機制。若不做,router 可能把大量 token 丟給少數熱門 experts,造成:
- 部分 experts 過載、延遲上升
- 其他 experts 閒置、算力浪費
- 訓練不穩或效果下降
因此許多 MoE 系統會搭配負載平衡策略與容量限制。
4-9 訓練穩定:Switch Transformer 解了哪些「MoE 難以普及」的痛點?
題目
Switch Transformer 為何被認為讓 MoE 更容易大規模採用?請說明它想解決的 MoE 主要阻礙。
解答
Switch Transformer 指出 MoE 過去難以普及的原因包含「複雜度、通訊成本、訓練不穩定」,並提出更簡化的 routing 與訓練技巧來改善,讓大規模稀疏模型更可訓練、更有效率。
4-10 推論部署:MoE 的 GPU 記憶體一定比較省嗎?
題目
有人說 MoE 因為每次只算少數 experts,所以推論顯存一定更省。這句話對嗎?請說明。
解答
不一定。MoE 的「每次啟動計算」變少,但「總權重」更大;推論時可能仍需要把大量 expert 權重常駐在 GPU(或分散在多卡上),再加上 dispatch/gather 的緩衝與通訊開銷,顯存未必比較省。
4-11 工程題:你會如何定位 MoE 的瓶頸在「算力、記憶體頻寬、還是通訊」?
題目
假設一個 MoE 模型吞吐不如預期,你會用哪些觀察指標快速判斷瓶頸是 compute-bound、memory-bound、還是 communication-bound?
解答
可行判斷方向(面試回答抓重點即可):
- compute-bound:GPU SM 利用率高、算子時間集中在 GEMM/FFN,通訊佔比低。
- memory-bound:顯存帶寬接近上限、算力利用率不高但時間花在權重/activation 搬運。
- communication-bound:all-to-all / gather / scatter 等通訊佔比高,GPU 常在等待同步;可參考框架提供的 MoE dispatcher/overlap 設計與觀測。
4-12 開放題:什麼情境你會「不建議」用 MoE?
題目
請列出兩種你會不建議使用 MoE 的真實場景,並說明理由。
解答
- 單卡或少卡、且重視低延遲小 batch 推論:MoE 可能被 dispatch/gather 與權重存取拖累,收益不一定覆蓋工程成本。
- 系統/團隊無法負擔通訊與負載平衡工程:MoE 的實作與調參比 Dense 複雜,若沒有相應基礎設施(例如成熟 MoE 框架),容易踩到不穩定與效率不佳問題。
