<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>模組三：LLM 的理論基礎 on Tarragon</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/</link><description>Recent content in 模組三：LLM 的理論基礎 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 11 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/index.xml" rel="self" type="application/rss+xml"/><item><title>3.1 Embedding 空間</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/embedding-spaces/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/embedding-spaces/</guid><description>&lt;p>Embedding 是 LLM 把離散 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 轉成連續向量的關鍵步驟。模型內部的每一層運算都對向量做、token 本身的整數 ID 只在 input / output 端用到。理解 embedding 怎麼運作、能解釋「為什麼模型能理解 token 之間的語意關係」「為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding 模型&lt;/a> 能做 semantic search」「為什麼不同 model 的 embedding 互不相容」。&lt;/p>
&lt;p>本章拆開 embedding 的三件事：怎麼從 token ID 變成向量、向量空間怎麼承載語意、embedding 是怎麼學出來的。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋 embedding layer 在 LLM 中的位置。&lt;/li>
&lt;li>看到「embedding dimension = 4096」時、知道指什麼。&lt;/li>
&lt;li>解釋 RAG / semantic search 為什麼用 embedding similarity。&lt;/li>
&lt;li>區分 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/word2vec/" data-link-title="Word2Vec" data-link-desc="早期靜態詞向量方法，用 skip-gram / CBOW 從上下文學出詞語 embedding">word2vec&lt;/a>、句子 embedding、contextual embedding 的差別。&lt;/li>
&lt;/ol>
&lt;h2 id="embedding-layer從-token-id-到向量">&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">Embedding Layer&lt;/a>：從 token ID 到向量&lt;/h2>
&lt;p>Embedding layer（嵌入層）的核心結構是「一個 lookup table、把 token ID（整數）map 到向量」。形式上是一個 &lt;code>(vocab_size, hidden_dim)&lt;/code> 的矩陣 E：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">token_id = 12345
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">embedding = E[12345] ← 取出第 12345 row、得到 hidden_dim 維向量&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Gemma 4 31B 的 embedding matrix：&lt;/p>
&lt;ul>
&lt;li>vocab_size = 256,000&lt;/li>
&lt;li>hidden_dim = 5120&lt;/li>
&lt;li>總參數 = 256,000 × 5120 ≈ 1.3 billion&lt;/li>
&lt;/ul>
&lt;p>光是 embedding layer 就佔 31B 中的 1.3B（約 4%）。70B 模型的 embedding layer 更大、可達 2B 以上。&lt;/p>
&lt;p>實作上 embedding lookup 比矩陣乘法便宜（只是查表）、但記憶體佔用顯著。&lt;/p>
&lt;h2 id="向量空間用-hidden_dim-維空間編碼語意">向量空間：用 hidden_dim 維空間編碼語意&lt;/h2>
&lt;p>Embedding 的設計目標是「讓相似 token 在向量空間中靠近、不相似的遠」。具體用&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積&lt;/a> 或 cosine similarity 衡量相似度：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">cosine_sim(a, b) = (a · b) / (||a|| × ||b||)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>訓練後的 embedding 會展現語意結構：&lt;/p>
&lt;ul>
&lt;li>&lt;code>embedding(cat)&lt;/code> 跟 &lt;code>embedding(kitten)&lt;/code> 內積大。&lt;/li>
&lt;li>&lt;code>embedding(cat)&lt;/code> 跟 &lt;code>embedding(algorithm)&lt;/code> 內積小。&lt;/li>
&lt;li>著名的「king - man + woman ≈ queen」現象（word2vec 時代發現、Transformer 上也成立）。&lt;/li>
&lt;/ul>
&lt;p>這個性質讓 embedding 能做：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Semantic search&lt;/strong>：把 query 跟 documents 都轉成 embedding、用 cosine similarity 找相似的。&lt;/li>
&lt;li>&lt;strong>RAG&lt;/strong>：把 codebase chunks embed、用 query embedding 找相關片段。&lt;/li>
&lt;li>&lt;strong>Clustering&lt;/strong>：embedding 上跑 k-means、把語意相近的 document 分組。&lt;/li>
&lt;li>&lt;strong>Anomaly detection&lt;/strong>：embedding 離 cluster 中心遠的就是異常。&lt;/li>
&lt;/ul>
&lt;h2 id="embedding-怎麼學出來">Embedding 怎麼學出來&lt;/h2>
&lt;p>Embedding layer 跟其他 layer 一樣、是訓練過程中學出來的。具體機制：&lt;/p></description><content:encoded><![CDATA[<p>Embedding 是 LLM 把離散 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 轉成連續向量的關鍵步驟。模型內部的每一層運算都對向量做、token 本身的整數 ID 只在 input / output 端用到。理解 embedding 怎麼運作、能解釋「為什麼模型能理解 token 之間的語意關係」「為什麼 <a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">embedding 模型</a> 能做 semantic search」「為什麼不同 model 的 embedding 互不相容」。</p>
<p>本章拆開 embedding 的三件事：怎麼從 token ID 變成向量、向量空間怎麼承載語意、embedding 是怎麼學出來的。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋 embedding layer 在 LLM 中的位置。</li>
<li>看到「embedding dimension = 4096」時、知道指什麼。</li>
<li>解釋 RAG / semantic search 為什麼用 embedding similarity。</li>
<li>區分 <a href="/blog/llm/knowledge-cards/word2vec/" data-link-title="Word2Vec" data-link-desc="早期靜態詞向量方法，用 skip-gram / CBOW 從上下文學出詞語 embedding">word2vec</a>、句子 embedding、contextual embedding 的差別。</li>
</ol>
<h2 id="embedding-layer從-token-id-到向量"><a href="/blog/llm/knowledge-cards/embedding-layer/" data-link-title="Embedding Layer" data-link-desc="Transformer 第一層的查表結構、把整數 token ID 轉成可運算的向量">Embedding Layer</a>：從 token ID 到向量</h2>
<p>Embedding layer（嵌入層）的核心結構是「一個 lookup table、把 token ID（整數）map 到向量」。形式上是一個 <code>(vocab_size, hidden_dim)</code> 的矩陣 E：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">token_id = 12345
</span></span><span class="line"><span class="ln">2</span><span class="cl">embedding = E[12345]   ← 取出第 12345 row、得到 hidden_dim 維向量</span></span></code></pre></div><p>Gemma 4 31B 的 embedding matrix：</p>
<ul>
<li>vocab_size = 256,000</li>
<li>hidden_dim = 5120</li>
<li>總參數 = 256,000 × 5120 ≈ 1.3 billion</li>
</ul>
<p>光是 embedding layer 就佔 31B 中的 1.3B（約 4%）。70B 模型的 embedding layer 更大、可達 2B 以上。</p>
<p>實作上 embedding lookup 比矩陣乘法便宜（只是查表）、但記憶體佔用顯著。</p>
<h2 id="向量空間用-hidden_dim-維空間編碼語意">向量空間：用 hidden_dim 維空間編碼語意</h2>
<p>Embedding 的設計目標是「讓相似 token 在向量空間中靠近、不相似的遠」。具體用<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積</a> 或 cosine similarity 衡量相似度：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">cosine_sim(a, b) = (a · b) / (||a|| × ||b||)</span></span></code></pre></div><p>訓練後的 embedding 會展現語意結構：</p>
<ul>
<li><code>embedding(cat)</code> 跟 <code>embedding(kitten)</code> 內積大。</li>
<li><code>embedding(cat)</code> 跟 <code>embedding(algorithm)</code> 內積小。</li>
<li>著名的「king - man + woman ≈ queen」現象（word2vec 時代發現、Transformer 上也成立）。</li>
</ul>
<p>這個性質讓 embedding 能做：</p>
<ul>
<li><strong>Semantic search</strong>：把 query 跟 documents 都轉成 embedding、用 cosine similarity 找相似的。</li>
<li><strong>RAG</strong>：把 codebase chunks embed、用 query embedding 找相關片段。</li>
<li><strong>Clustering</strong>：embedding 上跑 k-means、把語意相近的 document 分組。</li>
<li><strong>Anomaly detection</strong>：embedding 離 cluster 中心遠的就是異常。</li>
</ul>
<h2 id="embedding-怎麼學出來">Embedding 怎麼學出來</h2>
<p>Embedding layer 跟其他 layer 一樣、是訓練過程中學出來的。具體機制：</p>
<ol>
<li>訓練初期 embedding 是隨機初始化。</li>
<li>Forward pass 用這些 embedding 跑模型、預測下一個 token。</li>
<li>預測錯了、loss 大、<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">backprop</a> 算 gradient、更新 embedding。</li>
<li>反覆 trillion token 訓練、embedding 收斂到能表達語意。</li>
</ol>
<p>訓練機制讓「常在類似 context 出現的 token」拿到相似的 embedding。例如 <code>cat</code> 跟 <code>kitten</code> 在訓練資料中常出現在類似句子（「The ___ is sleeping」「I have a pet ___」等）、模型最佳化的方向會自然讓兩者的 embedding 接近。</p>
<p>這就是「distributional semantics」（分佈式語意）的核心假設：<strong>字詞的意義由它周圍的字詞決定</strong>（&ldquo;You shall know a word by the company it keeps&rdquo;, J. R. Firth, 1957）。</p>
<h2 id="word2vecembedding-的早期實作">Word2Vec：embedding 的早期實作</h2>
<p>Word2Vec（Mikolov et al., 2013）是 embedding 的經典實作、影響後續所有 NLP。它的核心是「用淺層網路專門學 embedding」、不做下游任務：</p>
<ul>
<li><strong>Skip-gram</strong>：給一個中心字、預測周圍字。</li>
<li><strong>CBOW</strong>：給周圍字、預測中心字。</li>
</ul>
<p>訓練後 embedding 展現語意結構（包括「king - man + woman ≈ queen」這個著名實驗、近年研究指出該類比有 cherry-picking 質疑、Linzen 2016 / Nissim et al. 2020、是入門啟發、非嚴格 evidence）。Word2Vec 在大型語意理解場景已被 contextual embedding 取代、但在「靜態查表、邊緣計算、輕量 baseline」等情境仍有用、不是完全淘汰。</p>
<h2 id="word-level-vs-contextual-embedding">Word-level vs Contextual Embedding</h2>
<p>Word-level embedding（Word2Vec、GloVe 等）每個字一個固定向量、不考慮 context：</p>
<ul>
<li><code>bank</code> 在「river bank」跟「bank account」中拿到同樣的 embedding。</li>
<li>簡單、可預先計算、查表快。</li>
<li>限制：無法區分多義詞。</li>
</ul>
<p>Contextual embedding（BERT、GPT 等 Transformer-based）的向量隨 context 改變：</p>
<ul>
<li><code>bank</code> 在「river bank」跟「bank account」中拿到不同的向量。</li>
<li>模型每層輸出都可視為一種 contextual embedding、越深越抽象。</li>
<li>缺點：需要跑完整模型、不能預先計算。</li>
</ul>
<p>LLM 內部用的是 contextual embedding。輸入端的 embedding layer 是 word-level（每個 token ID 對應固定向量）、但經過 attention 後變成 context-dependent。</p>
<h2 id="sentence--paragraph-embedding">Sentence / Paragraph Embedding</h2>
<p>句子或段落級別的 embedding 是把整段文字壓成一個向量、用於 retrieval 與分類任務。常見實作：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>特性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Sentence-BERT (SBERT)</td>
          <td>用 siamese BERT 訓練、retrieval 經典</td>
      </tr>
      <tr>
          <td>nomic-embed-text</td>
          <td>開源、Continue.dev 預設</td>
      </tr>
      <tr>
          <td>OpenAI text-embedding-3</td>
          <td>商業 API、品質高</td>
      </tr>
      <tr>
          <td>BGE / E5 系列</td>
          <td>多語言、SOTA 開源</td>
      </tr>
  </tbody>
</table>
<p><a href="/blog/llm/knowledge-cards/embedding-model/" data-link-title="Embedding Model" data-link-desc="把文字轉成向量的模型：用於 codebase 索引與語意搜尋">Embedding 模型</a> 跟 chat model 是不同訓練流程：</p>
<ul>
<li>Chat model 學「下個 token 機率分佈」。</li>
<li>Embedding model 學「整段文字壓成一個向量、用 cosine similarity 衡量語意相似度」。</li>
</ul>
<p>兩者底層架構都是 Transformer、但訓練 objective 不同、得到的向量空間不通用。</p>
<h2 id="向量空間互不相容">向量空間互不相容</h2>
<p>不同 embedding 模型的向量空間互不相容：</p>
<ul>
<li>nomic-embed-text 輸出 768 維向量。</li>
<li>OpenAI text-embedding-3-small 輸出 1536 維向量。</li>
<li>兩者各自的座標軸有獨立意義、不能拿 nomic 的向量跟 OpenAI 的向量算 cosine。</li>
</ul>
<p>實務啟示：</p>
<ol>
<li>換 embedding 模型要重建 vector database。</li>
<li>一個 retrieval 系統用同一個 embedding 模型 throughout、混用會壞。</li>
<li>模型升級時要 backfill 舊資料。</li>
</ol>
<h2 id="embedding-similarity-的失效情境">Embedding similarity 的失效情境</h2>
<p>Embedding similarity 在多數 retrieval / semantic search 場景能用、但有幾類已知失效模式、影響 RAG / <code>@codebase</code> 的回答品質：</p>
<table>
  <thead>
      <tr>
          <th>失效模式</th>
          <th>判讀訊號</th>
          <th>修法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anisotropy（向量擠在窄錐）</td>
          <td>隨機 query 對的 cosine score 平均 &gt; 0.7、相對排序失準</td>
          <td>換較強 embedding model、做 mean-centering / whitening 後處理</td>
      </tr>
      <tr>
          <td>否定句被當相似</td>
          <td>「我能買牛奶」跟「我不能買牛奶」cosine 接近</td>
          <td>結構性區分 / 補 BM25 lexical retrieval 取交集、或用 reranker 做最終排序</td>
      </tr>
      <tr>
          <td>Lexical mismatch</td>
          <td>query 用同義詞、retrieval 找不到原文</td>
          <td>加 hybrid retrieval（embedding + BM25）、或在 <a href="/blog/llm/knowledge-cards/query-expansion/" data-link-title="Query Expansion" data-link-desc="RAG 檢索前把一個 query 擴成多個語意變體，增加 coverage，再合併 retrieval 結果">query expansion</a> 做改寫</td>
      </tr>
      <tr>
          <td>長尾稀有詞</td>
          <td>專有名詞 / 縮寫 / domain 術語 retrieval 結果飄</td>
          <td>跑 domain fine-tune embedding、或保留 BM25 作為 backup 排序</td>
      </tr>
      <tr>
          <td>跨語言混合 token</td>
          <td>中英混雜文件查不準</td>
          <td>用多語言 embedding（BGE-m3 / multilingual-e5）取代英文 only embedding</td>
      </tr>
  </tbody>
</table>
<p>實作層級的修法多半是 hybrid retrieval（embedding + BM25 / TF-IDF 各跑一次、合併分數）或加 reranker 做最終排序、純依賴 cosine similarity 風險高的場景值得納入這層。</p>
<h2 id="位置編碼把順序資訊加進-embedding">位置編碼：把順序資訊加進 embedding</h2>
<p>純 embedding layer 沒有「順序資訊」、<code>[cat, dog]</code> 跟 <code>[dog, cat]</code> 的 embedding 序列只是 order 不同的 set。Transformer 用 <a href="/blog/llm/knowledge-cards/positional-encoding/" data-link-title="Positional Encoding" data-link-desc="把 token 位置資訊注入 Transformer 的機制，讓 attention 能分辨順序與距離">positional encoding</a> 把位置資訊加進去。</p>
<p>主流位置編碼方法：</p>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>機制</th>
          <th>主要使用模型 / 取捨</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Sinusoidal</td>
          <td>用 sin / cos 不同頻率生成固定位置向量、加進 embedding</td>
          <td>原始 Transformer paper、現已少見、長度外推能力弱</td>
      </tr>
      <tr>
          <td>Learned</td>
          <td>學一個 <code>(max_seq_len, hidden_dim)</code> 的位置矩陣、加進 embedding</td>
          <td>GPT-2 / BERT 系列、被綁死在訓練長度、無法外推</td>
      </tr>
      <tr>
          <td>RoPE</td>
          <td>Rotary Position Embedding、把位置編碼到 Q/K 的旋轉中</td>
          <td>Llama / Gemma / Qwen 主流、長度外推能力佳、實作上是相對位置</td>
      </tr>
      <tr>
          <td>ALiBi</td>
          <td>Attention with Linear Biases、在 attention scores 加位置 bias</td>
          <td>MPT 系列、長度外推極佳、但 LLM 主流仍偏 RoPE</td>
      </tr>
  </tbody>
</table>
<p>RoPE 是 2026 年的主流選擇。詳細展開見 <a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 Transformer 架構</a>。</p>
<h2 id="tied-vs-untied-embedding">Tied vs Untied Embedding</h2>
<p>「Tied embedding」指「input embedding（token → vector）跟 output projection（hidden → logits）共用同一個矩陣」。實作上 input embedding 矩陣 <code>E</code> 的 shape 是 <code>(vocab_size, hidden_dim)</code>、output projection 矩陣的 shape 是 <code>(hidden_dim, vocab_size)</code>；tied 模式直接用 <code>E^T</code>（轉置）當 output projection、省下一份 <code>(vocab_size, hidden_dim)</code> 大小的權重。GPT-2 系列預設 tied、節省參數。</p>
<p>「Untied embedding」是兩者各自獨立、各自訓練。Llama 系列預設 untied、品質略好（兩個矩陣可以各自最佳化）、但 embedding layer 跟 output layer 都要存。</p>
<p>實務上、大模型（30B+）幾乎都採 untied、用較多參數換較高品質；小模型（1B 以下）為了壓縮參數量仍會 tied。</p>
<h2 id="embedding-在-llm-forward-pass-中的位置">Embedding 在 LLM forward pass 中的位置</h2>
<p>LLM 的 forward pass 概略：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">tokens (整數序列)
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  ↓ embedding lookup
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">embeddings (向量序列、shape: [seq_len, hidden_dim])
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓ + positional encoding
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">positioned embeddings
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  ↓ Transformer block × N
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">final hidden states
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  ↓ output projection
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">logits (shape: [seq_len, vocab_size])
</span></span><span class="line"><span class="ln">10</span><span class="cl">  ↓ softmax
</span></span><span class="line"><span class="ln">11</span><span class="cl">機率分佈</span></span></code></pre></div><p>每個 Transformer block 內部都對向量做變換、向量維度保持 hidden_dim 不變、只有 input embedding 跟 output projection 在 vocab_size 跟 hidden_dim 之間轉換。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2 attention 機制</a>、Transformer 的招牌技術。</p>
]]></content:encoded></item><item><title>3.2 Attention 機制</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/attention-mechanism/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/attention-mechanism/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">Attention&lt;/a>（注意力）是 Transformer 的核心創新、也是 LLM 能處理長 context 的關鍵。它的核心想法是「每個 token 決定該關注前面哪幾個 token」、用 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding&lt;/a> 之間的&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積&lt;/a> 量化「相關性」。理解 attention 後、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">Multi-head&lt;/a>、KV cache、Flash Attention、attention sink 等術語都能放到正確位置。&lt;/p>
&lt;p>本章從「為什麼需要 attention」開始、拆 scaled dot-product attention 公式、再展開 multi-head attention 跟 causal masking、最後接到 KV cache 與長 context 場景。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>用 Q / K / V 三個角色解釋 attention 在算什麼。&lt;/li>
&lt;li>看到 attention 公式時、能解讀每個運算的角色。&lt;/li>
&lt;li>解釋 multi-head attention 跟 single-head 的取捨。&lt;/li>
&lt;li>把 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 跟 attention 公式對上。&lt;/li>
&lt;/ol>
&lt;h2 id="為什麼需要-attention">為什麼需要 attention&lt;/h2>
&lt;p>LLM 處理「下一個 token 該是什麼」、需要綜合 prompt 中前面所有 token 的資訊。早期解法（RNN、LSTM）用「序列狀態」串接、每個 token 只看到上一步的 hidden state。缺點：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>長距離依賴難&lt;/strong>：訊息傳遞要跑過所有中間 token、容易遺失。&lt;/li>
&lt;li>&lt;strong>無法並行&lt;/strong>：每步依賴上一步、訓練速度有瓶頸。&lt;/li>
&lt;/ol>
&lt;p>Attention 的核心突破是「每個 token 直接看所有前面的 token、無需透過中間 hidden state 傳遞」。每個 token 用 attention scores 決定「該關注哪些前面 token」、用這些 token 的向量加權求和、形成自己的 context-aware 表示。&lt;/p>
&lt;p>Attention 帶來三個性質：兩個是優勢、一個是代價：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>優勢一、長距離依賴變直接&lt;/strong>：attention 直接連到任何位置、不再需要透過 RNN 的中間 hidden state 接力。&lt;/li>
&lt;li>&lt;strong>優勢二、可以並行&lt;/strong>：不同 token 的 attention 計算彼此獨立、訓練時整段序列一次跑完。&lt;/li>
&lt;li>&lt;strong>代價、O(n²) 計算複雜度&lt;/strong>：seq_len = n 時要算 n × n 個 attention scores、長 context 場景成本暴增、見後面的 KV cache 與 Flash Attention 段。&lt;/li>
&lt;/ul>
&lt;h2 id="q--k--v-三個角色">Q / K / V 三個角色&lt;/h2>
&lt;p>Attention 給每個 token 三個向量、各自有不同角色：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>角色&lt;/th>
 &lt;th>直覺&lt;/th>
 &lt;th>數學&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Query (Q)&lt;/td>
 &lt;td>「我在找什麼」&lt;/td>
 &lt;td>Q = X @ W_Q&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Key (K)&lt;/td>
 &lt;td>「我有什麼可以被找到」&lt;/td>
 &lt;td>K = X @ W_K&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Value (V)&lt;/td>
 &lt;td>「找到我之後、要傳出去什麼」&lt;/td>
 &lt;td>V = X @ W_V&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>其中 X 是 input embedding、&lt;code>W_Q&lt;/code>、&lt;code>W_K&lt;/code>、&lt;code>W_V&lt;/code> 是三個 learnable 權重矩陣。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">Attention</a>（注意力）是 Transformer 的核心創新、也是 LLM 能處理長 context 的關鍵。它的核心想法是「每個 token 決定該關注前面哪幾個 token」、用 <a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding</a> 之間的<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積</a> 量化「相關性」。理解 attention 後、<a href="/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">Multi-head</a>、KV cache、Flash Attention、attention sink 等術語都能放到正確位置。</p>
<p>本章從「為什麼需要 attention」開始、拆 scaled dot-product attention 公式、再展開 multi-head attention 跟 causal masking、最後接到 KV cache 與長 context 場景。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>用 Q / K / V 三個角色解釋 attention 在算什麼。</li>
<li>看到 attention 公式時、能解讀每個運算的角色。</li>
<li>解釋 multi-head attention 跟 single-head 的取捨。</li>
<li>把 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 跟 attention 公式對上。</li>
</ol>
<h2 id="為什麼需要-attention">為什麼需要 attention</h2>
<p>LLM 處理「下一個 token 該是什麼」、需要綜合 prompt 中前面所有 token 的資訊。早期解法（RNN、LSTM）用「序列狀態」串接、每個 token 只看到上一步的 hidden state。缺點：</p>
<ol>
<li><strong>長距離依賴難</strong>：訊息傳遞要跑過所有中間 token、容易遺失。</li>
<li><strong>無法並行</strong>：每步依賴上一步、訓練速度有瓶頸。</li>
</ol>
<p>Attention 的核心突破是「每個 token 直接看所有前面的 token、無需透過中間 hidden state 傳遞」。每個 token 用 attention scores 決定「該關注哪些前面 token」、用這些 token 的向量加權求和、形成自己的 context-aware 表示。</p>
<p>Attention 帶來三個性質：兩個是優勢、一個是代價：</p>
<ul>
<li><strong>優勢一、長距離依賴變直接</strong>：attention 直接連到任何位置、不再需要透過 RNN 的中間 hidden state 接力。</li>
<li><strong>優勢二、可以並行</strong>：不同 token 的 attention 計算彼此獨立、訓練時整段序列一次跑完。</li>
<li><strong>代價、O(n²) 計算複雜度</strong>：seq_len = n 時要算 n × n 個 attention scores、長 context 場景成本暴增、見後面的 KV cache 與 Flash Attention 段。</li>
</ul>
<h2 id="q--k--v-三個角色">Q / K / V 三個角色</h2>
<p>Attention 給每個 token 三個向量、各自有不同角色：</p>
<table>
  <thead>
      <tr>
          <th>角色</th>
          <th>直覺</th>
          <th>數學</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Query (Q)</td>
          <td>「我在找什麼」</td>
          <td>Q = X @ W_Q</td>
      </tr>
      <tr>
          <td>Key (K)</td>
          <td>「我有什麼可以被找到」</td>
          <td>K = X @ W_K</td>
      </tr>
      <tr>
          <td>Value (V)</td>
          <td>「找到我之後、要傳出去什麼」</td>
          <td>V = X @ W_V</td>
      </tr>
  </tbody>
</table>
<p>其中 X 是 input embedding、<code>W_Q</code>、<code>W_K</code>、<code>W_V</code> 是三個 learnable 權重矩陣。</p>
<p>直覺：</p>
<ul>
<li>每個 token 同時當「找東西的人」（query）跟「被找的東西」（key + value）。</li>
<li>Query 跟其他 token 的 Key 內積、得到「該關注每個 token 多少」的分數。</li>
<li>用這些分數對所有 token 的 Value 加權求和、得到當前 token 的 context-aware 表示。</li>
</ul>
<h2 id="scaled-dot-product-attention核心公式">Scaled Dot-Product Attention：核心公式</h2>
<p>Attention（Vaswani et al., 2017）的核心公式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Attention(Q, K, V) = softmax(Q @ K^T / sqrt(d_k)) @ V</span></span></code></pre></div><p>逐步拆解：</p>
<ol>
<li><strong><code>Q @ K^T</code></strong>：所有 query 跟所有 key 兩兩內積、得到 <code>(seq_len, seq_len)</code> 矩陣。矩陣 [i][j] 等於「token i 該關注 token j 多少」的原始分數。</li>
<li><strong><code>/ sqrt(d_k)</code></strong>：scale by sqrt of key dimension。若沒有這步、d_k 大時 softmax 會極端化、訓練不穩。</li>
<li><strong><code>softmax(...)</code></strong>：對每一 row 做 <a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">softmax</a>、把分數正規化成機率分佈、保證「每個 token 對所有前面 token 的注意力總和 = 1」。</li>
<li><strong><code>@ V</code></strong>：用 attention 機率對所有 token 的 V 加權求和、得到 <code>(seq_len, d_v)</code> 的輸出。每個輸出 row 是該 token 整合了前面所有 token 資訊的 context-aware 表示。</li>
</ol>
<p>這個公式叫 <strong>scaled dot-product attention</strong>、是 Transformer 的核心運算。</p>
<h2 id="multi-head-attention多個-attention-並行"><a href="/blog/llm/knowledge-cards/multi-head-attention/" data-link-title="Multi-Head Attention" data-link-desc="把 attention 切成多個 head 並行計算、讓模型能同時注意多種模式">Multi-Head Attention</a>：多個 attention 並行</h2>
<p>Multi-head attention 的核心想法是「跑 N 個獨立的 attention、每個 head 各自有自己的 W_Q / W_K / W_V、結果 concatenate 再過一個線性層」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">head_i = Attention(Q W_Q_i, K W_K_i, V W_V_i)
</span></span><span class="line"><span class="ln">2</span><span class="cl">MultiHead(Q, K, V) = Concat(head_1, ..., head_h) @ W_O</span></span></code></pre></div><p>幾何意義：每個 head 學「關注一種 pattern」。例如：</p>
<ul>
<li>Head 1 可能學到「關注名詞的修飾語」。</li>
<li>Head 2 可能學到「關注前後標點」。</li>
<li>Head 3 可能學到「關注 quotation 邊界」。</li>
</ul>
<p>實驗發現不同 head 確實學到可解釋的功能（雖然多數 head 的功能難以直觀標籤）。在主流規模（hidden_dim ≥ 768、num_heads ≥ 8）下、multi-head 比 single-head 表達能力強；極小模型（hidden_dim &lt; 256）下 multi-head 收益遞減、有時 single-head 更穩定。</p>
<p>主流 LLM 的 head 數：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>num_heads</th>
          <th>head_dim</th>
          <th>hidden_dim</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-2 small</td>
          <td>12</td>
          <td>64</td>
          <td>768</td>
      </tr>
      <tr>
          <td>Llama 3 8B</td>
          <td>32</td>
          <td>128</td>
          <td>4096</td>
      </tr>
      <tr>
          <td>Llama 3 70B</td>
          <td>64</td>
          <td>128</td>
          <td>8192</td>
      </tr>
      <tr>
          <td>Gemma 4 31B</td>
          <td>約 40</td>
          <td>約 128</td>
          <td>約 5120</td>
      </tr>
  </tbody>
</table>
<p>關係：<code>hidden_dim = num_heads × head_dim</code>。每個 head 處理 head_dim 維、parallel 跑完再 concatenate 回 hidden_dim。</p>
<h2 id="causal-mask只看前面不看後面">Causal Mask：只看前面、不看後面</h2>
<p>LLM 是 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">autoregressive</a>、生成 token N 時只能看 token 0 到 N-1、不能看後面（後面還沒生）。Attention 機制要「擋掉未來位置」、用 <strong><a href="/blog/llm/knowledge-cards/causal-mask/" data-link-title="Causal Mask" data-link-desc="在 self-attention 裡擋掉「未來位置」的遮罩、讓 LLM 自回歸生成在訓練時也成立">causal mask</a></strong> 實現：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">masked_scores[i][j] = scores[i][j]   if j ≤ i
</span></span><span class="line"><span class="ln">2</span><span class="cl">                    = -∞              if j &gt; i</span></span></code></pre></div><p>把未來位置的 attention score 設為 -∞、softmax 後機率為 0、等於完全忽略未來。</p>
<p>實作上 mask 是一個下三角矩陣、訓練跟推論時都套用、但角色不同：</p>
<ul>
<li><strong>訓練時的 causal mask</strong>：讓 decoder 能「一次 forward pass 算所有 N 個 token 的 loss」、parallel 訓練。沒有 mask 就要對每個位置跑 N 次 forward（位置 i 只給 token 0 ~ i-1）、訓練速度掉一個量級。這是 Transformer 取代 RNN 在訓練效率上的關鍵。</li>
<li><strong>推論時的 causal mask</strong>：每生新 token 只看前面已生的 token、不能 peek 未來。實際因為 token 是按順序生成的、未來位置本來就還沒存在、mask 更像是「沿用訓練階段的同套運算結構、避免訓練 / 推論 mismatch」。</li>
</ul>
<p>「Decoder-only LLM」（GPT、Llama 系列）用 causal mask 做自回歸生成；「Encoder-only LLM」（BERT 等）不用 causal mask、可看雙向 context、適合分類 / NER 等理解任務、不走自回歸生成路徑；「Encoder-Decoder」（T5、BART）encoder 看雙向、decoder 用 causal mask、可生成、是另一條典型架構。</p>
<h2 id="kv-cache避免重複計算">KV Cache：避免重複計算</h2>
<p><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV Cache</a> 是 attention 機制下的關鍵優化。回到 attention 公式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Attention(Q, K, V) = softmax(Q @ K^T / sqrt(d_k)) @ V</span></span></code></pre></div><p>生成 token N 時：</p>
<ul>
<li>Q 是 token N 對應的 query（新的）。</li>
<li>K、V 是 token 0 到 N-1 的 key / value（前面都算過）。</li>
</ul>
<p>如果每生一個 token 都重新算 K、V、會浪費大量計算。KV cache 把 K、V 存起來、下次生 token N+1 時：</p>
<ul>
<li>Q 是 token N+1 的新 query。</li>
<li>K、V 是 cache + 新 token 的 K、V。</li>
</ul>
<p>只算 token N+1 對應的 K、V 新值、跟既有 cache concat。每生一個 token 的計算量從 O(n²) 降到 O(n)。</p>
<p>代價是 KV cache 隨 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 線性增長、長 context 場景吃記憶體。Gemma 4 31B 在 32GB Mac 上實用 context 約 8 ~ 16K tokens、超過會 swap。記憶體吃緊時的 KV cache 量化（K=Q8 / V=Q4）原理與 context / 併發取捨見 <a href="/blog/llm/05-discrete-gpu/kv-cache-quantization-strategy/" data-link-title="5.2 KV cache 量化策略" data-link-desc="PC 場景用 K=Q8 / V=Q4 等量化把 KV cache 壓縮、騰出 VRAM 開大 context window 或加併發數的判讀">模組五 5.2 KV cache 量化策略</a>、整體 VRAM 預算見 <a href="/blog/llm/05-discrete-gpu/vram-ram-budget/" data-link-title="5.0 VRAM &#43; RAM 分層預算" data-link-desc="PC 獨立 GPU 場景的記憶體預算判讀：VRAM 是快的世界、RAM 是大的世界、PCIe 把兩個世界連起來">5.0 VRAM + RAM 分層預算</a>。</p>
<h2 id="flash-attention記憶體高效實作">Flash Attention：記憶體高效實作</h2>
<p>Flash Attention（Dao et al., 2022）是 attention 的 GPU 高效實作。標準 attention 在記憶體中具體實作 <code>(seq_len, seq_len)</code> 矩陣、長 context 時記憶體爆炸（10K context = 100M 個 float）。</p>
<p>Flash Attention 用「tiling + recompute」技巧、把 attention 拆成 block 算、不具體實作完整 attention matrix。記憶體佔用從 O(n²) 降到 O(n)、速度也快 2 ~ 4 倍。</p>
<p>Apple Silicon 上的對應實作可能稱為 Metal FlashAttention 或類似名稱、Ollama、LM Studio、oMLX 等本地推論伺服器逐步整合。</p>
<p>Flash Attention 何時收益有限：</p>
<ul>
<li><strong>短 context 場景</strong>：seq_len &lt; 1K 時、attention matrix 本身就小、Flash Attention 的記憶體節省無感。</li>
<li><strong>CPU 推論</strong>：Flash Attention 的 tiling 設計針對 GPU memory hierarchy（HBM ↔ SRAM）、CPU 上的記憶體層級不同、收益遠小於 GPU。</li>
<li><strong>配合 GQA 的場景</strong>：GQA 已大幅減少 KV cache、Flash Attention 的相對收益縮小。</li>
</ul>
<h2 id="grouped-query-attentiongqa"><a href="/blog/llm/knowledge-cards/grouped-query-attention/" data-link-title="Grouped-Query Attention" data-link-desc="讓多個 query head 共用較少的 key/value head，以降低 KV cache 體積與推論記憶體壓力">Grouped Query Attention（GQA）</a></h2>
<p>Grouped Query Attention 是 multi-head attention 的變體、減少 KV cache 佔用。核心想法：「不同 head 共用 K、V、只有 Q 各自獨立」。</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>Q heads</th>
          <th>K/V heads</th>
          <th>特性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Multi-Head Attention (MHA)</td>
          <td>N</td>
          <td>N</td>
          <td>標準、各 head 完全獨立</td>
      </tr>
      <tr>
          <td>Multi-Query Attention (MQA)</td>
          <td>N</td>
          <td>1</td>
          <td>所有 head 共用一組 K/V、最省記憶體</td>
      </tr>
      <tr>
          <td>Grouped Query Attention (GQA)</td>
          <td>N</td>
          <td>K (K &lt; N)</td>
          <td>折衷、品質接近 MHA、KV cache 較小</td>
      </tr>
  </tbody>
</table>
<p>Llama 3 / Gemma 4 / Qwen3 都用 GQA、把 KV cache 大小減半到三分之一、長 context 場景受益。</p>
<h2 id="為什麼-speculative-decoding-在-code-場景加速明顯attention-並行性的支撐">為什麼 speculative decoding 在 code 場景加速明顯：attention 並行性的支撐</h2>
<p>加速本身來自 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> / <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a>、attention 在這條路徑上的角色是「提供並行驗證所需的計算結構」：</p>
<ul>
<li>Speculative decoding 一次驗證 N 個 token、需要 attention 同時處理 N 個 query 對前面所有 K/V。</li>
<li>Attention 機制天生可並行、一次 forward pass 驗證 N 個 token 跟驗證 1 個 token 的時間接近（瓶頸是讀權重而非算 attention）。</li>
<li>寫 code 場景 drafter 接受率高（code 的 pattern 容易預測）、加速明顯。</li>
</ul>
<p>理解這點、能解釋為什麼 MTP 對 coding 比創意寫作加速更明顯：差別不在 attention 本身、在「drafter 預測的接受率」這個 sampling 層的變數。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 Transformer 架構</a>、把 attention 跟 embedding 組裝成完整模型。</p>
]]></content:encoded></item><item><title>3.3 Transformer 架構細節</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/transformer-architecture/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/transformer-architecture/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer&lt;/a> 把 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention&lt;/a> 組合成完整 forward pass 結構。LLM 用的是「decoder-only Transformer」、跟原始 paper（Vaswani et al., 2017）的 encoder-decoder 結構不同。本章把現代 LLM（Llama / Gemma / Qwen 系列）的 Transformer 架構走過一遍、解釋每個組件的角色。&lt;/p>
&lt;p>理解整個架構後、看 LLM paper 中的「residual stream」「pre-norm vs post-norm」「FFN」「MoE」等術語都能對到具體位置。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>畫出一個 Transformer block 的結構。&lt;/li>
&lt;li>解釋 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/positional-encoding/" data-link-title="Positional Encoding" data-link-desc="把 token 位置資訊注入 Transformer 的機制，讓 attention 能分辨順序與距離">positional encoding&lt;/a> 的角色與選擇。&lt;/li>
&lt;li>看到 RMSNorm、SwiGLU 等術語時、知道是 layer norm / activation 的變體。&lt;/li>
&lt;li>解釋為什麼現代 LLM 普遍用 decoder-only 架構。&lt;/li>
&lt;/ol>
&lt;h2 id="encoder-vs-decoder兩種-transformer">Encoder vs Decoder：兩種 Transformer&lt;/h2>
&lt;p>原始 Transformer paper 提出 encoder-decoder 結構、用於機器翻譯：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Encoder&lt;/strong>：處理 input sequence、產生 contextual embedding。雙向 attention（每個 token 可看所有 token）。&lt;/li>
&lt;li>&lt;strong>Decoder&lt;/strong>：根據 encoder 輸出 + 已生成 tokens、產生下一個 token。Causal attention（只看前面）。&lt;/li>
&lt;/ul>
&lt;p>後續發展出三種主流變體：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類型&lt;/th>
 &lt;th>例子&lt;/th>
 &lt;th>適合任務&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Encoder-only&lt;/td>
 &lt;td>BERT、RoBERTa&lt;/td>
 &lt;td>分類、實體識別、retrieval&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Decoder-only&lt;/td>
 &lt;td>GPT、Llama、Gemma&lt;/td>
 &lt;td>生成、對話、寫 code&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Encoder-Decoder&lt;/td>
 &lt;td>T5、BART&lt;/td>
 &lt;td>翻譯、摘要、seq-to-seq&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>寫 code 場景接觸到的所有主流 LLM（GPT、Claude、Gemma、Llama、Qwen）都是 &lt;strong>decoder-only&lt;/strong>、只用 causal attention、用「文字接龍」方式做所有任務（chat、寫 code、翻譯都統一成「給前面文字、生成後面文字」）。&lt;/p>
&lt;p>本章其他部分聚焦 decoder-only 結構。&lt;/p>
&lt;h2 id="整體-forward-pass">整體 forward pass&lt;/h2>
&lt;p>Decoder-only Transformer 的 forward pass：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">input tokens [t1, t2, ..., tn]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> ↓ embedding lookup
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">embeddings [e1, e2, ..., en] (shape: seq_len × hidden_dim)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> ↓ + positional encoding（如 RoPE）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">positioned embeddings
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> ↓ Transformer block 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> ↓ Transformer block 2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> ↓ ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓ Transformer block N（30 ~ 80 層）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">final hidden states
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> ↓ final layer norm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">normalized states
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> ↓ output projection
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">logits [vocab_size]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> ↓ softmax
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">下個 token 的機率分佈&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>每個 Transformer block 內部結構（後面展開）。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/transformer/" data-link-title="Transformer" data-link-desc="寫 code 用的 LLM 神經網路架構：基於 attention 機制、自回歸生成 token">Transformer</a> 把 <a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">embedding</a> 與 <a href="/blog/llm/knowledge-cards/attention/" data-link-title="Attention" data-link-desc="Transformer 內部讓每個 token 對其他 token 加權平均的核心機制、形成 KV cache 跟 context window 的計算基礎">attention</a> 組合成完整 forward pass 結構。LLM 用的是「decoder-only Transformer」、跟原始 paper（Vaswani et al., 2017）的 encoder-decoder 結構不同。本章把現代 LLM（Llama / Gemma / Qwen 系列）的 Transformer 架構走過一遍、解釋每個組件的角色。</p>
<p>理解整個架構後、看 LLM paper 中的「residual stream」「pre-norm vs post-norm」「FFN」「MoE」等術語都能對到具體位置。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>畫出一個 Transformer block 的結構。</li>
<li>解釋 <a href="/blog/llm/knowledge-cards/positional-encoding/" data-link-title="Positional Encoding" data-link-desc="把 token 位置資訊注入 Transformer 的機制，讓 attention 能分辨順序與距離">positional encoding</a> 的角色與選擇。</li>
<li>看到 RMSNorm、SwiGLU 等術語時、知道是 layer norm / activation 的變體。</li>
<li>解釋為什麼現代 LLM 普遍用 decoder-only 架構。</li>
</ol>
<h2 id="encoder-vs-decoder兩種-transformer">Encoder vs Decoder：兩種 Transformer</h2>
<p>原始 Transformer paper 提出 encoder-decoder 結構、用於機器翻譯：</p>
<ul>
<li><strong>Encoder</strong>：處理 input sequence、產生 contextual embedding。雙向 attention（每個 token 可看所有 token）。</li>
<li><strong>Decoder</strong>：根據 encoder 輸出 + 已生成 tokens、產生下一個 token。Causal attention（只看前面）。</li>
</ul>
<p>後續發展出三種主流變體：</p>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>例子</th>
          <th>適合任務</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Encoder-only</td>
          <td>BERT、RoBERTa</td>
          <td>分類、實體識別、retrieval</td>
      </tr>
      <tr>
          <td>Decoder-only</td>
          <td>GPT、Llama、Gemma</td>
          <td>生成、對話、寫 code</td>
      </tr>
      <tr>
          <td>Encoder-Decoder</td>
          <td>T5、BART</td>
          <td>翻譯、摘要、seq-to-seq</td>
      </tr>
  </tbody>
</table>
<p>寫 code 場景接觸到的所有主流 LLM（GPT、Claude、Gemma、Llama、Qwen）都是 <strong>decoder-only</strong>、只用 causal attention、用「文字接龍」方式做所有任務（chat、寫 code、翻譯都統一成「給前面文字、生成後面文字」）。</p>
<p>本章其他部分聚焦 decoder-only 結構。</p>
<h2 id="整體-forward-pass">整體 forward pass</h2>
<p>Decoder-only Transformer 的 forward pass：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">input tokens [t1, t2, ..., tn]
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  ↓ embedding lookup
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">embeddings [e1, e2, ..., en]   (shape: seq_len × hidden_dim)
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓ + positional encoding（如 RoPE）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">positioned embeddings
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  ↓ Transformer block 1
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  ↓ Transformer block 2
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  ↓ ...
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  ↓ Transformer block N（30 ~ 80 層）
</span></span><span class="line"><span class="ln">10</span><span class="cl">final hidden states
</span></span><span class="line"><span class="ln">11</span><span class="cl">  ↓ final layer norm
</span></span><span class="line"><span class="ln">12</span><span class="cl">normalized states
</span></span><span class="line"><span class="ln">13</span><span class="cl">  ↓ output projection
</span></span><span class="line"><span class="ln">14</span><span class="cl">logits [vocab_size]
</span></span><span class="line"><span class="ln">15</span><span class="cl">  ↓ softmax
</span></span><span class="line"><span class="ln">16</span><span class="cl">下個 token 的機率分佈</span></span></code></pre></div><p>每個 Transformer block 內部結構（後面展開）。</p>
<h2 id="transformer-block架構核心">Transformer Block：架構核心</h2>
<p>一個 Transformer block 包含兩個 sub-layer、各自前後加 layer norm 跟 residual connection。現代 LLM 用的「pre-norm」結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">input x
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">norm 1 (RMSNorm)
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">multi-head attention（causal）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">+ x（residual connection）
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">中間結果 y
</span></span><span class="line"><span class="ln">10</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">11</span><span class="cl">norm 2 (RMSNorm)
</span></span><span class="line"><span class="ln">12</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">13</span><span class="cl">FFN（feed-forward network）
</span></span><span class="line"><span class="ln">14</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">15</span><span class="cl">+ y（residual connection）
</span></span><span class="line"><span class="ln">16</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">17</span><span class="cl">output</span></span></code></pre></div><p>兩個關鍵組件：</p>
<ol>
<li><strong>Multi-head attention</strong>：見 <a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2</a>、Q/K/V 來源同 sequence 的部分見 <a href="/blog/llm/knowledge-cards/self-attention/" data-link-title="Self-Attention" data-link-desc="Q / K / V 都從同一個 sequence 投影出來的 attention、Transformer 的標誌性設計">self-attention</a> 卡。</li>
<li><strong><a href="/blog/llm/knowledge-cards/ffn/" data-link-title="FFN（Feed-Forward Network）" data-link-desc="Transformer block 內部的兩層 linear &#43; activation、佔模型參數量的多數">FFN</a></strong>（feed-forward network）：兩層 <a href="/blog/llm/03-theoretical-foundations/neural-network-basics/" data-link-title="3.0 神經網路基礎" data-link-desc="從單一 neuron 到 multi-layer：weights、activation function、forward / backward pass 的角色">linear layer</a> + 非線性 <a href="/blog/llm/knowledge-cards/activation-function/" data-link-title="Activation Function" data-link-desc="在 linear layer 之間插入的非線性函數、讓神經網路能表達非線性關係">activation</a>。</li>
</ol>
<p>每個 sub-layer 前後加 <strong><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">residual connection</a></strong>：把 sub-layer 的輸出加回 input、形成「主流」。這個結構讓 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 容易在深層網路中傳遞、解決 <a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">gradient vanishing</a> 問題。</p>
<h2 id="feed-forward-networkffn">Feed-Forward Network（FFN）</h2>
<blockquote>
<p>符號 legend：以下公式中 <code>@</code> 表矩陣乘法、<code>⊙</code> 表逐元素乘（Hadamard product）、<code>x</code> 是 hidden vector。</p></blockquote>
<p>FFN 是 Transformer block 中的第二個 sub-layer、結構是「升維 → activation → 降維」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">FFN(x) = activation(x @ W1) @ W2</span></span></code></pre></div><p>其中：</p>
<ul>
<li><code>W1</code> shape: <code>(hidden_dim, intermediate_dim)</code></li>
<li><code>W2</code> shape: <code>(intermediate_dim, hidden_dim)</code></li>
<li><code>intermediate_dim</code> 通常是 hidden_dim 的 2.5 ~ 4 倍</li>
</ul>
<p>例：Llama 3 8B、hidden_dim 4096、intermediate_dim 14336（約 3.5x）。FFN 是模型大部分參數的來源（attention 的 W_Q/K/V 只佔少數）。</p>
<p><code>intermediate_dim</code> 比例的邊界：低於 2.5x 時 FFN 的「升維 → 過 activation → 降維」表達能力不足、模型 capacity 跟訓練資料 fit 變差；高於 4x 時邊際參數收益遞減、且推論成本線性增加、不划算。SwiGLU / GeGLU 因為內部有兩個 projection、實作上 <code>intermediate_dim</code> 會略低（約 2/3）抵消多出來的參數量。</p>
<p>Activation 選擇：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>FFN Activation</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-2</td>
          <td>GELU</td>
      </tr>
      <tr>
          <td>Llama 系列</td>
          <td>SwiGLU</td>
      </tr>
      <tr>
          <td>Gemma 系列</td>
          <td>GeGLU</td>
      </tr>
      <tr>
          <td>Qwen3 系列</td>
          <td>SwiGLU</td>
      </tr>
  </tbody>
</table>
<p>SwiGLU / GeGLU 屬於 <strong>gated linear unit (GLU) 家族</strong>、用兩個 linear projection、其中一個過 activation 當 gate：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">SwiGLU(x) = (x @ W1) ⊙ SiLU(x @ W3) @ W2</span></span></code></pre></div><p><code>SiLU(x) = x × sigmoid(x)</code>（Swish 的別名）、產出「平滑版的 ReLU」。實驗發現 GLU 家族比純 GELU 略好、是現代 LLM 主流。</p>
<h2 id="layer-normalization穩定訓練">Layer Normalization：穩定訓練</h2>
<p><a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">Layer normalization</a>（layer norm）的核心定義是「把每個 token 的 hidden vector 重新正規化到 mean=0、variance=1、再用 learnable scale / shift 調整」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">LayerNorm(x) = γ ⊙ (x - mean(x)) / sqrt(var(x) + ε) + β</span></span></code></pre></div><p>其中 γ、β 是 learnable 參數。</p>
<p>LLM 用的變體：</p>
<table>
  <thead>
      <tr>
          <th>變體</th>
          <th>機制</th>
          <th>用在</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LayerNorm</td>
          <td>mean + variance 都正規化</td>
          <td>GPT-2</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/layer-normalization/" data-link-title="Layer Normalization" data-link-desc="在每個 token 的 hidden state 上做正規化（減 mean、除 std）、穩定深層網路訓練">RMSNorm</a></td>
          <td>只用 root-mean-square、不算 mean</td>
          <td>Llama / Gemma / Qwen 系列</td>
      </tr>
  </tbody>
</table>
<p>RMSNorm 比標準 LayerNorm 簡單、計算稍快、品質接近、在大型 LLM（&gt;7B）上是主流；小模型 / 訓練不穩定需要強正規化的場景下、LayerNorm 仍有實際貢獻。</p>
<h2 id="pre-norm-vs-post-norm">Pre-Norm vs Post-Norm</h2>
<p>Layer norm 的位置有兩個選擇：</p>
<ul>
<li><strong>Post-norm</strong>（原始 Transformer paper）：先做 attention / FFN、再加 residual、再 layer norm。深層網路訓練不穩、但搭配特殊 init / warmup / 較淺層數（&lt; 12 層）仍可用、encoder-only 模型（BERT）跟特定 transformer variant 仍走這條。</li>
<li><strong>Pre-norm</strong>（現代 LLM 主流）：先 layer norm、再做 attention / FFN、再加 residual。訓練穩定、深層網路才能訓得起來。</li>
</ul>
<p>大型現代 LLM（Llama / Gemma / Qwen / GPT-3+）幾乎都用 pre-norm。Post-norm 在淺層 encoder 或需要 strict bottleneck 的場景仍有實際用途。</p>
<h2 id="residual-connection殘差連接">Residual Connection（殘差連接）</h2>
<p><a href="/blog/llm/knowledge-cards/residual-connection/" data-link-title="Residual Connection" data-link-desc="把 layer 的輸入直接加到輸出上的「跳接」、讓深層網路的梯度能穩定回流">Residual connection</a> 的核心定義是「sub-layer 的輸出加回它的 input」：<code>output = sublayer(x) + x</code>。這個結構由 ResNet（He et al., 2015）首先廣泛採用、Transformer 跟現代深度網路都用。跨層持續傳遞的 hidden state 主通道見 <a href="/blog/llm/knowledge-cards/residual-stream/" data-link-title="Residual Stream" data-link-desc="Transformer block 之間持續傳遞與累積資訊的 hidden state 通道，常用於架構與 mechanistic interpretability 討論">residual stream</a>。</p>
<p>效果：</p>
<ol>
<li><strong>Gradient 直接傳遞</strong>：backward pass 中 gradient 可直接從深層流回淺層、避免 vanishing。</li>
<li><strong>Identity 是 default</strong>：若 sub-layer 學壞、residual 確保至少不退步（output = x）。</li>
<li><strong>Residual stream 概念</strong>：模型內部可視為一個「主流」、每層 sub-layer 對它做 incremental update。這個視角是現代可解釋性研究（mechanistic interpretability）的核心。</li>
</ol>
<h2 id="positional-encoding把順序加進去">Positional Encoding：把順序加進去</h2>
<p><a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">Embedding</a> 章節提到 attention 機制本身沒有順序資訊。Positional encoding 把位置資訊注入、讓 <code>[cat, dog]</code> 跟 <code>[dog, cat]</code> 有區別。主流方法：</p>
<h3 id="sinusoidal原始-transformer">Sinusoidal（原始 Transformer）</h3>
<p>用 sin / cos 不同頻率生成位置向量、加進 token embedding：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
</span></span><span class="line"><span class="ln">2</span><span class="cl">PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))</span></span></code></pre></div><p>固定值、不訓練。早期 GPT 用、後續被學習式取代。</p>
<h3 id="learned-positional-embedding">Learned Positional Embedding</h3>
<p>訓練一個 <code>(max_seq_len, hidden_dim)</code> 的矩陣、每個位置一個 embedding、加進 token embedding。GPT-2 用、簡單但有 max_seq_len 限制。</p>
<h3 id="rotary-position-embeddingrope">Rotary Position Embedding（RoPE）</h3>
<p><a href="/blog/llm/knowledge-cards/rope/" data-link-title="RoPE（Rotary Position Embedding）" data-link-desc="用旋轉矩陣把位置資訊直接旋轉進 Q/K 向量、現代 LLM 主流的位置編碼方式">RoPE</a>（Su et al., 2021）的核心想法是「不加位置 embedding、而是把 Q 跟 K 在每個 attention head 內做位置相關的旋轉」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">RoPE(Q, position) = 把 Q 的 2D 子空間按 position 旋轉特定角度</span></span></code></pre></div><p>旋轉的直覺：兩個 token 在 RoPE 旋轉後做內積、結果只跟「兩者的位置差」相關、跟「絕對位置」無關。所以 RoPE 的內積天然編碼相對位置、attention 看到的是「token i 跟 token j 相隔多遠」、不是「token i 在第 N 個位置」。</p>
<p>優點：</p>
<ul>
<li><strong>相對位置</strong>：attention 看的是兩個 token 的相對距離、不是絕對位置。</li>
<li><strong>無 max_seq_len</strong>：理論上可外推到任意長度（實務 degradation：超過訓練長度 4x 後品質明顯下降、超過 8x 後幾乎無用、要搭配 RoPE scaling / YaRN 等技巧）。</li>
<li><strong>可訓練 + 不需要額外參數</strong>：旋轉角度固定、不增加模型參數。</li>
</ul>
<p>Llama 系列、Gemma 系列、Qwen 系列都用 RoPE、目前主流。</p>
<h3 id="alibiattention-with-linear-biases">ALiBi（Attention with Linear Biases）</h3>
<p>ALiBi 的核心想法是「在 attention scores 加一個位置 bias、距離越遠 bias 越負」、attention 自然傾向關注近處。MosaicML 的 MPT 系列用、長 context 外推性質佳。</p>
<h2 id="長-context-的擴展技巧">長 Context 的擴展技巧</h2>
<p>LLM 在訓練長度（如 8K）以外的 context 上品質會 degradation。擴展長 context 的方法：</p>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>機制</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RoPE scaling</td>
          <td>把 RoPE 的旋轉頻率縮小、attention 看「更遠」</td>
      </tr>
      <tr>
          <td>YaRN</td>
          <td>RoPE scaling 的改進、保留近距精度</td>
      </tr>
      <tr>
          <td>NTK-aware scaling</td>
          <td>另一種 RoPE 頻率調整方法</td>
      </tr>
      <tr>
          <td>Position interpolation</td>
          <td>把位置 ID 縮放到訓練範圍內</td>
      </tr>
  </tbody>
</table>
<p>主流 LLM 在預訓練後做這些 scaling、把 context window 從 8K / 32K 擴展到 128K / 1M。代價是長 context 上的精度逐步下降、實用上界 &lt; 聲稱上界。</p>
<p>詳見 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 卡片。</p>
<h2 id="output-projection從-hidden-到-logits">Output Projection：從 hidden 到 logits</h2>
<p><a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">Forward pass</a> 最後一步是把最終 hidden states 投射到 vocab size、得到 <a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logits</a>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">logits = final_hidden_states @ W_output</span></span></code></pre></div><p><code>W_output</code> shape: <code>(hidden_dim, vocab_size)</code>。</p>
<p>Gemma 4 31B 的 output projection 參數約 1.3B（hidden 5120 × vocab 256,000）、跟 input embedding 同量級。如果 tied（共用權重）就只算一次；現代 LLM 多半 untied、兩者獨立。</p>
<p>Output 後接 <a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a> 轉成下個 token 的機率分佈、進入 <a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">sampling</a> 流程。</p>
<h2 id="mixture-of-expertsmoe">Mixture of Experts（MoE）</h2>
<p><a href="/blog/llm/knowledge-cards/moe/" data-link-title="Mixture of Experts (MoE)" data-link-desc="把 transformer 的 FFN 層拆成多個專家、每 token 只啟用少數、總參數大但每 token 計算量小的架構">Mixture of Experts</a> 是 FFN 的擴展、把單個 FFN 換成 N 個 expert、每個 token 只 route 到 K 個 expert（K &laquo; N）。例如 Mixtral 8x7B：</p>
<ul>
<li>每層有 8 個 expert FFN。</li>
<li>每個 token 由 router 選 2 個 expert 處理。</li>
<li>總參數約 47B、但每個 token 只啟動 12B 左右。</li>
</ul>
<p>優點：總參數可超大、推論時實際算力只用一小部分。缺點：記憶體仍要載入全部 expert、訓練更複雜。</p>
<p>DeepSeek-V3、Qwen2-MoE、Mixtral 等是知名 MoE 模型。寫 code 場景的 Apple Silicon Mac 上 MoE 較少當主力、原因是「總參數要塞進統一記憶體（容量壓力大）」但「速度受限的是啟用權重的頻寬（速度反而可能還好）」、容量 vs 頻寬的 trade-off 跟 dense 模型不同。PC 獨立 GPU 場景可以走 CPU 卸載專家層的路徑、見 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU 卸載</a>。</p>
<p>MoE 的常見失敗模式：</p>
<ul>
<li><strong>Router collapse</strong>：訓練時所有 token 都 route 到同幾個 expert、其他 expert 完全沒學到東西。修法是加 auxiliary loss 鼓勵 load balancing。</li>
<li><strong>Load imbalance</strong>：推論時某些 expert 太熱門、batch 內排隊；某些 expert 閒置浪費。Production deployment 要監控 per-expert utilization。</li>
<li><strong>Memory 壓力高於 dense</strong>：總參數塞滿記憶體、但推論時實際算量只用其中一部分、容量利用率低。記憶體預算吃緊時 dense 模型反而較合適。</li>
</ul>
<h2 id="為什麼-llm-是-decoder-only">為什麼 LLM 是 decoder-only</h2>
<p>現代 LLM 普遍用 decoder-only 架構、背後有幾個理由：</p>
<ol>
<li><strong>任務統一性</strong>：「文字接龍」框架可以包進對話、寫 code、翻譯、摘要等所有任務。</li>
<li><strong>訓練效率</strong>：causal mask 讓所有位置可以並行訓練（每個 token 都當訓練目標）。</li>
<li><strong>In-context learning</strong>：decoder-only 在 few-shot prompting 上特別強。</li>
</ol>
<p>GPT-3 證明這套之後、整個產業靠攏 decoder-only。Encoder-decoder（T5 系列）仍有研究價值、但商業 LLM 主流都是 decoder-only。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 訓練流程</a>、解釋這些權重怎麼學出來。</p>
]]></content:encoded></item><item><title>3.4 訓練流程：pre-train → SFT → RLHF</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/training-pipeline/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/training-pipeline/</guid><description>&lt;p>現代 LLM 的訓練分三個階段：&lt;strong>pre-training&lt;/strong>（預訓練）、&lt;strong>supervised fine-tuning（SFT、指令微調）&lt;/strong>、&lt;strong>alignment&lt;/strong>（傳統用 RLHF、近年也用 DPO 等替代方案）。每個階段目標不同、資料不同、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function&lt;/a> 不同。理解這條鏈、能解釋為什麼「Gemma 4 31B base」跟「Gemma 4 31B instruct」是兩個版本、為什麼 fine-tuning 需要慎重、為什麼 RLHF 對對話品質這麼關鍵。&lt;/p>
&lt;p>本章從預訓練的 next-token prediction 開始、進入 instruction tuning、最後展開 RLHF 與其替代方案。寫 code 場景的使用者通常不會自己跑這些訓練、但理解流程能解釋模型行為跟版本差異。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model&lt;/a> 的訓練差異。&lt;/li>
&lt;li>解釋 RLHF 為什麼影響 LLM 的對話風格。&lt;/li>
&lt;li>區分 SFT、RLHF、DPO、LoRA 在訓練流程中的位置。&lt;/li>
&lt;li>理解「fine-tuning 為什麼可能讓模型變差」。&lt;/li>
&lt;/ol>
&lt;h2 id="階段-1pre-training預訓練">階段 1：Pre-training（預訓練）&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">Pre-training&lt;/a> 的核心目標是「從大量未標註文字學語言模型」、用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">next-token prediction&lt;/a> 當訓練 objective。&lt;/p>
&lt;h3 id="流程">流程&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>資料&lt;/strong>：trillion token 級別的網路文字、書籍、code、論文。常見資料集如 Common Crawl、RefinedWeb、The Pile、Stack、Wikipedia。&lt;/li>
&lt;li>&lt;strong>任務&lt;/strong>：「給前 N 個 token、預測第 N+1 個 token」。&lt;/li>
&lt;li>&lt;strong>Loss&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy&lt;/a> loss、衡量模型預測機率分佈跟實際下一個 token（one-hot）的差距、由 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation&lt;/a> 算出 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient&lt;/a> 更新權重。詳細展開見 &lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">2.1 機率與資訊論&lt;/a>。&lt;/li>
&lt;li>&lt;strong>訓練量&lt;/strong>：數十億 GPU-hour、數百到數萬個 GPU 並行、訓練數週到數月。&lt;/li>
&lt;li>&lt;strong>結果&lt;/strong>：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model&lt;/a>、會做文字接龍、但對話能力有限。&lt;/li>
&lt;/ol>
&lt;h3 id="為什麼-next-token-prediction-這麼有效">為什麼 next-token prediction 這麼有效&lt;/h3>
&lt;p>「給前文預測下一個 token」看起來是簡單任務、但要做好需要：&lt;/p>
&lt;ul>
&lt;li>理解語法、文法。&lt;/li>
&lt;li>理解語意、世界知識。&lt;/li>
&lt;li>理解 reasoning（推理鏈中的下一步是 token、模型要會推理才能準確預測）。&lt;/li>
&lt;li>理解 multi-step task（複雜程式碼跟複雜文章的下一個 token 也是 next-token problem）。&lt;/li>
&lt;/ul>
&lt;p>LLM 的「智能」很大程度是 next-token prediction 在大資料上的 emergent property（湧現特性）。&lt;/p>
&lt;h3 id="預訓練成本">預訓練成本&lt;/h3>
&lt;p>訓練前沿 LLM 的成本：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模型&lt;/th>
 &lt;th>估計訓練成本（美元）&lt;/th>
 &lt;th>訓練資料量&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>GPT-3 (2020)&lt;/td>
 &lt;td>~$5M&lt;/td>
 &lt;td>300B tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Llama 3 70B&lt;/td>
 &lt;td>~$30M&lt;/td>
 &lt;td>15T tokens&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GPT-4 (估)&lt;/td>
 &lt;td>$100M+&lt;/td>
 &lt;td>不公開&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訓練前沿模型&lt;/td>
 &lt;td>數億美元&lt;/td>
 &lt;td>10T+ tokens&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>預訓練是 LLM 訓練成本的 95%+。後續 fine-tuning 跟 RLHF 的成本是預訓練的零頭。&lt;/p>
&lt;h2 id="階段-2supervised-fine-tuningsft指令微調">階段 2：Supervised Fine-Tuning（SFT、指令微調）&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT&lt;/a> 的核心目標是「在 base model 上、用「指令-回答」對資料微調、讓模型會跟著指令走」。&lt;/p></description><content:encoded><![CDATA[<p>現代 LLM 的訓練分三個階段：<strong>pre-training</strong>（預訓練）、<strong>supervised fine-tuning（SFT、指令微調）</strong>、<strong>alignment</strong>（傳統用 RLHF、近年也用 DPO 等替代方案）。每個階段目標不同、資料不同、<a href="/blog/llm/knowledge-cards/loss-function/" data-link-title="Loss Function" data-link-desc="把「模型預測」跟「正確答案」的差距量化成一個純量、訓練的最佳化目標">loss function</a> 不同。理解這條鏈、能解釋為什麼「Gemma 4 31B base」跟「Gemma 4 31B instruct」是兩個版本、為什麼 fine-tuning 需要慎重、為什麼 RLHF 對對話品質這麼關鍵。</p>
<p>本章從預訓練的 next-token prediction 開始、進入 instruction tuning、最後展開 RLHF 與其替代方案。寫 code 場景的使用者通常不會自己跑這些訓練、但理解流程能解釋模型行為跟版本差異。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋 <a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a> 跟 <a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model</a> 的訓練差異。</li>
<li>解釋 RLHF 為什麼影響 LLM 的對話風格。</li>
<li>區分 SFT、RLHF、DPO、LoRA 在訓練流程中的位置。</li>
<li>理解「fine-tuning 為什麼可能讓模型變差」。</li>
</ol>
<h2 id="階段-1pre-training預訓練">階段 1：Pre-training（預訓練）</h2>
<p><a href="/blog/llm/knowledge-cards/pre-training/" data-link-title="Pre-training" data-link-desc="LLM 訓練的第一階段：用 trillion-token 級網路文字做 next-token prediction、得到 base model">Pre-training</a> 的核心目標是「從大量未標註文字學語言模型」、用 <a href="/blog/llm/knowledge-cards/autoregressive/" data-link-title="Autoregressive" data-link-desc="LLM 一次生成一個 token、把已生成內容作為下一次輸入的架構">next-token prediction</a> 當訓練 objective。</p>
<h3 id="流程">流程</h3>
<ol>
<li><strong>資料</strong>：trillion token 級別的網路文字、書籍、code、論文。常見資料集如 Common Crawl、RefinedWeb、The Pile、Stack、Wikipedia。</li>
<li><strong>任務</strong>：「給前 N 個 token、預測第 N+1 個 token」。</li>
<li><strong>Loss</strong>：<a href="/blog/llm/knowledge-cards/cross-entropy/" data-link-title="Cross-Entropy" data-link-desc="衡量「預測機率分佈」跟「真實分佈」距離的指標、LLM 預訓練的主要 loss">cross-entropy</a> loss、衡量模型預測機率分佈跟實際下一個 token（one-hot）的差距、由 <a href="/blog/llm/knowledge-cards/backpropagation/" data-link-title="Backpropagation" data-link-desc="從 output loss 反向遞推、用 chain rule 算出每個權重的 gradient 的演算法">backpropagation</a> 算出 <a href="/blog/llm/knowledge-cards/gradient/" data-link-title="Gradient" data-link-desc="loss function 對權重的偏微分向量、指出「該往哪個方向調權重才能讓 loss 下降最快」">gradient</a> 更新權重。詳細展開見 <a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">2.1 機率與資訊論</a>。</li>
<li><strong>訓練量</strong>：數十億 GPU-hour、數百到數萬個 GPU 並行、訓練數週到數月。</li>
<li><strong>結果</strong>：<a href="/blog/llm/knowledge-cards/base-model/" data-link-title="Base Model" data-link-desc="未經指令微調的原始模型：擅長文字接龍、適合下游微調用途">base model</a>、會做文字接龍、但對話能力有限。</li>
</ol>
<h3 id="為什麼-next-token-prediction-這麼有效">為什麼 next-token prediction 這麼有效</h3>
<p>「給前文預測下一個 token」看起來是簡單任務、但要做好需要：</p>
<ul>
<li>理解語法、文法。</li>
<li>理解語意、世界知識。</li>
<li>理解 reasoning（推理鏈中的下一步是 token、模型要會推理才能準確預測）。</li>
<li>理解 multi-step task（複雜程式碼跟複雜文章的下一個 token 也是 next-token problem）。</li>
</ul>
<p>LLM 的「智能」很大程度是 next-token prediction 在大資料上的 emergent property（湧現特性）。</p>
<h3 id="預訓練成本">預訓練成本</h3>
<p>訓練前沿 LLM 的成本：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>估計訓練成本（美元）</th>
          <th>訓練資料量</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-3 (2020)</td>
          <td>~$5M</td>
          <td>300B tokens</td>
      </tr>
      <tr>
          <td>Llama 3 70B</td>
          <td>~$30M</td>
          <td>15T tokens</td>
      </tr>
      <tr>
          <td>GPT-4 (估)</td>
          <td>$100M+</td>
          <td>不公開</td>
      </tr>
      <tr>
          <td>訓練前沿模型</td>
          <td>數億美元</td>
          <td>10T+ tokens</td>
      </tr>
  </tbody>
</table>
<p>預訓練是 LLM 訓練成本的 95%+。後續 fine-tuning 跟 RLHF 的成本是預訓練的零頭。</p>
<h2 id="階段-2supervised-fine-tuningsft指令微調">階段 2：Supervised Fine-Tuning（SFT、指令微調）</h2>
<p><a href="/blog/llm/knowledge-cards/sft/" data-link-title="SFT（Supervised Fine-Tuning）" data-link-desc="在 base model 上用「指令-回答」對資料微調、讓模型會跟著指令走">SFT</a> 的核心目標是「在 base model 上、用「指令-回答」對資料微調、讓模型會跟著指令走」。</p>
<h3 id="流程-1">流程</h3>
<ol>
<li><strong>資料</strong>：人類標註或 AI 生成的「prompt - response」對、數萬到數百萬個樣本。</li>
<li><strong>任務</strong>：跟 pre-training 同樣是 next-token prediction、但只對 response 部分算 loss（prompt 部分不算）。</li>
<li><strong>Loss</strong>：cross-entropy、只在 response token 上計算。</li>
<li><strong>訓練量</strong>：相對小、幾天到一週、單機可訓。</li>
<li><strong>結果</strong>：<a href="/blog/llm/knowledge-cards/instruction-tuned/" data-link-title="Instruction-Tuned Model" data-link-desc="經過指令微調的模型：會跟著 prompt 走、回答使用者問題">instruction-tuned model</a>、會跟著 prompt 走、回答使用者問題。</li>
</ol>
<h3 id="sft-的關鍵性">SFT 的關鍵性</h3>
<p>Base model 雖然有大量知識、但「問問題、給答案」的交互模式對它不自然。SFT 後同一個模型行為大改：</p>
<ul>
<li>Base model：問「寫一個 Python fibonacci」可能得到「寫一個 Python fibonacci。寫一個 JavaScript fibonacci。寫一個&hellip;」（純文字接龍）。</li>
<li>Instruction-tuned：問同樣問題、得到實際 function。</li>
</ul>
<p>寫 code 場景的所有模型都是 instruction-tuned 後的版本。Coding-tuned（如 Qwen3-Coder）是 SFT 階段大量加入 code 對話資料的特化版本。</p>
<h3 id="instruction-tuning-的資料來源">Instruction Tuning 的資料來源</h3>
<ul>
<li><strong>Human-annotated</strong>：人類寫 prompt + 回答、品質高但成本高。Anthropic、OpenAI、Meta 都有自己的標註團隊。</li>
<li><strong>AI-generated</strong>：用更強的 model（如 GPT-4）生成 prompt + 回答、品質依賴 source model。Alpaca、Vicuna 是早期例子。</li>
<li><strong>Synthetic</strong>：規則生成 + LLM 改寫。Magpie、Self-Instruct 等方法。</li>
</ul>
<p>主流模型多半混合上述三種來源。</p>
<h2 id="階段-3alignment對齊">階段 3：Alignment（對齊）</h2>
<p>Alignment 的核心目標是「進一步調整模型、讓回答符合「helpful、harmless、honest」三個維度」。SFT 後的模型可能說出有害內容、誇大事實、給平庸答案；alignment 階段解決這些問題。</p>
<h3 id="rlhfreinforcement-learning-from-human-feedback">RLHF：Reinforcement Learning from Human Feedback</h3>
<p><a href="/blog/llm/knowledge-cards/rlhf/" data-link-title="RLHF" data-link-desc="Reinforcement Learning from Human Feedback：用人類偏好訓練的 reward model 透過 RL 對齊 LLM">RLHF</a> 是 alignment 的經典方法（Ouyang et al., 2022、InstructGPT 論文）、三步驟：</p>
<h4 id="step-1reward-model">Step 1：Reward Model</h4>
<ol>
<li>收集 prompt、用模型生成多個 response。</li>
<li>人類對 response 做 pairwise 排序（「A 比 B 好」）。</li>
<li>訓練一個 reward model、輸入 (prompt, response)、輸出一個分數、最大化「人類偏好高的 response 拿高分」。</li>
</ol>
<h4 id="step-2用-ppo-最佳化模型">Step 2：用 PPO 最佳化模型</h4>
<ol>
<li>Policy = 當前的 LLM（在 RL 框架下、模型輸出的 token 分佈被視為「策略」、所以稱為 policy）。</li>
<li>用 RL（通常用 PPO 演算法、Proximal Policy Optimization、一種限制每步參數更新幅度的 RL 演算法、訓練比較穩）最佳化 policy、讓 reward model 給的分數最大化。</li>
<li>加 KL constraint：policy 不能偏離 base SFT model 太遠（用 <a href="/blog/llm/knowledge-cards/kl-divergence/" data-link-title="KL Divergence" data-link-desc="衡量「兩個機率分佈差距」的非對稱指標、RLHF / DPO 等 alignment 訓練的關鍵約束">KL divergence</a>、推導見 <a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">2.1 機率與資訊論</a>）、避免 reward hacking。</li>
</ol>
<h4 id="step-3迭代">Step 3：迭代</h4>
<p>可以再收集人類反饋、再訓 reward model、再 RL；多輪迭代。</p>
<p>RLHF 後的模型在 helpfulness、harmlessness 上明顯提升、但流程複雜、訓練不穩、reward model 易被 hack。</p>
<h3 id="dpodirect-preference-optimization">DPO：Direct Preference Optimization</h3>
<p><a href="/blog/llm/knowledge-cards/dpo/" data-link-title="DPO（Direct Preference Optimization）" data-link-desc="RLHF 的簡化替代：跳過 reward model、直接從人類偏好資料 fine-tune LLM">DPO</a>（Rafailov et al., 2023）是 RLHF 的替代方案、跳過 reward model、直接用人類偏好資料 fine-tune policy：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">loss = -log(σ(β × (log π(y_w|x)/π_ref(y_w|x) - log π(y_l|x)/π_ref(y_l|x))))</span></span></code></pre></div><p>其中：</p>
<ul>
<li>y_w：人類偏好的 response。</li>
<li>y_l：人類較不喜歡的 response。</li>
<li>π：當前 policy。</li>
<li>π_ref：reference model（通常 SFT model）。</li>
</ul>
<p>公式的直觀解讀：對每對 (好回答, 差回答)、拉高 π 給好回答的相對機率（比 π_ref 高）、壓低 π 給差回答的相對機率（比 π_ref 低）、β 控制偏離 π_ref 的力度。σ 是 sigmoid、把整體 score 壓到 (0, 1) 區間。</p>
<p>DPO 比 RLHF 簡單、不用訓 reward model、不用 RL 演算法、訓練穩定、在「離線偏好資料量充足 + 偏好相對穩定」的場景是 2024 ~ 2026 主流選擇。Llama 3、Gemma 4 等都用 DPO 或變體。</p>
<h3 id="其他替代方案">其他替代方案</h3>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>特性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RLAIF</td>
          <td>把 RLHF 中的「human feedback」換成「AI feedback」、由更強 model 評分</td>
      </tr>
      <tr>
          <td>ORPO</td>
          <td>把 SFT 跟 alignment 合併成一步、簡化流程</td>
      </tr>
      <tr>
          <td>KTO</td>
          <td>用 binary preference（好 / 不好）而非 pairwise</td>
      </tr>
      <tr>
          <td>RPO</td>
          <td>RLHF + DPO 混合方案</td>
      </tr>
  </tbody>
</table>
<p>主流前沿 LLM 用 SFT + DPO（或變體）的組合；資料量足夠 + 偏好穩定時 DPO 較佳、需要 online 人類反饋或 reward shaping（複雜環境互動、多輪偏好調整）的場景下 PPO 仍有實際空間、特別是 reasoning model（DeepSeek-R1 等）的後訓練階段。</p>
<h2 id="fine-tuning在-instruction-tuned-model-上做特化">Fine-tuning：在 instruction-tuned model 上做特化</h2>
<p>「Fine-tuning」這個詞在 LLM 社群有兩層意思：</p>
<ol>
<li><strong>SFT 階段</strong>（前面提的）：base model → instruction-tuned model。</li>
<li><strong>下游 fine-tuning</strong>：使用者在 instruction-tuned model 上、用自己的資料再 fine-tune、做特定領域特化。</li>
</ol>
<p>下游 fine-tuning 的常見方法：</p>
<h3 id="full-fine-tuning">Full Fine-tuning</h3>
<p>更新模型所有參數。需要大量 GPU、Gemma 4 31B 全參數 fine-tune 要 8 × H100 起。品質好、但成本高、容易過擬合小資料。</p>
<h3 id="loralow-rank-adaptation">LoRA（Low-Rank Adaptation）</h3>
<p><a href="/blog/llm/knowledge-cards/lora/" data-link-title="LoRA" data-link-desc="Low-Rank Adaptation：凍住原模型權重、只訓兩個小矩陣的 parameter-efficient fine-tuning">LoRA</a>（Hu et al., 2021）的核心想法是「凍結 base model 權重、只訓練一組小的 adapter 矩陣」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">W_new = W_frozen + α × A @ B</span></span></code></pre></div><p>其中 A、B 是低秩矩陣（rank=4 ~ 64）、總參數遠少於 full fine-tune。</p>
<p>優點：</p>
<ul>
<li>記憶體佔用 1/10 ~ 1/100。</li>
<li>訓練快得多。</li>
<li>多個 LoRA adapter 可以共用同一個 base model、推論時切換。</li>
<li>不會破壞 base model（凍結）。</li>
</ul>
<p>LoRA 是 consumer 級硬體做 fine-tuning 的主流選擇。32GB Mac + MLX 可以跑 7B / 14B 模型的 LoRA fine-tuning。</p>
<p>LoRA 何時不適用 / 必須走 full fine-tune：</p>
<ul>
<li><strong>大幅行為改變</strong>：要把模型從通用 chat 轉成完全不同的人設 / 風格 / 領域。LoRA rank 容量有限（rank=4 ~ 64 對應幾百萬 ~ 幾千萬參數）、裝不下整體行為的大幅改寫；rank 拉到 256+ 後 LoRA 的記憶體優勢消失。</li>
<li><strong>跨 domain transfer</strong>：base model 是 general English、想 fine-tune 到醫學 / 法律等需要重學 vocab 跟結構的 domain。LoRA 只調整現有 layer 的偏移、難以從零學新 domain；通常要先做 continued pre-training（full fine-tune）再 LoRA。</li>
<li><strong>跟量化推論的相容性</strong>：base model 用 Q4 推論時、要先 dequantize 才能加上 LoRA delta、會導致 latency / memory 增加；production 場景常用 QLoRA + 在推論時 merge 回 base、避免每次推論都拆兩段。</li>
</ul>
<h3 id="qlora">QLoRA</h3>
<p><a href="/blog/llm/knowledge-cards/qlora/" data-link-title="QLoRA" data-link-desc="把 base model 量化到 4-bit &#43; LoRA fine-tune 的組合、消費級 GPU 也能 fine-tune 大模型">QLoRA</a> = Quantized LoRA、把 base model 量化到 4-bit、再做 LoRA。記憶體進一步降低、犧牲少量品質。</p>
<h3 id="為什麼-fine-tuning-可能讓模型變差">為什麼 fine-tuning 可能讓模型變差</h3>
<p>下游 fine-tuning 對寫 code 場景的多數使用者價值有限、原因：</p>
<ol>
<li><strong>過擬合</strong>：fine-tune 資料量小、模型可能學到 spurious pattern、在 fine-tune 領域外能力下降。</li>
<li><strong>Catastrophic forgetting</strong>：學新資料時忘記舊知識、原本會的東西變差。</li>
<li><strong>資料品質決定上限</strong>：fine-tune 資料品質低、模型學到低品質回答。</li>
<li><strong>Alignment 退化</strong>：fine-tune 可能破壞 RLHF / DPO 階段建立的「helpful、harmless」性質。</li>
</ol>
<p>寫 code 場景優先用 instruction-tuned 通用模型（Gemma 4、Qwen3-Coder 等）、需要特化再評估 <a href="/blog/llm/knowledge-cards/rag/" data-link-title="RAG" data-link-desc="Retrieval-Augmented Generation：動態外掛知識給 LLM、繞開模型參數記憶的靜態限制">RAG</a> 或 prompt engineering、最後才考慮 fine-tuning。三條路的取捨判讀見 <a href="/blog/llm/04-applications/rag-principles/" data-link-title="4.1 RAG 原理：retrieval &#43; augmentation 模式" data-link-desc="為什麼模型需要外掛知識、語意相似 vs 字面相似、chunking 的本質取捨、retrieval 失敗的根本原因">4.1 RAG 原理</a>。</p>
<h2 id="in-context-learningfine-tuning-的替代品">In-Context Learning：fine-tuning 的替代品</h2>
<p>In-context learning（ICL）的核心想法是「不更新模型權重、只在 prompt 中給範例、讓模型 generalize」。</p>
<ul>
<li><strong>Zero-shot</strong>：直接給任務描述、不給範例。</li>
<li><strong>Few-shot</strong>：給幾個 input-output 範例、再給新 input。</li>
<li><strong>Chain-of-thought</strong>：要求模型把推理過程寫出來、再給答案。</li>
</ul>
<p>GPT-3 paper 顯示大模型有強 ICL 能力、不用 fine-tune 就能做新任務。現代 LLM 進一步強化 ICL、加上 long context、<a href="/blog/llm/knowledge-cards/agent/" data-link-title="LLM Agent" data-link-desc="把控制流交給 LLM 的應用模式：自主決策、跨多步呼叫工具、人類角色從主導變監督">agent</a> loop、<a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a> 等技術、覆蓋大部分原本需要 fine-tune 的場景。</p>
<p>實務啟示：「想做新任務、先試 prompt engineering、不夠再試 RAG、最後才考慮 fine-tuning」。fine-tuning 是最重的投資、適合放在最後驗證、prompt engineering 跟 RAG 跑完仍不夠才動。</p>
<h2 id="訓練資料污染data-contamination">訓練資料污染（Data Contamination）</h2>
<p>訓練資料污染指「benchmark 的測試集出現在預訓練資料中」、模型「記住答案」而非真正能解問題。</p>
<p>問題：</p>
<ul>
<li>公開 benchmark（SWE-bench、MMLU 等）的測試題常出現在 GitHub / 論壇、進入預訓練資料。</li>
<li>模型在這些 benchmark 上分數可能高估真實能力。</li>
</ul>
<p>解決：</p>
<ul>
<li><strong>SWE-bench Verified</strong>：OpenAI 篩選過、相對乾淨的子集。</li>
<li><strong>HELM</strong>：Stanford 的 holistic 評估、含污染檢測。</li>
<li><strong>新 benchmark</strong>：每隔一段時間出新 benchmark、用尚未被 LLM「看過」的資料。</li>
<li><strong>自己跑 benchmark</strong>：用自己工作流的真實任務評估、繞過所有污染問題。</li>
</ul>
<p>詳見 <a href="/blog/llm/knowledge-cards/swe-bench/" data-link-title="SWE-bench" data-link-desc="用真實 GitHub issue 量化 LLM coding 能力的 benchmark">SWE-bench 卡片</a> 跟 <a href="/blog/llm/00-foundations/info-judgment-frames/" data-link-title="0.6 判讀本地 LLM 資訊的五個框架" data-link-desc="本地 LLM 資訊更新快，學會用版本、層級、變數、能力、資料流五個框架評估文章與宣稱">模組零 0.6 判讀框架</a> 的框架二（量化宣稱三變數）。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">3.5 sampling 與 decoding 策略</a>、模型輸出後怎麼挑下一個 token。</p>
]]></content:encoded></item><item><title>3.5 Sampling 與 Decoding 策略</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/sampling-and-decoding/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/sampling-and-decoding/</guid><description>&lt;p>LLM 的輸出本質是「下一個 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a> 的機率分佈」、不是直接的 token。從機率分佈挑下一個 token 的具體方法、就是 sampling / decoding 策略。同一個模型、同一個 prompt、不同 sampling 策略會給出顯著不同的輸出。&lt;/p>
&lt;p>本章拆開主流 sampling 策略的機制、各自適合的場景、以及 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">&lt;code>temperature&lt;/code>&lt;/a>、&lt;code>top_p&lt;/code> 這些常見參數在這條鏈上的位置。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋 &lt;code>temperature=0&lt;/code> 跟 &lt;code>temperature=0.8&lt;/code> 的具體差別。&lt;/li>
&lt;li>區分 top-k、top-p、min-p 三者的機制。&lt;/li>
&lt;li>看到 &lt;code>repetition_penalty=1.1&lt;/code> 設定時、知道它解什麼問題。&lt;/li>
&lt;li>解釋為什麼確定性測試要設 &lt;code>temperature=0&lt;/code> + &lt;code>seed&lt;/code>。&lt;/li>
&lt;/ol>
&lt;h2 id="從-logits-到下個-token">從 logits 到下個 token&lt;/h2>
&lt;p>複習一下 LLM 輸出端的鏈：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">final hidden states → output projection → logits → temperature → softmax → 機率分佈
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">→ sampling 策略 → 下個 token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>各環節在 sampling 中的位置：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>環節&lt;/th>
 &lt;th>對 sampling 的影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logits&lt;/a>&lt;/td>
 &lt;td>模型給每個 token 的原始分數、還沒正規化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">temperature&lt;/a>&lt;/td>
 &lt;td>在 softmax 前除以 T、調整分佈尖銳度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax&lt;/a>&lt;/td>
 &lt;td>把 logits 轉成機率分佈&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>top-k / top-p / min-p&lt;/td>
 &lt;td>過濾低機率 token、把候選集縮小&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>重新正規化&lt;/td>
 &lt;td>把過濾後的剩餘 token 重新正規化成機率分佈&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>取樣&lt;/td>
 &lt;td>從正規化分佈中隨機選一個 token&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>repetition penalty&lt;/td>
 &lt;td>對已出現的 token 降權、避免重複&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>實際參數順序視推論伺服器實作而異、但概念上是這條鏈。&lt;/p>
&lt;h2 id="greedy-decoding永遠選機率最大">Greedy Decoding：永遠選機率最大&lt;/h2>
&lt;p>Greedy decoding 的核心定義是「每步選 softmax 後機率最大的 token」：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">next_token = argmax(probabilities)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>特性：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>確定性&lt;/strong>：同 prompt 永遠生同樣輸出。&lt;/li>
&lt;li>&lt;strong>快&lt;/strong>：不用 sampling、不用算 cumulative probabilities。&lt;/li>
&lt;li>&lt;strong>缺點&lt;/strong>：傾向選最常見 pattern、輸出單調；常陷入 repetition loop。&lt;/li>
&lt;/ul>
&lt;p>實務用途：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Reproducible 評估&lt;/strong>：跑 benchmark、自動測試。&lt;/li>
&lt;li>&lt;strong>單元測試&lt;/strong>：確保模型輸出可預測。&lt;/li>
&lt;li>&lt;strong>某些 reasoning chain&lt;/strong>：選最有信心的下一步。&lt;/li>
&lt;/ul>
&lt;p>效果上等同 &lt;code>temperature=0&lt;/code>、許多推論伺服器把兩者當同義詞。&lt;/p>
&lt;h2 id="beam-search保留-top-k-條候選序列">Beam Search：保留 top-K 條候選序列&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/beam-search/" data-link-title="Beam Search" data-link-desc="同時保留 K 條候選 sequence 的 decoding 策略、機器翻譯主流、chat / coding 場景慎用">Beam search&lt;/a> 的核心想法是「每步保留累積機率最大的 K 條序列、每條繼續展開、最後選整體機率最高的」。K 叫 beam size。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Beam size&lt;/th>
 &lt;th>行為&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1&lt;/td>
 &lt;td>等同 greedy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3 ~ 5&lt;/td>
 &lt;td>翻譯、摘要等任務常用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>10+&lt;/td>
 &lt;td>高品質生成、但計算成本高&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>特性：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>全局較優&lt;/strong>：不只看當步、考慮整段序列。&lt;/li>
&lt;li>&lt;strong>適合「有正確答案」的任務&lt;/strong>：翻譯、摘要、code 生成。&lt;/li>
&lt;li>&lt;strong>缺點&lt;/strong>：對 open-ended 生成（聊天、創意寫作）會 collapse 到平庸、缺乏多樣性。&lt;/li>
&lt;/ul>
&lt;p>具體失效症狀：K=5 在 chat 場景常產生「Sure!」「Thank you」「That&amp;rsquo;s a great question」這種高頻 boilerplate、各 beam 探索的方向都收斂到相似的平庸開頭、明明 logit 分佈本來該保留的多樣性被 beam 平均化掉。&lt;/p></description><content:encoded><![CDATA[<p>LLM 的輸出本質是「下一個 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a> 的機率分佈」、不是直接的 token。從機率分佈挑下一個 token 的具體方法、就是 sampling / decoding 策略。同一個模型、同一個 prompt、不同 sampling 策略會給出顯著不同的輸出。</p>
<p>本章拆開主流 sampling 策略的機制、各自適合的場景、以及 <a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項"><code>temperature</code></a>、<code>top_p</code> 這些常見參數在這條鏈上的位置。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋 <code>temperature=0</code> 跟 <code>temperature=0.8</code> 的具體差別。</li>
<li>區分 top-k、top-p、min-p 三者的機制。</li>
<li>看到 <code>repetition_penalty=1.1</code> 設定時、知道它解什麼問題。</li>
<li>解釋為什麼確定性測試要設 <code>temperature=0</code> + <code>seed</code>。</li>
</ol>
<h2 id="從-logits-到下個-token">從 logits 到下個 token</h2>
<p>複習一下 LLM 輸出端的鏈：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">final hidden states → output projection → logits → temperature → softmax → 機率分佈
</span></span><span class="line"><span class="ln">2</span><span class="cl">→ sampling 策略 → 下個 token</span></span></code></pre></div><p>各環節在 sampling 中的位置：</p>
<table>
  <thead>
      <tr>
          <th>環節</th>
          <th>對 sampling 的影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/logit/" data-link-title="Logit" data-link-desc="softmax 之前的原始實數分數、每個 vocab token 一個值、可正可負">logits</a></td>
          <td>模型給每個 token 的原始分數、還沒正規化</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sampling-constraint/" data-link-title="Sampling Constraint" data-link-desc="推論時限制下一個 token 候選集合的控制手段，用來把模型生成導向合法格式或特定選項">temperature</a></td>
          <td>在 softmax 前除以 T、調整分佈尖銳度</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/softmax/" data-link-title="Softmax" data-link-desc="把任意實數向量正規化成「總和為 1、每個分量 ∈ [0,1]」的機率分佈">softmax</a></td>
          <td>把 logits 轉成機率分佈</td>
      </tr>
      <tr>
          <td>top-k / top-p / min-p</td>
          <td>過濾低機率 token、把候選集縮小</td>
      </tr>
      <tr>
          <td>重新正規化</td>
          <td>把過濾後的剩餘 token 重新正規化成機率分佈</td>
      </tr>
      <tr>
          <td>取樣</td>
          <td>從正規化分佈中隨機選一個 token</td>
      </tr>
      <tr>
          <td>repetition penalty</td>
          <td>對已出現的 token 降權、避免重複</td>
      </tr>
  </tbody>
</table>
<p>實際參數順序視推論伺服器實作而異、但概念上是這條鏈。</p>
<h2 id="greedy-decoding永遠選機率最大">Greedy Decoding：永遠選機率最大</h2>
<p>Greedy decoding 的核心定義是「每步選 softmax 後機率最大的 token」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">next_token = argmax(probabilities)</span></span></code></pre></div><p>特性：</p>
<ul>
<li><strong>確定性</strong>：同 prompt 永遠生同樣輸出。</li>
<li><strong>快</strong>：不用 sampling、不用算 cumulative probabilities。</li>
<li><strong>缺點</strong>：傾向選最常見 pattern、輸出單調；常陷入 repetition loop。</li>
</ul>
<p>實務用途：</p>
<ul>
<li><strong>Reproducible 評估</strong>：跑 benchmark、自動測試。</li>
<li><strong>單元測試</strong>：確保模型輸出可預測。</li>
<li><strong>某些 reasoning chain</strong>：選最有信心的下一步。</li>
</ul>
<p>效果上等同 <code>temperature=0</code>、許多推論伺服器把兩者當同義詞。</p>
<h2 id="beam-search保留-top-k-條候選序列">Beam Search：保留 top-K 條候選序列</h2>
<p><a href="/blog/llm/knowledge-cards/beam-search/" data-link-title="Beam Search" data-link-desc="同時保留 K 條候選 sequence 的 decoding 策略、機器翻譯主流、chat / coding 場景慎用">Beam search</a> 的核心想法是「每步保留累積機率最大的 K 條序列、每條繼續展開、最後選整體機率最高的」。K 叫 beam size。</p>
<table>
  <thead>
      <tr>
          <th>Beam size</th>
          <th>行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>等同 greedy</td>
      </tr>
      <tr>
          <td>3 ~ 5</td>
          <td>翻譯、摘要等任務常用</td>
      </tr>
      <tr>
          <td>10+</td>
          <td>高品質生成、但計算成本高</td>
      </tr>
  </tbody>
</table>
<p>特性：</p>
<ul>
<li><strong>全局較優</strong>：不只看當步、考慮整段序列。</li>
<li><strong>適合「有正確答案」的任務</strong>：翻譯、摘要、code 生成。</li>
<li><strong>缺點</strong>：對 open-ended 生成（聊天、創意寫作）會 collapse 到平庸、缺乏多樣性。</li>
</ul>
<p>具體失效症狀：K=5 在 chat 場景常產生「Sure!」「Thank you」「That&rsquo;s a great question」這種高頻 boilerplate、各 beam 探索的方向都收斂到相似的平庸開頭、明明 logit 分佈本來該保留的多樣性被 beam 平均化掉。</p>
<p>Chat / 對話場景多半不用 beam search、用 sampling 策略保留多樣性。</p>
<h2 id="temperature調分佈尖銳度">Temperature：調分佈尖銳度</h2>
<p>Temperature 的機制在 <a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">模組二 2.1</a> 已經詳細展開。簡單回顧：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">adjusted_logits = logits / temperature
</span></span><span class="line"><span class="ln">2</span><span class="cl">probabilities = softmax(adjusted_logits)</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>Temperature</th>
          <th>效果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td>等同 greedy（argmax）</td>
      </tr>
      <tr>
          <td>0.2 ~ 0.4</td>
          <td>寫 code、回答事實問題、減少 hallucination</td>
      </tr>
      <tr>
          <td>0.7</td>
          <td>預設、平衡多樣性與品質</td>
      </tr>
      <tr>
          <td>0.9 ~ 1.0</td>
          <td>創意寫作、保留多樣性</td>
      </tr>
      <tr>
          <td>&gt; 1.5</td>
          <td>隨機性極高、輸出可能變混亂</td>
      </tr>
  </tbody>
</table>
<p>實務經驗：</p>
<ul>
<li>寫 code 場景設 0.2 ~ 0.4 較穩。</li>
<li>創意任務（寫故事、brainstorming）設 0.8 ~ 1.0。</li>
<li>Reproducible 測試設 0 + 固定 seed。</li>
<li>T &gt; 1.5 失效症狀：產出開始出現拼字錯誤、語法破洞、UTF-8 byte 混亂、甚至跨語言突然切換；極端 T 等同近 uniform 分佈、模型結構被當作 dice。</li>
</ul>
<p>Temperature 在 sampling 鏈上的位置（行 26 的流程鏈）跟其他過濾步驟有疊加順序、值得展開：</p>
<ol>
<li><strong>Temperature 先動分佈尖銳度</strong>：高 T 把分佈拉平、低 T 拉尖。</li>
<li><strong>再過 top-p / top-k / min-p</strong>：在拉平 / 拉尖後的分佈上做候選過濾。</li>
<li><strong>兩者相乘的常見坑</strong>：高 T（如 1.5）+ 低 top-p（如 0.5）= 「分佈被拉平、然後只挑前幾名」、實際出現的多樣性反而被壓縮、容易出現語義跳動。穩健做法：固定其中一個（多半是 top-p=0.9）、調另一個。</li>
<li><strong>Reasoning model 的特殊性</strong>：o1、DeepSeek-R1 等內建 chain-of-thought 的模型、官方建議 T=0 或 1.0、調 T 會破壞 reasoning trace 連貫性。</li>
</ol>
<h2 id="top-k-sampling">Top-K Sampling</h2>
<p><a href="/blog/llm/knowledge-cards/top-p-sampling/" data-link-title="Top-K / Top-P / Min-P Sampling" data-link-desc="從機率分佈取樣前先過濾低機率 token 的三種策略、現代 LLM 推論主流">Top-K sampling</a> 的核心定義是「只考慮機率最大的 K 個 token、其他設 0、重新正規化後取樣」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">1. 對機率排序、取最大的 K 個。
</span></span><span class="line"><span class="ln">2</span><span class="cl">2. 其他設 0。
</span></span><span class="line"><span class="ln">3</span><span class="cl">3. 重新正規化（讓總和為 1）。
</span></span><span class="line"><span class="ln">4</span><span class="cl">4. 從正規化分佈取樣。</span></span></code></pre></div><p>K 控制候選範圍：</p>
<table>
  <thead>
      <tr>
          <th>K</th>
          <th>行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>等同 greedy</td>
      </tr>
      <tr>
          <td>40</td>
          <td>預設常用值</td>
      </tr>
      <tr>
          <td>100+</td>
          <td>接近完全 sampling、限制較小</td>
      </tr>
  </tbody>
</table>
<p>缺點：K 是固定值、無法適應分佈尖銳度。當分佈尖銳時（一個 token 機率 90%）、K=40 包括很多近 0 機率的雜訊；當分佈平坦時（每個 token 機率 1%）、K=40 過於限制。具體失效症狀：在 code 生成情境、模型對「下一個 token 是 <code>)</code>」極度確定（95%+ 機率）時、K=40 把後面 39 個近零雜訊也納入候選、偶爾 sample 出語法錯的字元；改用 top-p 或 min-p 可避開。</p>
<h2 id="top-p--nucleus-sampling">Top-P / Nucleus Sampling</h2>
<p>Top-P sampling（也叫 nucleus sampling、Holtzman et al., 2019）的核心想法是「動態決定候選集大小」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">1. 對機率從大到小排序。
</span></span><span class="line"><span class="ln">2</span><span class="cl">2. 從大到小累加、直到累積機率 ≥ P（如 0.9）。
</span></span><span class="line"><span class="ln">3</span><span class="cl">3. 只保留這些 token、其他設 0。
</span></span><span class="line"><span class="ln">4</span><span class="cl">4. 重新正規化、取樣。</span></span></code></pre></div><p>例：</p>
<ul>
<li>分佈尖銳（一個 token 機率 95%）：P=0.9 可能只選 1 ~ 2 個 token。</li>
<li>分佈平坦（top 10 各 5%）：P=0.9 可能選 15 ~ 20 個 token。</li>
</ul>
<p>P 的常用值：</p>
<table>
  <thead>
      <tr>
          <th>P</th>
          <th>行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0.5</td>
          <td>較保守、傾向選機率高的</td>
      </tr>
      <tr>
          <td>0.9</td>
          <td>預設、保留合理多樣性</td>
      </tr>
      <tr>
          <td>0.95</td>
          <td>略放寬</td>
      </tr>
      <tr>
          <td>1.0</td>
          <td>等同關閉 top-p、用完整分佈</td>
      </tr>
  </tbody>
</table>
<p>在 chat / coding 場景下 top-p 是主流選擇、比 top-K 彈性；reproducible 評估則回到 greedy（T=0）、不用 sampling。多數推論伺服器預設 top_p=0.9。</p>
<h2 id="min-p自適應閾值-sampling">Min-P：自適應閾值 sampling</h2>
<p>Min-P sampling（2024 ~）的核心想法是「設一個機率閾值、最大機率 token × P_min 以下的全部去掉」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">1. 找出最大機率 p_max。
</span></span><span class="line"><span class="ln">2</span><span class="cl">2. 閾值 = p_max × P_min（如 0.1）。
</span></span><span class="line"><span class="ln">3</span><span class="cl">3. 機率 &lt; 閾值的 token 全部設 0、重新正規化。</span></span></code></pre></div><p>特性：</p>
<ul>
<li>自動適應分佈尖銳度（用比例而非絕對值）。</li>
<li>比 top-P 更穩定、近一兩年在開源社群興起。</li>
<li>LM Studio、llama.cpp 等支援。</li>
</ul>
<p>P_min 常用值：</p>
<table>
  <thead>
      <tr>
          <th>P_min</th>
          <th>行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0.05</td>
          <td>保留多樣性</td>
      </tr>
      <tr>
          <td>0.1</td>
          <td>平衡</td>
      </tr>
      <tr>
          <td>0.2</td>
          <td>較保守</td>
      </tr>
  </tbody>
</table>
<h2 id="repetition-penalty">Repetition Penalty</h2>
<p>Repetition penalty 的核心想法是「對已出現的 token 降低機率、避免無限重複」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">adjusted_logit(token) = logit(token) / repetition_penalty   if token 已出現
</span></span><span class="line"><span class="ln">2</span><span class="cl">                      = logit(token)                          if token 沒出現</span></span></code></pre></div><p>P 大於 1 時、已出現 token 的 logit 被降低、後續 sampling 較難選到。</p>
<table>
  <thead>
      <tr>
          <th>Penalty</th>
          <th>效果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1.0</td>
          <td>關閉</td>
      </tr>
      <tr>
          <td>1.05</td>
          <td>輕微抑制</td>
      </tr>
      <tr>
          <td>1.1</td>
          <td>預設常用</td>
      </tr>
      <tr>
          <td>1.3+</td>
          <td>強烈抑制、可能過度避免合理重複</td>
      </tr>
  </tbody>
</table>
<p>代價：寫 code 場景下、<code>if</code>、<code>for</code>、<code>return</code> 等關鍵字常出現、太高的 repetition penalty 會壞掉 code。寫 code 場景 penalty 設低（1.0 ~ 1.05）或關閉；creative writing 場景則設 1.1 ~ 1.2、避免段落 / 句子層級的重複。</p>
<h2 id="seed固定-sampling-的隨機性">Seed：固定 sampling 的隨機性</h2>
<p>Sampling 用 random number generator 取樣。<strong>設定 seed 讓 RNG 確定性</strong>、相同 prompt + 相同 seed 給相同輸出：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="s2">&#34;temperature&#34;</span><span class="p">:</span> <span class="mf">0.7</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="s2">&#34;top_p&#34;</span><span class="p">:</span> <span class="mf">0.9</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="s2">&#34;seed&#34;</span><span class="p">:</span> <span class="mi">42</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>實務用途：</p>
<ul>
<li><strong>Reproducible 評估</strong>：跑 benchmark 要可重複。</li>
<li><strong>A/B 測試</strong>：對比不同 prompt 在同 seed 下的差異。</li>
<li><strong>Debug</strong>：重現一個錯誤輸出。</li>
</ul>
<p>注意：seed 不是所有伺服器都支援、OpenAI API 是 best-effort（同 seed 不保證完全一致）、本地伺服器多半支援嚴格 seed 控制。</p>
<h2 id="logit-bias強制--排除特定-token">Logit Bias：強制 / 排除特定 token</h2>
<p>Logit bias 的機制是「對特定 token 的 logit 加減一個固定值」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">adjusted_logit(token) = logit(token) + bias(token)</span></span></code></pre></div><p>用途：</p>
<ul>
<li><strong>強制特定 token</strong>：bias = +100、softmax 後機率近 1。</li>
<li><strong>完全禁止</strong>：bias = -100、softmax 後機率近 0。</li>
<li><strong>微調傾向</strong>：bias = ±5、輕微傾斜。</li>
</ul>
<p>實務用例：</p>
<ul>
<li>強制輸出 JSON 格式：對 <code>{</code> 加 bias 在開頭。</li>
<li>避免特定詞：對敏感詞加負 bias。</li>
<li>約束輸出：限制只能用特定 vocabulary。</li>
</ul>
<p>OpenAI、Ollama 等多數推論伺服器支援 logit_bias 參數。</p>
<h2 id="structured-output--constrained-decoding">Structured Output / Constrained Decoding</h2>
<p><a href="/blog/llm/knowledge-cards/structured-output/" data-link-title="Structured Output" data-link-desc="讓 LLM 輸出可被 parser 穩定消費的推論階段設計：JSON mode、schema-guided decoding、grammar 約束都屬於這一層">Structured output</a> 的核心想法是「sampling 時加 grammar 約束、強制輸出符合特定結構（JSON、SQL、regex 等）」。實作方法：</p>
<ul>
<li><strong>JSON mode</strong>：每步只允許「能讓 JSON 仍合法」的 token。</li>
<li><strong>Grammar-based</strong>：用 <a href="/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF</a> / lark / etc. 定義語法、sampling 時 reject 違反語法的 token。</li>
<li><strong>Token mask</strong>：依當前狀態決定哪些 token 合法、不合法的 logit 設 -∞。</li>
</ul>
<p>實務工具：</p>
<ul>
<li>llama.cpp 的 <code>grammar</code> 參數。</li>
<li>Outlines、LMQL 等 framework。</li>
<li>OpenAI 的 <code>response_format: { type: &quot;json_schema&quot; }</code>。</li>
</ul>
<p>寫 code 場景中、structured output 對「要可解析的輸出」（如 commit message 格式、structured API call）很有用。</p>
<h2 id="decoding-策略對體感的影響">Decoding 策略對體感的影響</h2>
<p>下表是寫 code 場景下、不同 decoding 配置的體感：</p>
<table>
  <thead>
      <tr>
          <th>配置</th>
          <th>體感</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>temperature=0、greedy</td>
          <td>確定、可重複、但可能單調</td>
      </tr>
      <tr>
          <td>temperature=0.2、top_p=0.95</td>
          <td>穩定、寫 code 主流</td>
      </tr>
      <tr>
          <td>temperature=0.7、top_p=0.9</td>
          <td>平衡、預設</td>
      </tr>
      <tr>
          <td>temperature=1.0、top_p=0.95、min_p=0.05</td>
          <td>創意、多樣</td>
      </tr>
      <tr>
          <td>temperature=1.5</td>
          <td>過於隨機、code 容易壞</td>
      </tr>
      <tr>
          <td>repetition_penalty=1.3、寫 code 場景</td>
          <td>抑制太強、會壞掉 keyword 重複用法</td>
      </tr>
  </tbody>
</table>
<p>實務建議：寫 code 場景下 temperature=0.2 ~ 0.4、top_p=0.9 ~ 0.95、其他保留預設就好。Continue.dev 等 IDE 整合多半自動調整。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">3.6 tokenization 算法</a>、補完 input / output 端的細節。</p>
]]></content:encoded></item><item><title>3.6 Tokenization：BPE、SentencePiece、Tiktoken</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/tokenization-algorithms/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/tokenization-algorithms/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Tokenization&lt;/a> 是把文字切成模型可處理的 token 序列的過程。看似簡單的「切字」實際上有完整算法、且 tokenizer 的選擇深刻影響模型能力、context window 利用率、跨語言表現、跟一些奇怪 bug 的成因（GPT 在某些字串上表現異常的「glitch tokens」就源於 tokenizer 設計）。&lt;/p>
&lt;p>本章拆開四個主流 tokenization 算法（BPE、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/wordpiece/" data-link-title="WordPiece" data-link-desc="以 likelihood improvement 選擇子詞合併的 tokenizer 演算法，BERT 系列代表性使用">WordPiece&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/unigram-tokenizer/" data-link-title="Unigram Tokenizer" data-link-desc="以機率模型選擇子詞切分的 tokenizer 演算法，常見於 SentencePiece 的 unigram 模式">Unigram&lt;/a>、SentencePiece）、解釋 vocabulary 怎麼學出來、為什麼中文 / 中日韓字幾乎一字一 token、tokenizer 為什麼影響 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding&lt;/a> 的相容性。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋 BPE（Byte-Pair Encoding）的工作原理。&lt;/li>
&lt;li>看到不同 model 切同段文字得到不同 token 數時、知道原因。&lt;/li>
&lt;li>解釋為什麼 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter&lt;/a> 跟 target 必須共用 tokenizer。&lt;/li>
&lt;li>看到 vocab_size = 256,000 vs 128,256 時、知道差異在哪。&lt;/li>
&lt;/ol>
&lt;h2 id="tokenization-的設計目標">Tokenization 的設計目標&lt;/h2>
&lt;p>理想 tokenizer 要同時滿足：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>覆蓋率高&lt;/strong>：能 encode 任何文字、不會「碰到沒見過的字壞掉」。&lt;/li>
&lt;li>&lt;strong>效率高&lt;/strong>：常見字串切成少數 token、節省 context 與計算。&lt;/li>
&lt;li>&lt;strong>語意保留&lt;/strong>：保留有意義的 sub-word 邊界（「unhappy」切成 &lt;code>un&lt;/code> + &lt;code>happy&lt;/code> 比 &lt;code>unh&lt;/code> + &lt;code>appy&lt;/code> 好）。&lt;/li>
&lt;li>&lt;strong>跨語言公平&lt;/strong>：英文跟中文 / 日文 / 阿拉伯文等都用合理數量的 token。&lt;/li>
&lt;/ol>
&lt;p>不同算法在這四個目標上有不同取捨。&lt;/p>
&lt;h2 id="早期方法word-level-跟-char-level">早期方法：word-level 跟 char-level&lt;/h2>
&lt;h3 id="word-level-tokenization">Word-level Tokenization&lt;/h3>
&lt;p>最簡單的方法是「用空白跟標點切」、每個 word 一個 token。&lt;/p>
&lt;p>優點：直觀。&lt;/p>
&lt;p>缺點：&lt;/p>
&lt;ol>
&lt;li>Vocabulary 爆炸：英文有幾百萬個 word forms（含複數、時態、複合詞等）。&lt;/li>
&lt;li>OOV（out-of-vocabulary）：新詞、typo、URL、混合語言完全壞掉。&lt;/li>
&lt;li>中文 / 日文沒有空白：要先做 word segmentation。&lt;/li>
&lt;/ol>
&lt;p>現代 LLM 已淘汰 word-level、主流改用 subword 系列。&lt;/p>
&lt;h3 id="char-level-tokenization">Char-level Tokenization&lt;/h3>
&lt;p>另一個極端是「每個 character 一個 token」。&lt;/p>
&lt;p>優點：vocabulary 小、無 OOV。&lt;/p>
&lt;p>缺點：序列變很長（一句話幾十到幾百 char、效率低）、模型要從很基礎學起、訓練不效率。&lt;/p>
&lt;p>現代 LLM 也跳過純 char-level、改用 subword 折衷。&lt;/p>
&lt;h3 id="折衷subword-tokenization">折衷：Subword Tokenization&lt;/h3>
&lt;p>主流方案是「subword tokenization」：常見字串當一個 token、罕見字串切成更小單位（甚至到 char 級別）。三個主流算法：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>算法&lt;/th>
 &lt;th>模型例子&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE&lt;/a>&lt;/td>
 &lt;td>GPT-2、GPT-3、GPT-4、Llama 系列&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>WordPiece&lt;/td>
 &lt;td>BERT&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece&lt;/a>&lt;/td>
 &lt;td>Gemma、PaLM、T5&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">Vocabulary size&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/special-tokens/" data-link-title="Special Tokens" data-link-desc="在 vocab 中保留給特殊用途的 token：sequence 邊界、角色標記、padding、tool call 等">special tokens&lt;/a> 是這幾個算法產出的 tokenizer 共同的概念維度。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">Tokenization</a> 是把文字切成模型可處理的 token 序列的過程。看似簡單的「切字」實際上有完整算法、且 tokenizer 的選擇深刻影響模型能力、context window 利用率、跨語言表現、跟一些奇怪 bug 的成因（GPT 在某些字串上表現異常的「glitch tokens」就源於 tokenizer 設計）。</p>
<p>本章拆開四個主流 tokenization 算法（BPE、<a href="/blog/llm/knowledge-cards/wordpiece/" data-link-title="WordPiece" data-link-desc="以 likelihood improvement 選擇子詞合併的 tokenizer 演算法，BERT 系列代表性使用">WordPiece</a>、<a href="/blog/llm/knowledge-cards/unigram-tokenizer/" data-link-title="Unigram Tokenizer" data-link-desc="以機率模型選擇子詞切分的 tokenizer 演算法，常見於 SentencePiece 的 unigram 模式">Unigram</a>、SentencePiece）、解釋 vocabulary 怎麼學出來、為什麼中文 / 中日韓字幾乎一字一 token、tokenizer 為什麼影響 <a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">speculative decoding</a> 的相容性。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋 BPE（Byte-Pair Encoding）的工作原理。</li>
<li>看到不同 model 切同段文字得到不同 token 數時、知道原因。</li>
<li>解釋為什麼 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 跟 target 必須共用 tokenizer。</li>
<li>看到 vocab_size = 256,000 vs 128,256 時、知道差異在哪。</li>
</ol>
<h2 id="tokenization-的設計目標">Tokenization 的設計目標</h2>
<p>理想 tokenizer 要同時滿足：</p>
<ol>
<li><strong>覆蓋率高</strong>：能 encode 任何文字、不會「碰到沒見過的字壞掉」。</li>
<li><strong>效率高</strong>：常見字串切成少數 token、節省 context 與計算。</li>
<li><strong>語意保留</strong>：保留有意義的 sub-word 邊界（「unhappy」切成 <code>un</code> + <code>happy</code> 比 <code>unh</code> + <code>appy</code> 好）。</li>
<li><strong>跨語言公平</strong>：英文跟中文 / 日文 / 阿拉伯文等都用合理數量的 token。</li>
</ol>
<p>不同算法在這四個目標上有不同取捨。</p>
<h2 id="早期方法word-level-跟-char-level">早期方法：word-level 跟 char-level</h2>
<h3 id="word-level-tokenization">Word-level Tokenization</h3>
<p>最簡單的方法是「用空白跟標點切」、每個 word 一個 token。</p>
<p>優點：直觀。</p>
<p>缺點：</p>
<ol>
<li>Vocabulary 爆炸：英文有幾百萬個 word forms（含複數、時態、複合詞等）。</li>
<li>OOV（out-of-vocabulary）：新詞、typo、URL、混合語言完全壞掉。</li>
<li>中文 / 日文沒有空白：要先做 word segmentation。</li>
</ol>
<p>現代 LLM 已淘汰 word-level、主流改用 subword 系列。</p>
<h3 id="char-level-tokenization">Char-level Tokenization</h3>
<p>另一個極端是「每個 character 一個 token」。</p>
<p>優點：vocabulary 小、無 OOV。</p>
<p>缺點：序列變很長（一句話幾十到幾百 char、效率低）、模型要從很基礎學起、訓練不效率。</p>
<p>現代 LLM 也跳過純 char-level、改用 subword 折衷。</p>
<h3 id="折衷subword-tokenization">折衷：Subword Tokenization</h3>
<p>主流方案是「subword tokenization」：常見字串當一個 token、罕見字串切成更小單位（甚至到 char 級別）。三個主流算法：</p>
<table>
  <thead>
      <tr>
          <th>算法</th>
          <th>模型例子</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a></td>
          <td>GPT-2、GPT-3、GPT-4、Llama 系列</td>
      </tr>
      <tr>
          <td>WordPiece</td>
          <td>BERT</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/sentencepiece/" data-link-title="SentencePiece" data-link-desc="Google 開源的多語言 tokenization 框架、支援 BPE 跟 unigram 演算法、處理空白統一">SentencePiece</a></td>
          <td>Gemma、PaLM、T5</td>
      </tr>
  </tbody>
</table>
<p><a href="/blog/llm/knowledge-cards/vocabulary-size/" data-link-title="Vocabulary Size" data-link-desc="tokenizer 詞彙表的 token 總數、影響 embedding 大小、tokenization 粒度、多語言友善度">Vocabulary size</a> 跟 <a href="/blog/llm/knowledge-cards/special-tokens/" data-link-title="Special Tokens" data-link-desc="在 vocab 中保留給特殊用途的 token：sequence 邊界、角色標記、padding、tool call 等">special tokens</a> 是這幾個算法產出的 tokenizer 共同的概念維度。</p>
<h2 id="bpebyte-pair-encoding">BPE：Byte-Pair Encoding</h2>
<p><a href="/blog/llm/knowledge-cards/bpe/" data-link-title="BPE（Byte-Pair Encoding）" data-link-desc="用「最常一起出現的字元對」合併建詞彙表的 tokenization 演算法、GPT / Llama 等主流">BPE</a>（Sennrich et al., 2016）的核心想法是「貪婪地合併最常出現的字元對」、迭代到 vocabulary 達到目標大小。</p>
<h3 id="訓練流程">訓練流程</h3>
<ol>
<li>初始 vocabulary：所有 character。</li>
<li>統計訓練語料中、所有相鄰 character pair 的頻率。</li>
<li>把頻率最高的 pair 合併成一個新 token、加進 vocabulary。</li>
<li>用新 vocabulary 重新 tokenize 語料、重複 step 2-3。</li>
<li>直到 vocabulary 達到目標大小（如 50,000、100,000）。</li>
</ol>
<p>例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">初始：l o w e r → 5 個 token
</span></span><span class="line"><span class="ln">2</span><span class="cl">步驟 1：合併 &#39;l&#39; + &#39;o&#39; = &#39;lo&#39;、變成 lo w e r → 4 個 token
</span></span><span class="line"><span class="ln">3</span><span class="cl">步驟 2：合併 &#39;lo&#39; + &#39;w&#39; = &#39;low&#39;、變成 low e r → 3 個 token
</span></span><span class="line"><span class="ln">4</span><span class="cl">步驟 3：合併 &#39;e&#39; + &#39;r&#39; = &#39;er&#39;、變成 low er → 2 個 token</span></span></code></pre></div><p>訓練後、<code>lower</code> 就是 2 個 token。</p>
<h3 id="byte-level-bpe">Byte-level BPE</h3>
<p>原始 BPE 在 character level 運作、但「character」依語言而異（Unicode 字元複雜）。Byte-level BPE 在 byte level 運作、任何文字都可以 encode 成 byte 序列、自然支援多語言。</p>
<p>GPT-2 / GPT-3 / GPT-4 / Llama 系列都用 byte-level BPE。</p>
<h3 id="tiktokenopenai-的高效實作">Tiktoken：OpenAI 的高效實作</h3>
<p>Tiktoken 是 OpenAI 開源的 BPE 高效實作、Python 套件。可以拿來算「這段文字在 GPT-4 上是多少 token」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">tiktoken</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">enc</span> <span class="o">=</span> <span class="n">tiktoken</span><span class="o">.</span><span class="n">encoding_for_model</span><span class="p">(</span><span class="s2">&#34;gpt-4&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">tokens</span> <span class="o">=</span> <span class="n">enc</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">&#34;Hello, world!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">))</span>   <span class="c1"># 4</span></span></span></code></pre></div><p>Tiktoken 是估算 OpenAI API 費用的標準工具。其他模型有各自的 tokenizer 套件（Llama 的 sentencepiece、Hugging Face 的 transformers.AutoTokenizer）。</p>
<h2 id="wordpiecebert-的選擇">WordPiece：BERT 的選擇</h2>
<p>WordPiece（Schuster &amp; Nakajima, 2012、後來 Google 用在 BERT）跟 BPE 類似、但合併策略不同：</p>
<ul>
<li>BPE：合併「最頻繁出現的 pair」。</li>
<li>WordPiece：合併「合併後 likelihood 最大化的 pair」（更貴的計算、但理論上更好）。</li>
</ul>
<p>實務差異微小。BERT 系列用 WordPiece、現代 LLM 大多回到 BPE 系列。</p>
<h2 id="unigram機率式-subword">Unigram：機率式 subword</h2>
<p>Unigram（Kudo, 2018）是另一條主流 subword 算法、跟 BPE 的「greedy 從下往上合併」相反、它從一個很大的 candidate vocabulary 開始、用機率模型逐步<strong>刪掉</strong> likelihood 貢獻最小的 token：</p>
<ol>
<li>起點：一個包含大量 candidate subword 的初始 vocab（可從訓練資料抓所有 substring）。</li>
<li>用 EM 算法估每個 candidate 的機率、把整段文字 tokenize 成 likelihood 最大的 segmentation。</li>
<li>評估「刪掉某個 candidate 後 total likelihood 損失多少」、刪掉損失最小的一批。</li>
<li>重複到 vocab 達目標大小。</li>
</ol>
<p>跟 BPE 的本質差異：</p>
<ul>
<li><strong>BPE</strong>：每個輸入文字只有一個切法（merge 規則決定）、結果是 deterministic。</li>
<li><strong>Unigram</strong>：每個輸入可能對應多個合法 segmentation、訓練時用機率挑、推論時取 top-1。這個性質讓 Unigram 天然支援 <strong>subword regularization</strong>（訓練時隨機取不同 segmentation、增強 robustness）。</li>
</ul>
<p>Unigram 是 SentencePiece 預設算法、T5、Gemma 系列訓練時用。實務上 Unigram 跟 BPE 的最終 tokenization 接近、選擇看「訓練時要不要做 subword regularization」。</p>
<h2 id="sentencepiecegoogle-的開源實作">SentencePiece：Google 的開源實作</h2>
<p>SentencePiece（Kudo &amp; Richardson, 2018）是 Google 開源的 tokenization 套件、可實作 BPE 或 Unigram 算法、設計上：</p>
<ul>
<li><strong>語言無關</strong>：把輸入當 byte 流處理、不假設「word boundary 是空白」。</li>
<li><strong>無前處理</strong>：不用先切 word、適合中文 / 日文等無空白語言。</li>
<li><strong>可逆</strong>：tokenize → detokenize 完全還原原文。</li>
</ul>
<p>Gemma 系列、PaLM、T5 用 SentencePiece。實務上跟 BPE 表現接近、差異主要在「對中日韓文等無空白語言更友善」。</p>
<h2 id="vocabulary-大小">Vocabulary 大小</h2>
<p>各 LLM 的 vocabulary 大小：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>vocab_size</th>
          <th>Tokenizer</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-2</td>
          <td>50,257</td>
          <td>byte-level BPE</td>
      </tr>
      <tr>
          <td>GPT-3 / GPT-4</td>
          <td>~100K</td>
          <td>byte-level BPE (tiktoken)</td>
      </tr>
      <tr>
          <td>Llama 2</td>
          <td>32,000</td>
          <td>SentencePiece</td>
      </tr>
      <tr>
          <td>Llama 3</td>
          <td>128,256</td>
          <td>tiktoken-style BPE</td>
      </tr>
      <tr>
          <td>Gemma 2</td>
          <td>256,000</td>
          <td>SentencePiece</td>
      </tr>
      <tr>
          <td>Gemma 3</td>
          <td>262,144</td>
          <td>SentencePiece</td>
      </tr>
      <tr>
          <td>Gemma 4</td>
          <td>256,000</td>
          <td>SentencePiece</td>
      </tr>
      <tr>
          <td>Qwen3</td>
          <td>152,064</td>
          <td>byte-level BPE</td>
      </tr>
  </tbody>
</table>
<p>Vocabulary 大小的取捨：</p>
<table>
  <thead>
      <tr>
          <th>大 vocab</th>
          <th>小 vocab</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>同段文字切出 token 數少（context 利用率高）</td>
          <td>同段文字切出 token 數多（context 吃緊）</td>
      </tr>
      <tr>
          <td>Embedding layer 跟 output projection 大</td>
          <td>Embedding 跟 output projection 小</td>
      </tr>
      <tr>
          <td>多語言覆蓋好</td>
          <td>多語言覆蓋差、可能切成 byte 級</td>
      </tr>
      <tr>
          <td>中文 / 日文每字一 token</td>
          <td>中文 / 日文一字可能切 2 ~ 3 個 token</td>
      </tr>
  </tbody>
</table>
<p>Gemma 4 的 256K vocab 是現代 LLM 中較大的、目的之一是多語言支援。</p>
<h2 id="同段文字在不同-tokenizer-上的差異">同段文字在不同 tokenizer 上的差異</h2>
<p>實測「The quick brown fox jumps over the lazy dog」：</p>
<table>
  <thead>
      <tr>
          <th>Tokenizer</th>
          <th>Token 數</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-4</td>
          <td>9</td>
      </tr>
      <tr>
          <td>Llama 3</td>
          <td>9</td>
      </tr>
      <tr>
          <td>Gemma 4</td>
          <td>11</td>
      </tr>
      <tr>
          <td>Qwen3</td>
          <td>10</td>
      </tr>
  </tbody>
</table>
<p>差異不大。但中文「敏捷的棕色狐狸跳過懶狗」：</p>
<table>
  <thead>
      <tr>
          <th>Tokenizer</th>
          <th>Token 數（估）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-4</td>
          <td>約 12</td>
      </tr>
      <tr>
          <td>Llama 2</td>
          <td>約 20 (byte 級)</td>
      </tr>
      <tr>
          <td>Llama 3</td>
          <td>約 10</td>
      </tr>
      <tr>
          <td>Gemma 4</td>
          <td>約 9</td>
      </tr>
  </tbody>
</table>
<p>Llama 2 的 32K vocab 對中文支援差、Llama 3 / Gemma 4 改善很多。實務影響：中文 prompt 在 Llama 2 上吃 context 多、Gemma 4 較友善。</p>
<h2 id="tokenizer-跟模型相容性">Tokenizer 跟模型相容性</h2>
<p><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding</a> 要 target 跟 <a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter</a> 共用 tokenizer、因為兩者必須對「下個 token」的概念一致：</p>
<ul>
<li>Gemma 4 31B + Gemma 4 E4B：同 tokenizer、可以配對。</li>
<li>Gemma 4 + Llama：不同 tokenizer、配不起來。</li>
</ul>
<p>理解這點、能解釋為什麼 LM Studio 的 draft model UI 自動過濾相容候選、為什麼 Ollama 的 <code>gemma4:31b-coding-mtp-bf16</code> model tag 內含 drafter 而不能自己組合不同家族。</p>
<h2 id="special-tokens">Special Tokens</h2>
<p>除了 vocabulary 中的「正常」token、還有特殊 token：</p>
<ul>
<li><code>&lt;BOS&gt;</code> / <code>&lt;bos&gt;</code>：Beginning of sequence、prompt 起點。</li>
<li><code>&lt;EOS&gt;</code> / <code>&lt;eos&gt;</code>：End of sequence、生成結束。</li>
<li><code>&lt;PAD&gt;</code>：Padding、batch 訓練時補齊長度。</li>
<li><code>&lt;UNK&gt;</code>：Unknown token（現代 BPE 少用、因為 byte-level 覆蓋所有字元）。</li>
<li><code>&lt;|im_start|&gt;</code> / <code>&lt;|im_end|&gt;</code>：ChatML 格式中區隔每段訊息的邊界 token。</li>
<li>ChatML 中的 role 名稱（<code>system</code> / <code>user</code> / <code>assistant</code>）寫在 <code>&lt;|im_start|&gt;</code> 之後當作文字內容、不是獨立 token；模型靠「<code>&lt;|im_start|&gt;</code> + 後接 role 字串」這個 pattern 識別說話者。</li>
</ul>
<p>聊天 LLM 的 prompt 實際長相是用 special tokens 標記 role 跟訊息邊界，而非純文字：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">&lt;|im_start|&gt;system
</span></span><span class="line"><span class="ln">2</span><span class="cl">You are a helpful assistant.&lt;|im_end|&gt;
</span></span><span class="line"><span class="ln">3</span><span class="cl">&lt;|im_start|&gt;user
</span></span><span class="line"><span class="ln">4</span><span class="cl">Hello!&lt;|im_end|&gt;
</span></span><span class="line"><span class="ln">5</span><span class="cl">&lt;|im_start|&gt;assistant</span></span></code></pre></div><p>不同模型的 chat template 不同、Ollama / Continue.dev 等工具自動處理、但若自己呼叫 API 要注意 template 對不對。</p>
<h2 id="tokenization-引發的-bug">Tokenization 引發的 bug</h2>
<p>Tokenizer 設計的副作用：</p>
<h3 id="glitch-tokens">Glitch Tokens</h3>
<p>某些 token 在訓練資料中很少出現、模型對它們的行為怪異。Reddit 上著名的 <code>SolidGoldMagikarp</code> 就是 GPT-2 / GPT-3 的 glitch token、模型遇到會出現奇怪反應。原因：tokenizer 學了這個 token、但訓練資料中幾乎沒上下文、模型沒學到它的語意。</p>
<h3 id="數字-tokenization">數字 tokenization</h3>
<p>早期 BPE 對數字的處理不一致：<code>1234</code> 可能切成 <code>123</code> + <code>4</code>、<code>1235</code> 可能切成 <code>12</code> + <code>35</code>。模型對「數字加法」表現差跟這個有關。</p>
<p>現代 LLM 多半把每個 digit 各自當一個 token（一致 tokenization）、改善數學能力。</p>
<h3 id="code-的-indentation">Code 的 indentation</h3>
<p>寫 code 場景的 tokenizer 要妥善處理 indentation。早期 LLM 把多個空白合併成一個 token、code 結構壞掉；現代 LLM（特別是 coding-specialized）把 4 空白 / 8 空白等常見 indentation 各自當一個 token。</p>
<h2 id="跟-context-window-的關係">跟 context window 的關係</h2>
<p><a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">Context window</a> 的單位是 token、不是字。1M token 的 context window 在英文約等於 750K 字、在中文約 1M 字（看 tokenizer）。</p>
<p>實務啟示：</p>
<ul>
<li>「128K context」在不同 tokenizer 上實際容量不同。</li>
<li>計算 API 費用要用該模型的 tokenizer 算 token 數。</li>
<li>中文 prompt 用 Llama 2 比 Llama 3 / Gemma 4 吃 context 多。</li>
</ul>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">3.7 想學更深：推薦公開課程</a>。</p>
]]></content:encoded></item><item><title>3.7 跨語言場景的 tokenizer 與訓練分佈原理</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/cross-language-tokenization/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/cross-language-tokenization/</guid><description>&lt;p>模組三 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">3.6 tokenization 章節&lt;/a> 提到 Llama 2 對中文支援差、Gemma 4 改善很多——但「為什麼」展開後不只 tokenizer 一層、還涉及訓練資料分佈、模型容量分配、跨語言 reasoning 行為差異。本章把跨語言場景的根本原理走過、讓「該用什麼語言寫 prompt」「commit message 用中文還是英文」這類取捨從直覺變成可推導判斷。&lt;/p>
&lt;p>本章寫的是「跨語言能力為什麼這樣分佈」「該如何依場景選語言」的原理層。具體模型在 2026/5 的中文 / 多語言 benchmark 不在本章——這些隨新模型版本變、用本章的雙因素 framework 重新評估就好。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋為什麼模型在不同語言上表現不一致、有哪兩個獨立因素。&lt;/li>
&lt;li>看到 tokenizer 對中文「一字切 N token」時、知道對 context cost 跟能力的影響。&lt;/li>
&lt;li>判讀「該翻英寫 prompt 還是維持中文」的取捨。&lt;/li>
&lt;li>解釋為什麼跨語言 reasoning 比 monolingual reasoning 容易失敗。&lt;/li>
&lt;/ol>
&lt;h2 id="為什麼模型對不同語言表現不一致雙因素">為什麼模型對不同語言表現不一致：雙因素&lt;/h2>
&lt;p>模型對不同語言的表現受兩個獨立因素疊加影響：&lt;/p>
&lt;h3 id="因素-1tokenizer-vocab-coverage">因素 1：Tokenizer Vocab Coverage&lt;/h3>
&lt;p>Tokenizer 把文字切成 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token&lt;/a>、tokenizer vocab 大小指 tokenizer 認識的 token 種類數（vocab 越大、能切得越細、越能用單一 token 表達常見字）。不同 tokenizer 對不同語言的切割密度不同：&lt;/p>
&lt;ul>
&lt;li>英文中心的 tokenizer（如 Llama 2 的 32K vocab）對 vocab 沒涵蓋的中文字會 fallback 到 byte 級切割（UTF-8 一個中文字常用 3 個 byte、所以變 3 個 token）。&lt;/li>
&lt;li>多語言 tokenizer（如 Gemma 4 的 256K vocab）把常見中文字當獨立 token 收進來、對中文多半一字一 token、跟英文接近。&lt;/li>
&lt;/ul>
&lt;p>完整的 BPE / WordPiece / Unigram / SentencePiece 算法見 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">3.6 tokenization 算法&lt;/a>。&lt;/p>
&lt;p>Tokenizer 影響三件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Context 成本&lt;/strong>：同樣 prompt 在不同 tokenizer 上吃 token 量級不同、API 費用、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window&lt;/a> 利用率都跟著差。&lt;/li>
&lt;li>&lt;strong>Token 粒度&lt;/strong>：粗粒度 tokenizer 對某語言的「字」切割不細、影響模型對該語言細微差異的辨識。&lt;/li>
&lt;li>&lt;strong>訓練效率&lt;/strong>：tokenizer 切得好、模型每個 token 學到更多語意、訓練收斂快。&lt;/li>
&lt;/ul>
&lt;h3 id="因素-2訓練資料分佈">因素 2：訓練資料分佈&lt;/h3>
&lt;p>模型預訓練資料的語言佔比決定模型「學了多少」這個語言：&lt;/p>
&lt;ul>
&lt;li>Common Crawl 等主流預訓練資料英文佔 70%+、中文約 1-3%、其他語言更少。&lt;/li>
&lt;li>即使 tokenizer 對某語言支援好、訓練資料少仍會限制模型在該語言上的能力。&lt;/li>
&lt;/ul>
&lt;p>訓練分佈影響三件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>事實準確度&lt;/strong>：訓練資料少 → 該語言的事實覆蓋低 → hallucination 多。&lt;/li>
&lt;li>&lt;strong>Reasoning 深度&lt;/strong>：複雜推理需要大量該語言範例支撐、訓練少就退化。&lt;/li>
&lt;li>&lt;strong>風格自然度&lt;/strong>：訓練少的語言、模型輸出語法 OK 但 idiom / 慣用搭配偏直譯。&lt;/li>
&lt;/ul>
&lt;h3 id="雙因素的獨立性">雙因素的獨立性&lt;/h3>
&lt;p>兩個因素獨立、各自影響不同維度：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Tokenizer 好&lt;/th>
 &lt;th>訓練資料多&lt;/th>
 &lt;th>結果&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>是&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>跨語言能力接近 native（Gemma 4 / Qwen3 在中文上的狀態）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>是&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>「會讀」但「不熟」、輸出語法 OK 但內容平庸&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>能力 OK 但 cost 高、context 利用率差&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>該語言基本不可用（Llama 2 對中文的狀態）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>判讀模型某語言能力時、兩個因素都要評估、單看一個會誤判。「Gemma 4 vocab 對中文好」不代表「中文表現一定好」、還要看訓練資料佔比。「OpenAI 訓練資料量大」不代表「對所有語言都好」、還要看 tokenizer 設計。&lt;/p></description><content:encoded><![CDATA[<p>模組三 <a href="/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">3.6 tokenization 章節</a> 提到 Llama 2 對中文支援差、Gemma 4 改善很多——但「為什麼」展開後不只 tokenizer 一層、還涉及訓練資料分佈、模型容量分配、跨語言 reasoning 行為差異。本章把跨語言場景的根本原理走過、讓「該用什麼語言寫 prompt」「commit message 用中文還是英文」這類取捨從直覺變成可推導判斷。</p>
<p>本章寫的是「跨語言能力為什麼這樣分佈」「該如何依場景選語言」的原理層。具體模型在 2026/5 的中文 / 多語言 benchmark 不在本章——這些隨新模型版本變、用本章的雙因素 framework 重新評估就好。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋為什麼模型在不同語言上表現不一致、有哪兩個獨立因素。</li>
<li>看到 tokenizer 對中文「一字切 N token」時、知道對 context cost 跟能力的影響。</li>
<li>判讀「該翻英寫 prompt 還是維持中文」的取捨。</li>
<li>解釋為什麼跨語言 reasoning 比 monolingual reasoning 容易失敗。</li>
</ol>
<h2 id="為什麼模型對不同語言表現不一致雙因素">為什麼模型對不同語言表現不一致：雙因素</h2>
<p>模型對不同語言的表現受兩個獨立因素疊加影響：</p>
<h3 id="因素-1tokenizer-vocab-coverage">因素 1：Tokenizer Vocab Coverage</h3>
<p>Tokenizer 把文字切成 <a href="/blog/llm/knowledge-cards/token/" data-link-title="Token" data-link-desc="LLM 處理文字時的最小單位：介於字元與單字之間">token</a>、tokenizer vocab 大小指 tokenizer 認識的 token 種類數（vocab 越大、能切得越細、越能用單一 token 表達常見字）。不同 tokenizer 對不同語言的切割密度不同：</p>
<ul>
<li>英文中心的 tokenizer（如 Llama 2 的 32K vocab）對 vocab 沒涵蓋的中文字會 fallback 到 byte 級切割（UTF-8 一個中文字常用 3 個 byte、所以變 3 個 token）。</li>
<li>多語言 tokenizer（如 Gemma 4 的 256K vocab）把常見中文字當獨立 token 收進來、對中文多半一字一 token、跟英文接近。</li>
</ul>
<p>完整的 BPE / WordPiece / Unigram / SentencePiece 算法見 <a href="/blog/llm/03-theoretical-foundations/tokenization-algorithms/" data-link-title="3.6 Tokenization：BPE、SentencePiece、Tiktoken" data-link-desc="把文字切成 token 的算法：為什麼不同模型切出不同 token 數、tokenizer 選擇對能力的影響">3.6 tokenization 算法</a>。</p>
<p>Tokenizer 影響三件事：</p>
<ul>
<li><strong>Context 成本</strong>：同樣 prompt 在不同 tokenizer 上吃 token 量級不同、API 費用、<a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 利用率都跟著差。</li>
<li><strong>Token 粒度</strong>：粗粒度 tokenizer 對某語言的「字」切割不細、影響模型對該語言細微差異的辨識。</li>
<li><strong>訓練效率</strong>：tokenizer 切得好、模型每個 token 學到更多語意、訓練收斂快。</li>
</ul>
<h3 id="因素-2訓練資料分佈">因素 2：訓練資料分佈</h3>
<p>模型預訓練資料的語言佔比決定模型「學了多少」這個語言：</p>
<ul>
<li>Common Crawl 等主流預訓練資料英文佔 70%+、中文約 1-3%、其他語言更少。</li>
<li>即使 tokenizer 對某語言支援好、訓練資料少仍會限制模型在該語言上的能力。</li>
</ul>
<p>訓練分佈影響三件事：</p>
<ul>
<li><strong>事實準確度</strong>：訓練資料少 → 該語言的事實覆蓋低 → hallucination 多。</li>
<li><strong>Reasoning 深度</strong>：複雜推理需要大量該語言範例支撐、訓練少就退化。</li>
<li><strong>風格自然度</strong>：訓練少的語言、模型輸出語法 OK 但 idiom / 慣用搭配偏直譯。</li>
</ul>
<h3 id="雙因素的獨立性">雙因素的獨立性</h3>
<p>兩個因素獨立、各自影響不同維度：</p>
<table>
  <thead>
      <tr>
          <th>Tokenizer 好</th>
          <th>訓練資料多</th>
          <th>結果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>是</td>
          <td>是</td>
          <td>跨語言能力接近 native（Gemma 4 / Qwen3 在中文上的狀態）</td>
      </tr>
      <tr>
          <td>是</td>
          <td>否</td>
          <td>「會讀」但「不熟」、輸出語法 OK 但內容平庸</td>
      </tr>
      <tr>
          <td>否</td>
          <td>是</td>
          <td>能力 OK 但 cost 高、context 利用率差</td>
      </tr>
      <tr>
          <td>否</td>
          <td>否</td>
          <td>該語言基本不可用（Llama 2 對中文的狀態）</td>
      </tr>
  </tbody>
</table>
<p>判讀模型某語言能力時、兩個因素都要評估、單看一個會誤判。「Gemma 4 vocab 對中文好」不代表「中文表現一定好」、還要看訓練資料佔比。「OpenAI 訓練資料量大」不代表「對所有語言都好」、還要看 tokenizer 設計。</p>
<h2 id="tokenizer-vocab-對非英文的影響">Tokenizer Vocab 對非英文的影響</h2>
<p>Tokenizer vocab 設計直接決定中文 context 成本量級、差距可達兩倍以上。具體看 tokenizer 對中文的影響（以下為各 tokenizer 對該句的近似切割、實測會 ±20%、用作量級對照、不含 system prompt / response budget）：</p>
<table>
  <thead>
      <tr>
          <th>Tokenizer</th>
          <th>Vocab</th>
          <th>中文「敏捷的棕色狐狸跳過懶狗」估算 token 數</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Llama 2 BPE</td>
          <td>32K</td>
          <td>約 20（byte 級切割、一字常 2-3 個 token）</td>
      </tr>
      <tr>
          <td>GPT-4 tiktoken</td>
          <td>~100K</td>
          <td>約 12</td>
      </tr>
      <tr>
          <td>Llama 3 BPE</td>
          <td>128,256</td>
          <td>約 10</td>
      </tr>
      <tr>
          <td>Qwen3 BPE</td>
          <td>152,064</td>
          <td>約 10</td>
      </tr>
      <tr>
          <td>Gemma 3</td>
          <td>262,144</td>
          <td>約 9</td>
      </tr>
      <tr>
          <td>Gemma 4</td>
          <td>256,000</td>
          <td>約 9</td>
      </tr>
  </tbody>
</table>
<p>數字差異看似不大、累積起來影響顯著：</p>
<ul>
<li><strong>128K context 的「實際容量」</strong>：以中文每字平均 token 數估算、Llama 2（約 2.2 字 / token 的反比、即一字 ≈ 2-3 token）對中文約 6K 中文字、Gemma 4（接近一字一 token）對中文約 14K 中文字、差兩倍以上（估算未含 system prompt + response budget、實際可用更少）。</li>
<li><strong>API 費用</strong>：同樣中文 prompt、Llama 2 費用是 Gemma 4 的兩倍以上（按 token 收費的話）。</li>
<li><strong>長 prompt 的 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 時間</strong>：token 多 prefill 慢、<a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 受影響。</li>
</ul>
<p>但這只是其中一個因素。Tokenizer 改進不會自動讓模型「懂」這個語言——還要訓練資料配合。Llama 3 vocab 比 Llama 2 大很多、但對中文表現的提升不只是 vocab 帶來的、也是訓練資料多語言比例提升的結果。</p>
<h2 id="訓練資料分佈語言佔比決定能力">訓練資料分佈：語言佔比決定能力</h2>
<p>Web 文字的語言分佈嚴重不平衡。Common Crawl 跟同類資料源的語言佔比約：</p>
<ul>
<li>英文：60-70%</li>
<li>中文：2-5%</li>
<li>西班牙文、葡萄牙文、日文、法文、德文：各 1-3%</li>
<li>其他幾百種語言：合計 &lt; 10%</li>
</ul>
<p>模型預訓練多半反映這個分佈。即使「主打多語言」的模型、英文仍是主導。</p>
<p>實務影響：</p>
<ul>
<li><strong>事實準確度</strong>：問模型「台灣某縣市的人口」這類本地化問題、中文回答的準確度通常低於英文回答同個問題（即使翻譯為相同 query）。</li>
<li><strong>Reasoning 深度</strong>：複雜中文推理（如解中文奧數題）、模型可能「翻譯成英文 reasoning、再翻回中文」、中間步驟跳過、答案合理但推理鏈不通。</li>
<li><strong>風格 / 慣用語</strong>：中文輸出可能語法 OK、但 idiom 與慣用搭配偏直譯、詞彙選擇偏「翻譯腔」。</li>
<li><strong>長尾事實</strong>：訓練資料少的語言、長尾事實更容易 hallucinate。</li>
</ul>
<p>判讀模型在某語言上的能力強弱、看訓練資料佔比是主要訊號。Qwen 系列訓練資料大量中文、中文能力強；Llama 系列訓練資料英文為主、即使最新版中文表現仍弱於 Qwen 在中文上的表現。</p>
<h2 id="兩因素的獨立性對實務的影響">兩因素的獨立性對實務的影響</h2>
<p>雙因素獨立、實際模型多半落在某個組合狀態：</p>
<p><strong>Gemma 4 / Qwen3 / Llama 3 主流開源旗艦</strong>：</p>
<ul>
<li>Tokenizer：多語言、vocab 256K 級、中文 token 效率接近英文。</li>
<li>訓練資料：中英都有大量比例、Qwen 中文比例高、Llama 英文比例高。</li>
<li>結果：中文能力接近 native level、跨語言能力差距縮小。</li>
</ul>
<p><strong>OpenAI / Anthropic 雲端旗艦</strong>：</p>
<ul>
<li>Tokenizer：tiktoken 等、中文 token 效率中等。</li>
<li>訓練資料：規模極大、所有語言絕對量都多（即使相對佔比低）。</li>
<li>結果：中英都強、絕對能力受訓練規模支撐。</li>
</ul>
<p><strong>早期 Llama 2 / 純英文模型</strong>：</p>
<ul>
<li>Tokenizer：32K 英文中心、中文切散。</li>
<li>訓練資料：英文主導、其他語言極少。</li>
<li>結果：中文勉強可讀、不建議用於對輸出品質有要求的工作場景。</li>
</ul>
<p>判讀新模型對某語言能力時、先看這兩個因素、再參考實測——比直接看 benchmark 數字準。</p>
<h2 id="中文-prompt-何時該翻英機會成本判讀">中文 Prompt 何時該翻英：機會成本判讀</h2>
<p>寫 code 場景常見問題「該用中文還是英文寫 prompt」、答案取決於三個變數：</p>
<h3 id="變數-1模型在中英的能力差距">變數 1：模型在中英的能力差距</h3>
<p>主流開源旗艦（Gemma 4 / Qwen3 / Llama 3）中英差距已縮小、寫 code 場景中英 prompt 表現接近。早期 / 較小模型差距大、英文 prompt 較穩。</p>
<p>判讀：用較強模型可以維持中文、用較弱模型考慮翻英。</p>
<h3 id="變數-2翻譯成本">變數 2：翻譯成本</h3>
<p>翻譯成本包括：時間、認知負擔、可能的精度損失。</p>
<ul>
<li>簡短 prompt（補完、寫單個 function）：翻英成本低、可考慮。</li>
<li>長 prompt（描述複雜需求、多個檔案 context）：翻英成本高、維持中文較划算。</li>
<li>含技術術語的 prompt：英文是 LLM 訓練的主流、術語維持英文較好（即使句子是中文也保留英文 keyword）。</li>
</ul>
<h3 id="變數-3輸出語言要求">變數 3：輸出語言要求</h3>
<ul>
<li>要中文回答（如寫中文 docs、跟中文團隊溝通）：維持中文 prompt 一致性較好。</li>
<li>要英文回答（如 commit message、open source PR）：英文 prompt 自然引導英文輸出、不需 explicit instruct。</li>
</ul>
<h3 id="綜合判讀">綜合判讀</h3>
<p>寫 code 場景的多數情境（主流模型 + 短 prompt + 維持原語言輸出）：直接用中文寫即可、不必特別翻英。例外：</p>
<ul>
<li>用較弱模型（&lt; 14B）、英文較穩。</li>
<li>特殊領域（法律、醫療、學術）、英文資料豐富、翻英可能更穩。</li>
<li>Domain-specific reasoning（數學、邏輯）、英文訓練資料多、翻英可能改善 reasoning 鏈。</li>
</ul>
<p>「直覺說該翻英」常是過度小心、實測通常發現中文跟英文 prompt 表現接近、翻譯成本浪費。</p>
<h2 id="commit--docstring--註解的語言選擇取捨">Commit / Docstring / 註解的語言選擇取捨</h2>
<p>寫 code 場景的「該用什麼語言」決策多半取決於非模型因素：</p>
<h3 id="commit-message">Commit Message</h3>
<ul>
<li><strong>團隊一致性</strong>：團隊都用英文就英文、都用中文就中文。</li>
<li><strong>長期保留</strong>：commit message 進 git 歷史、長期保留、跨團隊成員 / 外部貢獻者讀。</li>
<li><strong>可讀性受眾</strong>：團隊有非中文 reader 就英文、純中文團隊用中文也 OK。</li>
<li><strong>隱私 / 合規</strong>：commit 進 git、可能進 public repo、敏感資訊不該寫進去（不論語言）。</li>
</ul>
<p>模型對中英 commit message 都能寫、選擇主要看團隊跟 repo 屬性、不是看模型偏好。</p>
<h3 id="docstring">Docstring</h3>
<ul>
<li><strong>語言生態慣例</strong>：Python / JavaScript 開源社群慣例是英文 docstring；JetBrains / 微軟在地化文件多中文。</li>
<li><strong>API consumer</strong>：API 給誰用、用什麼語言。</li>
<li><strong>自動化工具</strong>：docs generator、type checker、IDE hint 對英文 docstring 支援較成熟。</li>
</ul>
<h3 id="程式內註解">程式內註解</h3>
<ul>
<li><strong>團隊母語 vs 國際慣例</strong>：團隊母語寫註解最自然、國際慣例（特別 open source）多英文。</li>
<li><strong>複雜邏輯</strong>：用最能精確表達的語言寫、不一定要英文。</li>
<li><strong>TODO / FIXME</strong>：跟團隊慣例一致。</li>
</ul>
<p>這些決策本質上是團隊跟生態問題、不是 LLM 問題。LLM 對中英都能 handle、選哪個取決於 downstream 讀者。</p>
<h2 id="跨語言-reasoning-的失敗訊號">跨語言 Reasoning 的失敗訊號</h2>
<p>跨語言 reasoning（如中文 prompt 要求模型用中文推理過數學題、或用中文回答需要英文事實 retrieval 的問題）容易出現幾種失敗：</p>
<h3 id="內部翻譯失敗">內部翻譯失敗</h3>
<p>模型「中文 prompt → 內部翻譯成英文 reasoning → 翻回中文輸出」、中間步驟跳過、中文輸出看起來合理但推理鏈不通。</p>
<p>判讀訊號：要求模型「請用中文逐步推理」、模型輸出推理鏈不連貫、步驟跳躍。</p>
<p>緩解：強制 step-by-step prompt、或乾脆翻英 prompt 拿英文輸出、再人工譯回中文。</p>
<h3 id="訓練語言切換">訓練語言切換</h3>
<p>模型在某語言上 reasoning 訓練不足、即使理解 query、輸出推理深度受限。</p>
<p>判讀訊號：中文 query 拿到淺薄答案、同樣 query 翻英拿到深入答案。</p>
<p>緩解：複雜推理任務用英文 prompt + 英文輸出、最後再翻譯。</p>
<h3 id="tokenizer-引發的細節遺失">Tokenizer 引發的細節遺失</h3>
<p>中文一字切多個 token 時、模型可能在 token 邊界誤判語意、輸出細節不準。</p>
<p>判讀訊號：細節錯（罕用字 OOV 被切成 byte / 數字本身切分不一致導致算術出錯）、英文同義問題不會錯。</p>
<p>緩解：對細節敏感的任務（數字、日期、人名）強調確認、或翻英降低 tokenizer 誤判機率。</p>
<h3 id="何時跨語言-reasoning-不會失敗--何時翻英無收益">何時跨語言 reasoning 不會失敗 / 何時翻英無收益</h3>
<p>上述三類失敗模式不會均勻發生在所有跨語言任務上、實際觸發條件是「深度推理 + 語言 specific 事實 retrieval」雙條件命中。以下情境通常翻英沒收益、留在中文 prompt 反而省事：</p>
<ul>
<li><strong>Code 補完、語法重構、加 type annotation</strong>：code 本身就跨語言、模型不需要「翻譯」code、中文 prompt 直接寫即可。</li>
<li><strong>短 QA、context-rich prompt</strong>：問題本身就含完整 context（如「這段程式碼做什麼」+ code）、模型不需要做 retrieval、reasoning 深度需求低。</li>
<li><strong>格式 / 結構轉換</strong>：JSON 轉 YAML、Markdown 重排、tabular 整理 — 任務機械化、跟語言關係小。</li>
<li><strong>單檔 refactor</strong>：選定範圍內的改寫、不需跨檔 retrieval、推理深度受 context 限制而非語言。</li>
<li><strong>commit message / docstring 草稿</strong>：套用 template 性質、模型輸出語言跟 prompt 一致較自然。</li>
</ul>
<p>需要翻英的場景集中在「深度推理（多步邏輯 / 數學）」+「需要 retrieval 語言 specific 事實（如某個 framework 的 API、特定論文細節、英文社群討論）」這兩條都命中時、其他場景翻譯成本是浪費。</p>
<h2 id="code-跟自然語言的不對稱">Code 跟自然語言的不對稱</h2>
<p>Code 本身是「英文偏向」的：keyword（<code>if</code>、<code>for</code>、<code>return</code>）、變數名（多半 ASCII）、API（多半英文）。LLM 對 code 的能力跨語言差距較小——code 本身就跨語言、模型不需要「翻譯」code。</p>
<p>但「code + 自然語言」的混合場景仍受自然語言訓練分佈影響：</p>
<ul>
<li>寫 code + 中文 docstring：模型寫 code 表現一致、寫 docstring 受訓練分佈影響。</li>
<li>解釋 code 給人聽：用哪種語言解釋、受該語言訓練分佈影響。</li>
<li>改寫 code 註解：改 code 行為一致、改自然語言部分受訓練分佈影響。</li>
</ul>
<p>判讀「該不該翻英」時、要區分「code 部分」跟「自然語言部分」。Code 部分中英差距小、自然語言部分中英差距視模型而定。</p>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>Tokenizer + 訓練分佈雙因素 framing。</li>
<li>跨語言能力受結構性限制的本質（不只是「模型不夠強」）。</li>
<li>三個變數判讀（能力差距、翻譯成本、輸出語言要求）。</li>
<li>跨語言 reasoning 失敗模式的分類。</li>
<li>Code 跟自然語言的不對稱觀察。</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體模型在特定語言上的當下能力（會隨新模型版本變、Gemma 5 / Qwen4 等出來會再變）。</li>
<li>各 tokenizer 的 vocab 大小（會調整）。</li>
<li>訓練資料的多語言比例（業界正在改善）。</li>
<li>哪些模型「中文能力好」的具體 ranking。</li>
</ul>
<p>看到新模型時、回到雙因素 framework 評估：tokenizer vocab 多大、中文 token 效率如何、訓練資料中文佔比、實測中文表現是否符合預期——這個 framework 不變、評估結果會隨模型版本更新。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/reasoning-models/" data-link-title="3.8 Reasoning models：test-time compute paradigm" data-link-desc="Chain-of-thought 從 prompting 技巧演化成訓練 paradigm、reasoning model 的內部運作、本地可跑的選項與適用任務">3.8 Reasoning models</a>、看 2024-2026 的 test-time compute paradigm。完整公開課推薦見 <a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">3.10 想學更深</a>。</p>
]]></content:encoded></item><item><title>3.8 Reasoning models：test-time compute paradigm</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/reasoning-models/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/reasoning-models/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">Reasoning model&lt;/a> 把「LLM 該想多久」從固定的 forward pass 數變成&lt;strong>可訓練、可在推論時動態擴展&lt;/strong>的維度。OpenAI o1（2024 年底）跟 DeepSeek-R1（2025 年初）是這條路線的兩個里程碑、後續 Qwen-QwQ、Claude thinking、Gemini thinking 等都跟上。本章把 reasoning model 的訓練原理、推論行為、本地可跑選項、適用 / 不適用任務拆成可操作的判讀。&lt;/p>
&lt;p>本章不重複 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute&lt;/a> 卡片的定義、聚焦「reasoning model 怎麼運作、怎麼跟本地工作流結合」。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋「reasoning model」相對 instruct model 的訓練差異。&lt;/li>
&lt;li>看到 &lt;code>&amp;lt;think&amp;gt;...&amp;lt;/think&amp;gt;&lt;/code> 標記或「extended thinking」field 時、知道是 reasoning trace、怎麼解讀。&lt;/li>
&lt;li>判斷一個任務該用 reasoning model 還是 instruct model。&lt;/li>
&lt;li>對自己的硬體預算估算「能不能本地跑 reasoning model」、選哪個。&lt;/li>
&lt;/ol>
&lt;h2 id="paradigm-shift從-scaling-pretrain-到-scaling-test-time">Paradigm shift：從 scaling pretrain 到 scaling test-time&lt;/h2>
&lt;p>LLM 能力提升的兩條歷史路徑：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">2020-2023 時期：scale pretrain compute
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> GPT-3 → GPT-4：模型大 5-10×、訓練 compute 大 50-100×
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> 策略：更多參數 + 更多訓練 token = 更好的 base model
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">2024-2026 時期：scale test-time compute
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> GPT-4 → o1：模型大小接近、但推論時花 5-50× 算力
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> 策略：base model 不變、訓練「推理能力」+ 推論時動態擴展 reasoning trace&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>兩條路線&lt;strong>不對立&lt;/strong>、是疊加：reasoning model 本身仍跑在大 base model 上、reasoning RL 是再加一層後訓練。Cost trade-off 對比的 framing 跟對使用者錢包的影響、見 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute 卡片&lt;/a>。本章接下來聚焦「reasoning model 的訓練流程」跟「本地選型」、不重複 paradigm 層的對比。&lt;/p>
&lt;p>關鍵理解：reasoning model 不是「更聰明的 GPT-4」、是「同等聰明 base model + 學會把算力花在 reasoning 上」。底層 base model 依然是 Transformer、所有前面章節（attention、FFN、sampling）原理不變。&lt;/p>
&lt;h2 id="reasoning-model-的訓練流程">Reasoning model 的訓練流程&lt;/h2>
&lt;p>DeepSeek-R1 是第一個公開細節的開源 reasoning model、其 paper 揭示的訓練流程具有代表性：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">Stage 1: Cold-start SFT
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> 用幾千份「高品質 long reasoning trace」資料 fine-tune base model
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 目標：讓模型學會「該怎麼想」的 format
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">Stage 2: Reasoning-focused RL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> Reward：最終答案正確（math / code / logic 等可機械驗證的任務）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Policy：把 reasoning trace 越拉越長、越能正確、reward 越高
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 約束：保留語言流暢度（不能 reasoning trace 變成亂碼）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> → 模型自發學會「困難問題想更久」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">Stage 3: SFT on reasoning + non-reasoning data
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> 把 reasoning RL 學到的能力跟一般 instruct 能力 mix
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> 避免「只會 reasoning、不會聊天」
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">Stage 4: Final RLHF / DPO（可選）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> 跟 instruct model 同樣的 alignment 階段、refine helpfulness&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵特性：&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">Reasoning model</a> 把「LLM 該想多久」從固定的 forward pass 數變成<strong>可訓練、可在推論時動態擴展</strong>的維度。OpenAI o1（2024 年底）跟 DeepSeek-R1（2025 年初）是這條路線的兩個里程碑、後續 Qwen-QwQ、Claude thinking、Gemini thinking 等都跟上。本章把 reasoning model 的訓練原理、推論行為、本地可跑選項、適用 / 不適用任務拆成可操作的判讀。</p>
<p>本章不重複 <a href="/blog/llm/knowledge-cards/chain-of-thought/" data-link-title="Chain-of-Thought（CoT）" data-link-desc="讓 LLM 先輸出推理步驟再給最終答案的 prompting / 訓練方式、reasoning model 的基礎機制">chain-of-thought</a> 跟 <a href="/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute</a> 卡片的定義、聚焦「reasoning model 怎麼運作、怎麼跟本地工作流結合」。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋「reasoning model」相對 instruct model 的訓練差異。</li>
<li>看到 <code>&lt;think&gt;...&lt;/think&gt;</code> 標記或「extended thinking」field 時、知道是 reasoning trace、怎麼解讀。</li>
<li>判斷一個任務該用 reasoning model 還是 instruct model。</li>
<li>對自己的硬體預算估算「能不能本地跑 reasoning model」、選哪個。</li>
</ol>
<h2 id="paradigm-shift從-scaling-pretrain-到-scaling-test-time">Paradigm shift：從 scaling pretrain 到 scaling test-time</h2>
<p>LLM 能力提升的兩條歷史路徑：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">2020-2023 時期：scale pretrain compute
</span></span><span class="line"><span class="ln">2</span><span class="cl">  GPT-3 → GPT-4：模型大 5-10×、訓練 compute 大 50-100×
</span></span><span class="line"><span class="ln">3</span><span class="cl">  策略：更多參數 + 更多訓練 token = 更好的 base model
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">2024-2026 時期：scale test-time compute
</span></span><span class="line"><span class="ln">6</span><span class="cl">  GPT-4 → o1：模型大小接近、但推論時花 5-50× 算力
</span></span><span class="line"><span class="ln">7</span><span class="cl">  策略：base model 不變、訓練「推理能力」+ 推論時動態擴展 reasoning trace</span></span></code></pre></div><p>兩條路線<strong>不對立</strong>、是疊加：reasoning model 本身仍跑在大 base model 上、reasoning RL 是再加一層後訓練。Cost trade-off 對比的 framing 跟對使用者錢包的影響、見 <a href="/blog/llm/knowledge-cards/test-time-compute/" data-link-title="Test-Time Compute" data-link-desc="推論時動態增加計算量換取答案品質的 paradigm、reasoning model 跟 best-of-N 的共同基底">test-time compute 卡片</a>。本章接下來聚焦「reasoning model 的訓練流程」跟「本地選型」、不重複 paradigm 層的對比。</p>
<p>關鍵理解：reasoning model 不是「更聰明的 GPT-4」、是「同等聰明 base model + 學會把算力花在 reasoning 上」。底層 base model 依然是 Transformer、所有前面章節（attention、FFN、sampling）原理不變。</p>
<h2 id="reasoning-model-的訓練流程">Reasoning model 的訓練流程</h2>
<p>DeepSeek-R1 是第一個公開細節的開源 reasoning model、其 paper 揭示的訓練流程具有代表性：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Stage 1: Cold-start SFT
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  用幾千份「高品質 long reasoning trace」資料 fine-tune base model
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  目標：讓模型學會「該怎麼想」的 format
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">Stage 2: Reasoning-focused RL
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  Reward：最終答案正確（math / code / logic 等可機械驗證的任務）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Policy：把 reasoning trace 越拉越長、越能正確、reward 越高
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  約束：保留語言流暢度（不能 reasoning trace 變成亂碼）
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  → 模型自發學會「困難問題想更久」
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">Stage 3: SFT on reasoning + non-reasoning data
</span></span><span class="line"><span class="ln">12</span><span class="cl">  把 reasoning RL 學到的能力跟一般 instruct 能力 mix
</span></span><span class="line"><span class="ln">13</span><span class="cl">  避免「只會 reasoning、不會聊天」
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">Stage 4: Final RLHF / DPO（可選）
</span></span><span class="line"><span class="ln">16</span><span class="cl">  跟 instruct model 同樣的 alignment 階段、refine helpfulness</span></span></code></pre></div><p>關鍵特性：</p>
<ol>
<li><strong>Stage 2 的 reward 機械可驗證</strong>：math 答案、code unit test、logic 答案 — 不需要 human preference、所以可大量擴展訓練資料</li>
<li><strong>Reasoning trace 是「emerge」出來的</strong>：訓練不直接告訴模型「該怎麼想」、只給「答案對不對」、模型自己摸索出最佳 reasoning strategy</li>
<li><strong>跨任務 transfer 有限</strong>：reasoning model 在訓練分佈內任務（math、coding）強、跨到開放域對話、提升較小</li>
</ol>
<p><a href="/blog/llm/knowledge-cards/reasoning-model/" data-link-title="Reasoning Model" data-link-desc="訓練成自然輸出長 reasoning trace 的 LLM 變體、o1 / DeepSeek-R1 / Claude thinking 為代表">DeepSeek-R1 distill 系列</a> 是另一條路：用 R1 full 模型產生 reasoning trace、再 SFT 一個小 base model（如 Qwen2.5-32B）— 讓較小模型也有 reasoning 能力、但跳過昂貴的 RL 階段。</p>
<h2 id="reasoning-trace-的格式">Reasoning trace 的格式</h2>
<p>主流 reasoning model 在推論時輸出 reasoning trace 的格式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">DeepSeek-R1 / Qwen-QwQ：用特殊 token 標記
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  &lt;think&gt;
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  讓我先列出已知條件...先試 case 1...結果矛盾、改試 case 2...
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  &lt;/think&gt;
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  最終答案：X
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">OpenAI o1：對使用者隱藏
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  API 只回最終答案、但計費 reasoning token
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  使用者看不到 reasoning trace 內容
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">Claude 3.7 thinking：extended thinking field
</span></span><span class="line"><span class="ln">12</span><span class="cl">  API response 含 `extended_thinking` 跟 `text` 兩個 field
</span></span><span class="line"><span class="ln">13</span><span class="cl">  IDE / chat 介面通常折疊顯示 thinking 內容</span></span></code></pre></div><p>實作層的關鍵考量：</p>
<ol>
<li><strong>Tokenizer 對 reasoning token 的處理</strong>：<code>&lt;think&gt;</code> 等特殊 token 在 vocab 中被保留、tokenizer 識別後不切碎</li>
<li><strong>Context budget 分配</strong>：reasoning trace 通常 1000-10000 token、要預留 <a href="/blog/llm/knowledge-cards/context-window/" data-link-title="Context Window" data-link-desc="模型一次能處理的最大 token 數量：prompt 加生成的總和上限">context window</a> 容量</li>
<li><strong>Streaming 行為</strong>：reasoning trace streaming 時、使用者看到「模型在想」、TTFT 變短但「first useful output」變長</li>
<li><strong>Stop sequence</strong>：sampling 階段 <code>&lt;/think&gt;</code> 或對應結束 token 是 reasoning trace 的 terminator</li>
</ol>
<h2 id="本地可跑的-reasoning-model">本地可跑的 reasoning model</h2>
<p>2026/5 時、本地寫 code 工作流可考慮的 reasoning model：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>大小</th>
          <th>Q4 量化後記憶體</th>
          <th>適合硬體</th>
          <th>reasoning trace 平均 token</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DeepSeek-R1-Distill-Qwen-7B</td>
          <td>7B</td>
          <td>~4 GB</td>
          <td>16GB+ Mac / 16GB+ VRAM</td>
          <td>500-2000</td>
      </tr>
      <tr>
          <td>DeepSeek-R1-Distill-Qwen-14B</td>
          <td>14B</td>
          <td>~8 GB</td>
          <td>24GB+ Mac / 16GB+ VRAM</td>
          <td>1000-3000</td>
      </tr>
      <tr>
          <td>DeepSeek-R1-Distill-Qwen-32B</td>
          <td>32B</td>
          <td>~18 GB</td>
          <td>32GB+ Mac / 24GB+ VRAM</td>
          <td>1500-5000</td>
      </tr>
      <tr>
          <td>QwQ-32B</td>
          <td>32B</td>
          <td>~18 GB</td>
          <td>32GB+ Mac / 24GB+ VRAM</td>
          <td>2000-8000</td>
      </tr>
      <tr>
          <td>DeepSeek-R1（full）</td>
          <td>671B（MoE）</td>
          <td>~140 GB</td>
          <td>不實際本地跑</td>
          <td>5000-30000</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：模型大小、量化體積、reasoning trace 長度是 2026/5 主流版本的常見數量級；具體數字隨量化等級、context 配置、任務類型而變、引用前以對應 model card 跟自己 <code>llama-bench</code> 跑為準。</p></blockquote>
<p>選型判讀（個人 dev 場景）：</p>
<ol>
<li><strong>24GB Mac（M4 Pro）</strong>：可跑 14B distill、或 32B distill Q4 緊張、context 開小</li>
<li><strong>32GB Mac（M4 Pro 升級）</strong>：跑 32B distill 舒服、context 32K+ 可開</li>
<li><strong>48GB+ Mac（M4 Max）</strong>：跑 32B distill 寬鬆、可考慮 QwQ-32B 配 64K context</li>
<li><strong>16GB+ VRAM PC</strong>：跑 14B distill；32B distill 屬 dense 架構（不是 MoE）、要用 dense CPU offload（部分層放 RAM、靠 PCIe 走、tok/s 受 PCIe 頻寬限制）、跟 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE CPU offload</a> 是不同的戰術</li>
<li><strong>24GB+ VRAM PC（5090）</strong>：跑 32B distill 寬鬆</li>
</ol>
<h2 id="適合-reasoning-model-的任務">適合 reasoning model 的任務</h2>
<p>Reasoning model 的優勢任務有明確 pattern：</p>
<table>
  <thead>
      <tr>
          <th>任務類型</th>
          <th>為什麼適合</th>
          <th>案例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>複雜 algorithm design</td>
          <td>需要多步推理 + 探索多個解法</td>
          <td>Leetcode hard、設計 sliding window 解法</td>
      </tr>
      <tr>
          <td>棘手 debug</td>
          <td>需要排除多種可能、追蹤跨檔案邏輯</td>
          <td>「為什麼這個 race condition 偶爾出現」</td>
      </tr>
      <tr>
          <td>Math / 量化分析</td>
          <td>機械可驗證、模型訓練分佈內</td>
          <td>估算系統 capacity、複雜利率計算</td>
      </tr>
      <tr>
          <td>Multi-step refactor 規劃</td>
          <td>需要看到整體影響、分階段</td>
          <td>「把這個 service 拆成 3 個 microservice 的步驟」</td>
      </tr>
      <tr>
          <td>系統設計取捨</td>
          <td>多 dimension 比較、需要展開論證</td>
          <td>「DB 該選 Postgres 還是 Cassandra」</td>
      </tr>
      <tr>
          <td>解 obscure error</td>
          <td>需要 reason about 多個可能根因</td>
          <td>「kernel panic 訊息 X 可能來源」</td>
      </tr>
  </tbody>
</table>
<p>不適合用 reasoning model 的任務（用 instruct model 即可）：</p>
<table>
  <thead>
      <tr>
          <th>任務類型</th>
          <th>為什麼不適合</th>
          <th>改用</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Autocomplete</td>
          <td>reasoning trace 拉長 TTFT、體感變慢</td>
          <td>Instruct 小模型（如 Qwen3-Coder-7B）</td>
      </tr>
      <tr>
          <td>簡單 docstring / comment</td>
          <td>過度推理、浪費 token</td>
          <td>Instruct model</td>
      </tr>
      <tr>
          <td>純翻譯 / 風格改寫</td>
          <td>不需要 reasoning</td>
          <td>Instruct model</td>
      </tr>
      <tr>
          <td>高頻短查詢</td>
          <td>每次 reasoning overhead 累積</td>
          <td>Instruct model + KV cache</td>
      </tr>
      <tr>
          <td>已知答案的查表</td>
          <td>reasoning 反而引入錯誤</td>
          <td>Instruct model</td>
      </tr>
      <tr>
          <td>探索性 brainstorming</td>
          <td>不需要「正確答案」、reasoning 反而限制創意</td>
          <td>Instruct model + 高 temperature</td>
      </tr>
  </tbody>
</table>
<p>判讀反射：先問「這任務有沒有客觀正確答案 + 是否需要多步推理」、兩者都 yes 才用 reasoning model。</p>
<h2 id="reasoning-model--tool-use">Reasoning model + tool use</h2>
<p>Reasoning model 跟 <a href="/blog/llm/knowledge-cards/tool-use/" data-link-title="Tool Use" data-link-desc="LLM 透過結構化呼叫外部工具（讀檔、查資料庫、發 API request）來擴展能力的設計、function calling 跟 MCP 是常見實作">tool use</a> 結合是 2026 新趨勢、典型形態：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">模型在 reasoning trace 中發現「需要驗證一個事實」
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">3</span><span class="cl">呼叫 tool（calculator / web search / code interpreter）
</span></span><span class="line"><span class="ln">4</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">5</span><span class="cl">拿到結果、繼續 reasoning
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ↓
</span></span><span class="line"><span class="ln">7</span><span class="cl">最終答案</span></span></code></pre></div><p>代表場景：</p>
<ol>
<li><strong>Coding agent + reasoning</strong>：reasoning 階段規劃 refactor 步驟、tool use 階段執行 file edit、reasoning 階段檢查結果</li>
<li><strong>Math / data analysis</strong>：reasoning 階段拆問題、code interpreter 跑 calculation、reasoning 階段解讀</li>
<li><strong>Web 研究</strong>：reasoning 階段列出該查的事實、web search、reasoning 階段彙整</li>
</ol>
<p>挑戰：</p>
<ol>
<li><strong>Reasoning trace + tool result 都進 context</strong>：context 用量爆炸快、需要 long context 模型（見 <a href="/blog/llm/04-applications/long-context-engineering/" data-link-title="4.11 Long context engineering" data-link-desc="128K / 1M context 模型怎麼用：claimed vs effective context、lost-in-the-middle、context 設計策略、Long context vs RAG 取捨">4.11 Long context engineering</a>）</li>
<li><strong>Tool use 訓練跟 reasoning 訓練是兩件事</strong>：本地 distill 模型 tool use 能力 = 對應 base model 的 tool use 能力、不一定強</li>
<li><strong>Error recovery</strong>：reasoning 階段假設錯了、tool 回 error、模型要會 backtrack（<a href="/blog/llm/knowledge-cards/agent-loop/" data-link-title="Agent Loop" data-link-desc="LLM agent 自我循環的工作流：LLM 規劃下一步、執行 tool、看結果、再規劃下一步、直到任務完成或停止條件觸發">agent loop</a> 失敗模式）</li>
</ol>
<p>實務上、本地 reasoning + agent 是「值得試、但仍處早期」階段；雲端 R1 / o3 / Claude thinking + Claude Code / Cursor 是現階段更穩的組合。</p>
<h2 id="跟-instruct-model-共存的混用策略">跟 instruct model 共存的混用策略</h2>
<p>寫 code 場景的合理混用配置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Default model（Continue.dev primary）：instruct model
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  Qwen3-Coder-30B-Instruct / Gemma 4 31B Instruct
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  日常 autocomplete、解釋、簡單 refactor
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">Reasoning model（Continue.dev secondary、手動切）：local reasoning
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  DeepSeek-R1-Distill-Qwen-32B / QwQ-32B
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  困難 bug、algorithm、複雜 refactor 規劃
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Cloud fallback（手動切）：雲端旗艦
</span></span><span class="line"><span class="ln">10</span><span class="cl">  Claude 3.7 Sonnet thinking / GPT-5 / o3
</span></span><span class="line"><span class="ln">11</span><span class="cl">  本地 reasoning 卡住、或極困難任務</span></span></code></pre></div><p>Continue.dev 的 multi-model config 可同時設多個、UI 下拉切換、不用重啟 server。安全 / 隱私面：reasoning trace 可能含敏感推理過程、跨雲端 / 本地邊界判讀同 <a href="/blog/llm/06-security/cross-cloud-local-data-boundary/" data-link-title="6.4 跨雲端 / 本地的資料邊界" data-link-desc="個人 dev 場景下混用雲端 LLM 跟本地 LLM 時的 prompt 洩漏點：Continue.dev 多 provider 設定、隱私資料流、按敏感度分流的判讀">6.4</a>。</p>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>Test-time compute 作為一個獨立 scaling 維度的概念</li>
<li>Reasoning trace 結構（pre-answer reasoning + answer）</li>
<li>「適合 reasoning vs instruct」的判讀框架</li>
<li>「機械可驗證的 reward + RL」是 reasoning training 的核心</li>
<li>Reasoning model + tool use 的設計取捨</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體 reasoning model（R1 → R2 → &hellip;、o1 → o3 → &hellip;、會持續迭代）</li>
<li>Reasoning trace 的具體格式（<code>&lt;think&gt;</code>、extended thinking field、未來可能標準化）</li>
<li>本地可跑的模型選項（distill 系列會持續更新）</li>
<li>Reasoning 跟 agent 結合的最佳實踐（仍在演化）</li>
<li>是否會出現 reasoning paradigm 的下一個替代（如 neurosymbolic、multi-agent reasoning）</li>
</ul>
<p>新 reasoning model 出來時、回到本章的 framing：訓練流程是否同 R1 pattern、reasoning trace 怎麼產出、本地能否跑、適用任務是否同樣 pattern — 多數新模型仍會 fit 進這個框架。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/speculative-decoding-internals/" data-link-title="3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限" data-link-desc="speculative decoding 的演算法細節、drafter 跟 target 怎麼配對、acceptance rate 怎麼決定實際加速、MTP 跟 EAGLE 等變體">3.9 Speculative decoding 內部</a>、看另一個推論時加速的技術細節。</p>
]]></content:encoded></item><item><title>3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/speculative-decoding-internals/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/speculative-decoding-internals/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding&lt;/a> 在多個前面章節被引用作為「LLM 推論加速的主要技術之一」。本章把這個機制完整展開：為什麼能加速、acceptance 怎麼運作、實際加速倍率怎麼算、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter model&lt;/a> 怎麼選、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> / EAGLE 等變體的關係。&lt;/p>
&lt;p>讀完本章後、看到「speculative decoding 加速 2.5×」這類聲稱時、能判斷可信度、能對自己工作流估算實際收益、能挑對 drafter。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>解釋為什麼 speculative decoding 能在「不降品質」前提下加速。&lt;/li>
&lt;li>區分 drafter-based、MTP、EAGLE 三條主流路線。&lt;/li>
&lt;li>用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/acceptance-rate/" data-link-title="Acceptance Rate" data-link-desc="speculative decoding 中 drafter 提出的 token 被 target model 接受的比例、決定實際加速倍率">acceptance rate&lt;/a> 估算實際加速倍率。&lt;/li>
&lt;li>判斷一個 drafter / target 配對是否值得用。&lt;/li>
&lt;li>看到 &lt;code>llama-bench&lt;/code> 結果時、判讀「speculative speed」對自己場景的意義。&lt;/li>
&lt;/ol>
&lt;h2 id="為什麼能加速memory-bandwidth-bound-的縫隙">為什麼能加速：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> bound 的縫隙&lt;/h2>
&lt;p>回顧 LLM 推論的瓶頸：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass&lt;/a> 每生一個 token 要把整份模型權重從記憶體讀到處理器一次、所以 memory bandwidth 是上限。每次讀的時候、處理器有大量算力是閒置的（modern GPU / Apple Silicon 算力遠超頻寬）。&lt;/p>
&lt;p>Speculative decoding 攻擊這個閒置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">單純 autoregressive 推論：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> 每 token：讀整份權重 → 算 forward → 出 1 個 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 讀權重 N 次、生 N 個 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> 瓶頸 = memory bandwidth × N
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Speculative decoding（K=4）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Drafter 一次生 4 個候選 token（drafter 小、讀它的權重快）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> Target 一次驗證 4 個位置（並行算 forward、權重只讀 1 次）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 若全部接受、生 4-5 個 token（含 bonus）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> 讀 target 權重次數從 4 降到 1、平均 token 成本顯著降&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵理解：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Target model 的 forward pass 對 K 個位置是並行的&lt;/strong>：一次讀權重、做矩陣乘法時把 K 個位置同時算（batch dimension 變大）&lt;/li>
&lt;li>&lt;strong>算力是免費資源&lt;/strong>：原本閒置的算力被用來「同時算多個位置」、不增加 memory bandwidth 消耗&lt;/li>
&lt;li>&lt;strong>正確性保證&lt;/strong>：sampling 階段的接受 / 拒絕邏輯確保最終輸出分佈跟「純 target 自回歸生成」一致 — speculative decoding 不降品質、只省時間&lt;/li>
&lt;/ol>
&lt;h2 id="演算法核心sampling-階段的接受邏輯">演算法核心：sampling 階段的接受邏輯&lt;/h2>
&lt;p>詳細的接受機制（簡化版）：&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding</a> 在多個前面章節被引用作為「LLM 推論加速的主要技術之一」。本章把這個機制完整展開：為什麼能加速、acceptance 怎麼運作、實際加速倍率怎麼算、<a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter model</a> 怎麼選、跟 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> / EAGLE 等變體的關係。</p>
<p>讀完本章後、看到「speculative decoding 加速 2.5×」這類聲稱時、能判斷可信度、能對自己工作流估算實際收益、能挑對 drafter。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>解釋為什麼 speculative decoding 能在「不降品質」前提下加速。</li>
<li>區分 drafter-based、MTP、EAGLE 三條主流路線。</li>
<li>用 <a href="/blog/llm/knowledge-cards/acceptance-rate/" data-link-title="Acceptance Rate" data-link-desc="speculative decoding 中 drafter 提出的 token 被 target model 接受的比例、決定實際加速倍率">acceptance rate</a> 估算實際加速倍率。</li>
<li>判斷一個 drafter / target 配對是否值得用。</li>
<li>看到 <code>llama-bench</code> 結果時、判讀「speculative speed」對自己場景的意義。</li>
</ol>
<h2 id="為什麼能加速memory-bandwidth-bound-的縫隙">為什麼能加速：<a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> bound 的縫隙</h2>
<p>回顧 LLM 推論的瓶頸：<a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass</a> 每生一個 token 要把整份模型權重從記憶體讀到處理器一次、所以 memory bandwidth 是上限。每次讀的時候、處理器有大量算力是閒置的（modern GPU / Apple Silicon 算力遠超頻寬）。</p>
<p>Speculative decoding 攻擊這個閒置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">單純 autoregressive 推論：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  每 token：讀整份權重 → 算 forward → 出 1 個 token
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  讀權重 N 次、生 N 個 token
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  瓶頸 = memory bandwidth × N
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Speculative decoding（K=4）：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Drafter 一次生 4 個候選 token（drafter 小、讀它的權重快）
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  Target 一次驗證 4 個位置（並行算 forward、權重只讀 1 次）
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  若全部接受、生 4-5 個 token（含 bonus）
</span></span><span class="line"><span class="ln">10</span><span class="cl">  讀 target 權重次數從 4 降到 1、平均 token 成本顯著降</span></span></code></pre></div><p>關鍵理解：</p>
<ol>
<li><strong>Target model 的 forward pass 對 K 個位置是並行的</strong>：一次讀權重、做矩陣乘法時把 K 個位置同時算（batch dimension 變大）</li>
<li><strong>算力是免費資源</strong>：原本閒置的算力被用來「同時算多個位置」、不增加 memory bandwidth 消耗</li>
<li><strong>正確性保證</strong>：sampling 階段的接受 / 拒絕邏輯確保最終輸出分佈跟「純 target 自回歸生成」一致 — speculative decoding 不降品質、只省時間</li>
</ol>
<h2 id="演算法核心sampling-階段的接受邏輯">演算法核心：sampling 階段的接受邏輯</h2>
<p>詳細的接受機制（簡化版）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">給定：drafter D、target T、context prefix x、speculative length K
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">Step 1：D 從 x 生 K 個候選 token：d_1, d_2, ..., d_K
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        對每個位置算 D(d_i | x, d_1..i-1) 機率
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Step 2：T 對 (x, d_1, d_2, ..., d_K) 做一次 forward pass、得到每個位置的 T 分佈
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        T_1 = T(· | x)
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        T_2 = T(· | x, d_1)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        ...
</span></span><span class="line"><span class="ln">10</span><span class="cl">        T_K = T(· | x, d_1..K-1)
</span></span><span class="line"><span class="ln">11</span><span class="cl">        T_{K+1} = T(· | x, d_1..K)   ← bonus token 位置
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">Step 3：從前往後處理：
</span></span><span class="line"><span class="ln">14</span><span class="cl">        for i = 1 to K:
</span></span><span class="line"><span class="ln">15</span><span class="cl">          r = uniform random in [0, 1]
</span></span><span class="line"><span class="ln">16</span><span class="cl">          if r &lt; min(1, T_i(d_i) / D(d_i)):
</span></span><span class="line"><span class="ln">17</span><span class="cl">            accept d_i           ← d_i 在 T 下機率 ≥ D 下機率、接受
</span></span><span class="line"><span class="ln">18</span><span class="cl">          else:
</span></span><span class="line"><span class="ln">19</span><span class="cl">            reject、sample 替代 token from (T_i - D)+ normalized
</span></span><span class="line"><span class="ln">20</span><span class="cl">            break
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">Step 4：若全 K 個接受、再 sample 一個 bonus token from T_{K+1}</span></span></code></pre></div><p>關鍵性質（數學上可證明）：</p>
<ol>
<li><strong>最終輸出分佈 ≡ 純 target 自回歸</strong>：不管 drafter 多爛、speculative decoding 的輸出在統計上跟「就用 T 從頭生」完全相同 — 不是「近似」、是「等價」</li>
<li><strong>Drafter 越接近 target、acceptance rate 越高</strong>：但即使 drafter 完全亂猜、輸出仍正確、只是沒加速</li>
<li><strong>每 step 至少生 1 個 token</strong>：最差情況第一個就拒絕、用 T 取代、退化成單純 T 自回歸</li>
</ol>
<h2 id="加速倍率--k--acceptance-rate-的限制">加速倍率 = K × acceptance rate 的限制</h2>
<p>理論加速分析：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Step 平均生 token 數 = E[接受長度] + 1（bonus 若有）
</span></span><span class="line"><span class="ln">2</span><span class="cl">                    ≈ K × acceptance_rate （簡化估算）
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">每 step 主要成本：
</span></span><span class="line"><span class="ln">5</span><span class="cl">  Drafter K 次小 forward + Target 1 次大 forward
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ≈ K × T_drafter + T_target
</span></span><span class="line"><span class="ln">7</span><span class="cl">  ≈ T_target × (1 + K × C)   where C = T_drafter / T_target
</span></span><span class="line"><span class="ln">8</span><span class="cl">
</span></span><span class="line"><span class="ln">9</span><span class="cl">加速倍率 ≈ K × acceptance_rate / (1 + K × C)</span></span></code></pre></div><p>實際例子（Gemma 4 31B target + Gemma 4 E4B drafter、K=5）：</p>
<ul>
<li>T_drafter / T_target ≈ 4B / 31B ≈ 0.13</li>
<li>K = 5、acceptance rate ≈ 0.7（同 family、estimate）</li>
<li>加速倍率 ≈ 5 × 0.7 / (1 + 5 × 0.13) ≈ 3.5 / 1.65 ≈ <strong>2.1×</strong></li>
</ul>
<p>對照 LM Studio / llama.cpp 實測常見的「2-3×」加速、推導合理。</p>
<p>什麼破壞加速：</p>
<ol>
<li><strong>Drafter 太大</strong>：C 接近 1、(1 + K × C) 爆增、淨收益消失</li>
<li><strong>Acceptance rate 太低</strong>：K × acceptance 達不到 1 + K × C、淨收益負</li>
<li><strong>K 設太大</strong>：drafter 後面 token acceptance rate 急降、且每步成本 K × T_drafter 線性增加</li>
</ol>
<h2 id="三條主流變體">三條主流變體</h2>
<h3 id="drafter-based經典-speculative-decoding">Drafter-based（經典 speculative decoding）</h3>
<p>Leviathan et al. 2022 / Chen et al. 2023 提出：</p>
<ul>
<li><strong>方式</strong>：獨立訓練一個小 drafter model、跟 target 同 family / 同 tokenizer</li>
<li><strong>代表</strong>：Gemma 4 31B + E4B、Llama 3.1 405B + 8B、Qwen3 30B + 1.5B</li>
<li><strong>優點</strong>：相對成熟、各推論伺服器（llama.cpp、vLLM）廣泛支援</li>
<li><strong>缺點</strong>：要訓 / 維護兩個 model；drafter 跟 target 必須完全相容</li>
</ul>
<h3 id="mtpmulti-token-prediction">MTP（Multi-Token Prediction）</h3>
<p>DeepSeek-V3 / Gemma 4 等內建：</p>
<ul>
<li><strong>方式</strong>：訓練 target 時、output 端額外加 K 個 head、每個 head 學「預測 N+1, N+2, &hellip;, N+K」</li>
<li><strong>代表</strong>：DeepSeek-V3（MTP=4）、Gemma 4 coding 變體</li>
<li><strong>優點</strong>：不需獨立 drafter、head 跟 target 完全同分佈、acceptance rate 高（通常 0.7-0.85）</li>
<li><strong>缺點</strong>：需要 target model 訓練時就支援、現存模型不能後加</li>
</ul>
<h3 id="eagleextrapolation-algorithm-for-greater-llm-efficiency">EAGLE（Extrapolation Algorithm for Greater LLM Efficiency）</h3>
<p>Li et al. 2024 / EAGLE-2 / EAGLE-3：</p>
<ul>
<li><strong>方式</strong>：drafter 用 target 內部的 hidden state（不是 token embedding）當輸入、預測下一個位置的 token 機率、逼近 target 的分佈。因為 drafter 看的是 target 已經處理過的 feature、acceptance rate 比純 token-based drafter 高</li>
<li><strong>代表</strong>：EAGLE-2、EAGLE-3 應用在 Llama 系列</li>
<li><strong>優點</strong>：acceptance rate 通常更高（0.8+）、且 drafter 可以很小</li>
<li><strong>缺點</strong>：實作較複雜、需要 access target 的 hidden state、推論伺服器支援度較窄</li>
</ul>
<blockquote>
<p><strong>事實查核註</strong>：MTP / EAGLE 的具體 acceptance rate 跟加速倍率依模型、任務、量化、推論伺服器實作而異、引用前以各推論伺服器 release notes 跟自己 <code>llama-bench</code> 結果為準。</p></blockquote>
<h2 id="怎麼挑-drafter">怎麼挑 drafter</h2>
<p>實務判讀：</p>
<table>
  <thead>
      <tr>
          <th>條件</th>
          <th>選擇</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Target 有內建 MTP（如 Gemma 4 coding-mtp）</td>
          <td>直接用 MTP、不另找 drafter</td>
      </tr>
      <tr>
          <td>Target 沒 MTP、有同 family 小模型</td>
          <td>用 drafter-based、選小一個量級的同 family 模型</td>
      </tr>
      <tr>
          <td>Target 沒 MTP、無同 family 小模型</td>
          <td>多半不值得 speculative、用一般推論</td>
      </tr>
      <tr>
          <td>用 Apple Silicon Mac、target ≤ 30B</td>
          <td>MTP 是首選、見 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP 卡片</a></td>
      </tr>
      <tr>
          <td>用 PC 獨立 GPU、target 較大</td>
          <td>看 llama.cpp 支援度、EAGLE-2 / drafter-based 都可</td>
      </tr>
  </tbody>
</table>
<p>挑 drafter 的反例（不該配）：</p>
<ol>
<li><strong>跨 family</strong>：Llama 3 + Qwen3 — tokenizer 不一致、無法配對</li>
<li><strong>跨 generation</strong>：Llama 2 + Llama 3 — vocab 不同</li>
<li><strong>太大 drafter</strong>：target 8B + drafter 3B — drafter 成本接近 target、淨收益小</li>
<li><strong>量化不對稱</strong>：target Q4 + drafter Q8 — drafter 不必比 target 精度高、浪費記憶體</li>
</ol>
<h2 id="怎麼測自己的加速倍率">怎麼測自己的加速倍率</h2>
<p><code>llama-bench</code> 是 llama.cpp 官方 benchmark 工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 純 target 推論</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">llama-bench -m gemma-4-31b-Q4_K_M.gguf -p <span class="m">512</span> -n <span class="m">128</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 加 drafter（speculative decoding）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">llama-bench -m gemma-4-31b-Q4_K_M.gguf <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>            --draft-model gemma-4-e4b-Q4_K_M.gguf <span class="se">\
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="se"></span>            --n-predict <span class="m">128</span> --speculative-draft <span class="m">5</span></span></span></code></pre></div><p>看的指標：</p>
<ul>
<li><strong>tg128 (純 target)</strong>：純自回歸生 128 token 的 tokens/s</li>
<li><strong>tg128 (with draft)</strong>：speculative decoding 模式的 tokens/s</li>
<li><strong>加速倍率</strong>：後者 / 前者</li>
</ul>
<p>實際工作流的 acceptance rate 跟 benchmark 上可能不同（取決於任務）、benchmark 是上限估算。</p>
<h2 id="跟其他加速技巧的關係">跟其他加速技巧的關係</h2>
<table>
  <thead>
      <tr>
          <th>技巧</th>
          <th>攻擊的瓶頸</th>
          <th>跟 speculative decoding 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Quantization</a></td>
          <td>權重大小</td>
          <td>正交、可疊加（兩個都用）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/flash-attention/" data-link-title="Flash Attention" data-link-desc="Attention 計算的記憶體友善實作、減少 GPU memory 讀寫、提升長 context 推論吞吐">Flash Attention</a></td>
          <td>Attention 記憶體佔用</td>
          <td>正交、可疊加</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache 量化</a></td>
          <td>KV cache 大小</td>
          <td>正交、可疊加</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/batching/" data-link-title="Batching" data-link-desc="多 request 一起跑、攤平 model load 成本：production LLM inference 的核心優化、決定 throughput vs latency 取捨">Batching</a></td>
          <td>多請求共用權重讀取</td>
          <td>跟 speculative 邏輯衝突（共用 batch dim）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache</a></td>
          <td>Prompt 重複部分</td>
          <td>正交、可疊加</td>
      </tr>
  </tbody>
</table>
<p>關鍵注意：<strong>Speculative decoding + batching 同時開的支援度差</strong> — 推論伺服器多半要選一個。個人 dev 場景 batch size = 1、用 speculative 是合理選擇；高併發 production 場景多半選 batching。</p>
<h2 id="何時不適合用-speculative-decoding">何時不適合用 speculative decoding</h2>
<ol>
<li><strong>Batch size &gt; 1 場景</strong>：跟 batching 衝突、加速可能反向</li>
<li><strong>Reasoning model</strong>：reasoning trace 的 token 多樣化、drafter 很難猜對、acceptance rate 低（多數 reasoning model 不用 speculative）</li>
<li><strong>Drafter 不存在或不合</strong>：勉強配差 family 的 drafter 反而拖慢</li>
<li><strong>記憶體吃緊</strong>：drafter 也要載入、可能擠掉 KV cache budget、其他地方變慢</li>
</ol>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>「Memory bandwidth bound 留下算力閒置」的根本觀察</li>
<li>接受 / 拒絕 sampling 邏輯（數學上等價於純 target）</li>
<li>Acceptance rate × K 是加速倍率主要 driver</li>
<li>Drafter / target 必須 tokenizer 相容</li>
<li>跟 batching 衝突的 trade-off</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體變體（drafter-based / MTP / EAGLE → 未來可能新方法）</li>
<li>各推論伺服器的支援度（llama.cpp、vLLM、TGI 都在演化）</li>
<li>模型廠商是否內建 MTP（目前 Gemma 4、DeepSeek 等先行、未來普及）</li>
<li>Reasoning model 是否會有 reasoning-aware speculative 變體</li>
</ul>
<h2 id="下一步">下一步</h2>
<p>下一步：模組三的內容到此完整、進入 <a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 應用層原理</a> 看 LLM 作為系統元件的設計取捨。</p>
]]></content:encoded></item><item><title>3.10 Constrained decoding 內部：grammar mask 跟性能取捨</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/constrained-decoding-internals/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/constrained-decoding-internals/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">3.5 sampling-and-decoding&lt;/a> 寫了 greedy / beam / top-p / top-k sampling、是「在合法輸出中選下一個 token」的基本機制。&lt;a href="https://tarrragon.github.io/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 application-protocols&lt;/a> 寫了 function calling / structured output 的應用層 — 但「為什麼 LLM 能保證輸出合法 JSON」這層原理在前兩章都沒展開。本章補 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding&lt;/a> 的內部機制：token mask 怎麼算、JSON schema / regex / &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">CFG&lt;/a> 三種 grammar、為什麼 XGrammar 等實作反而加速生成。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋「grammar 強制」是在 sampling 階段哪一步做的。&lt;/li>
&lt;li>區分 JSON schema / regex / CFG 三種 grammar 的適用場景。&lt;/li>
&lt;li>看 XGrammar / outlines / llama.cpp grammar 等實作、能對應到本章 framing。&lt;/li>
&lt;li>判讀「constrained decoding 加速還是拖慢」的具體場景。&lt;/li>
&lt;/ol>
&lt;h2 id="sampling-階段的位置">Sampling 階段的位置&lt;/h2>
&lt;p>回顧 LLM 輸出流程（見 &lt;a href="https://tarrragon.github.io/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">3.5&lt;/a>）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[forward pass] → logits（vocab_size 維、每個 token 一個實數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ↓ apply temperature（logits / T）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ apply constrained decoding（本章聚焦） ← grammar mask
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ↓ softmax → probability distribution
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> ↓ top-p / top-k / sampling
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> ↓ next token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Constrained decoding 在 softmax &lt;strong>之前&lt;/strong>插入 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">grammar mask&lt;/a>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">For each position：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> 1. Grammar 算當前位置的「合法 token 集合」（vocab 子集）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> 2. 對不在合法集的 token、logit 設 -∞
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> 3. Softmax 後、不合法 token 機率為 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> 4. Sampling 只可能選到合法 token&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵理解：grammar 不改變模型本身、不改變 logits 數值（除了 mask 部分）、只是&lt;strong>限制 sampling 空間&lt;/strong>。&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">3.5 sampling-and-decoding</a> 寫了 greedy / beam / top-p / top-k sampling、是「在合法輸出中選下一個 token」的基本機制。<a href="/blog/llm/04-applications/application-protocols/" data-link-title="4.6 應用層協議：function calling / structured output / MCP" data-link-desc="三個常被混為一談的概念：模型能力、sampling 約束、server 協議，三者的層級差異與組合方式">4.6 application-protocols</a> 寫了 function calling / structured output 的應用層 — 但「為什麼 LLM 能保證輸出合法 JSON」這層原理在前兩章都沒展開。本章補 <a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">constrained decoding</a> 的內部機制：token mask 怎麼算、JSON schema / regex / <a href="/blog/llm/knowledge-cards/grammar/" data-link-title="Grammar" data-link-desc="描述合法字串形狀的形式規則，在 structured output 中用來限制 LLM 每一步可輸出的 token">CFG</a> 三種 grammar、為什麼 XGrammar 等實作反而加速生成。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋「grammar 強制」是在 sampling 階段哪一步做的。</li>
<li>區分 JSON schema / regex / CFG 三種 grammar 的適用場景。</li>
<li>看 XGrammar / outlines / llama.cpp grammar 等實作、能對應到本章 framing。</li>
<li>判讀「constrained decoding 加速還是拖慢」的具體場景。</li>
</ol>
<h2 id="sampling-階段的位置">Sampling 階段的位置</h2>
<p>回顧 LLM 輸出流程（見 <a href="/blog/llm/03-theoretical-foundations/sampling-and-decoding/" data-link-title="3.5 Sampling 與 Decoding 策略" data-link-desc="Greedy、beam search、top-k、top-p、temperature、min-p：模型輸出後怎麼挑下一個 token">3.5</a>）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[forward pass] → logits（vocab_size 維、每個 token 一個實數）
</span></span><span class="line"><span class="ln">2</span><span class="cl">       ↓ apply temperature（logits / T）
</span></span><span class="line"><span class="ln">3</span><span class="cl">       ↓ apply constrained decoding（本章聚焦）  ← grammar mask
</span></span><span class="line"><span class="ln">4</span><span class="cl">       ↓ softmax → probability distribution
</span></span><span class="line"><span class="ln">5</span><span class="cl">       ↓ top-p / top-k / sampling
</span></span><span class="line"><span class="ln">6</span><span class="cl">       ↓ next token</span></span></code></pre></div><p>Constrained decoding 在 softmax <strong>之前</strong>插入 <a href="/blog/llm/knowledge-cards/constrained-decoding/" data-link-title="Constrained Decoding" data-link-desc="推論時用 grammar 強制 LLM 輸出符合特定格式（JSON / regex / CFG）的 sampling 機制、把不合法 token 的機率歸零">grammar mask</a>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">For each position：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  1. Grammar 算當前位置的「合法 token 集合」（vocab 子集）
</span></span><span class="line"><span class="ln">3</span><span class="cl">  2. 對不在合法集的 token、logit 設 -∞
</span></span><span class="line"><span class="ln">4</span><span class="cl">  3. Softmax 後、不合法 token 機率為 0
</span></span><span class="line"><span class="ln">5</span><span class="cl">  4. Sampling 只可能選到合法 token</span></span></code></pre></div><p>關鍵理解：grammar 不改變模型本身、不改變 logits 數值（除了 mask 部分）、只是<strong>限制 sampling 空間</strong>。</p>
<h2 id="三種主流-grammar">三種主流 grammar</h2>
<h3 id="json-schema">JSON Schema</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln">1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="p">{</span><span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="nt">&#34;age&#34;</span><span class="p">:</span> <span class="p">{</span><span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;integer&#34;</span><span class="p">,</span> <span class="nt">&#34;minimum&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">  <span class="nt">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;name&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>LLM 輸出必須是合法 JSON 且符合 schema。實作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">當前已生：&#39;{&#34;name&#34;: &#34;alice&#34;, &#39;
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓ 算下一個合法 token：
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - 必須繼續產合法 JSON
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - schema 還沒填 age（optional）但 name 已填、所以 } 合法、&#34;age&#34; 也合法
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - 不合法：&#39;{&#39; / &#39;]&#39; / 任意其他 key
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ↓ Token mask 套用
</span></span><span class="line"><span class="ln">7</span><span class="cl">  → 模型只能選 } 或 &#34;age&#34;</span></span></code></pre></div><h3 id="regex">Regex</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">\d{3}-\d{4}-\d{4}  # 台灣 phone number 格式</span></span></code></pre></div><p>LLM 輸出必須符合 regex。實作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">當前已生：&#39;09&#39;
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓ 算下一個合法 token：
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - regex 期望 \d 接下來
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - 合法 token：&#39;0&#39;-&#39;9&#39; 開頭的 token
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - 不合法：字母、符號
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ↓ Token mask</span></span></code></pre></div><h3 id="cfgcontext-free-grammar">CFG（Context-Free Grammar）</h3>
<p>用 <a href="/blog/llm/knowledge-cards/bnf/" data-link-title="BNF（Backus-Naur Form）" data-link-desc="用遞迴產生式描述語法的經典記法，是 CFG、parser 與 grammar-constrained sampling 常見的基礎表示">BNF</a> / EBNF 描述合法語法：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">expr   ::= term (&#34;+&#34; term)*
</span></span><span class="line"><span class="ln">2</span><span class="cl">term   ::= number | &#34;(&#34; expr &#34;)&#34;
</span></span><span class="line"><span class="ln">3</span><span class="cl">number ::= [0-9]+</span></span></code></pre></div><p>LLM 輸出必須符合此 grammar。實作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">當前已生：&#39;(1+2&#39;
</span></span><span class="line"><span class="ln">2</span><span class="cl">  ↓ CFG 算當下合法 next token：
</span></span><span class="line"><span class="ln">3</span><span class="cl">  - 已 match 部分 term + &#34;+&#34; + term
</span></span><span class="line"><span class="ln">4</span><span class="cl">  - 合法：&#34;)&#34; 或 &#34;+&#34; 開始新 term
</span></span><span class="line"><span class="ln">5</span><span class="cl">  - 不合法：字母、其他符號
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ↓ Token mask</span></span></code></pre></div><p>CFG 是最強表達力、但實作最複雜。SQL / 程式碼 generation 多用 CFG-based grammar。</p>
<h2 id="xgrammar-的-pre-compile-機制">XGrammar 的 pre-compile 機制</h2>
<p>XGrammar（Dong et al., 2024）是 2024-2025 主流的高效實作。核心優化：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Naive 實作（如 outlines 早期版）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  每次 sampling 都重算 grammar state
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  每個 token 都跑一次 grammar parse
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  → 開銷大、可能拖慢 generation
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">XGrammar 優化：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  1. Pre-compile grammar → 確定性 DFA / push-down automaton
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  2. Cache 每個 grammar state 的「合法 token mask bitmap」
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  3. Sampling 時 O(1) 查表得到 mask
</span></span><span class="line"><span class="ln">10</span><span class="cl">  4. Mask 用 bitwise op 套用到 logits</span></span></code></pre></div><p>效果：grammar 套用 overhead 趨近 0、甚至<strong>因為跳過 boilerplate token 反而加速</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">無 grammar 生 JSON：
</span></span><span class="line"><span class="ln">2</span><span class="cl">  {     &#34; n a m e &#34;     : &#34; a l i c e &#34; ...
</span></span><span class="line"><span class="ln">3</span><span class="cl">  ←     每個 token 都跑 forward pass    →
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">有 grammar 生 JSON：
</span></span><span class="line"><span class="ln">6</span><span class="cl">  跳過固定 token（{ &#34; : 等）、直接生關鍵字串
</span></span><span class="line"><span class="ln">7</span><span class="cl">  forward pass 次數減少
</span></span><span class="line"><span class="ln">8</span><span class="cl">  → 實測加速 1.5-3×</span></span></code></pre></div><p>主流推論伺服器（vLLM、SGLang、TensorRT-LLM）2025 後預設用 XGrammar。</p>
<h2 id="性能取捨加速還是拖慢">性能取捨：加速還是拖慢</h2>
<p>常見誤解：「constrained decoding 拖慢生成」。實際看實作：</p>
<table>
  <thead>
      <tr>
          <th>實作</th>
          <th>性能</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>XGrammar（vLLM 等預設）</td>
          <td><strong>加速 1.5-3×</strong>（跳過固定 token、forward pass 次數減）</td>
      </tr>
      <tr>
          <td>outlines（pre-compiled）</td>
          <td>略加速到中性</td>
      </tr>
      <tr>
          <td>outlines（lazy compile）</td>
          <td>略拖慢</td>
      </tr>
      <tr>
          <td>guidance（高階 API）</td>
          <td>中性到略拖慢</td>
      </tr>
      <tr>
          <td>llama.cpp grammar</td>
          <td>中性</td>
      </tr>
      <tr>
          <td>Lazy / naive 實作</td>
          <td>拖慢</td>
      </tr>
  </tbody>
</table>
<p>判讀：用主流推論伺服器（vLLM / SGLang）+ XGrammar 路線、constrained decoding 通常加速；自己寫 naive 實作可能拖慢。</p>
<h2 id="跟-function-calling-的關係">跟 <a href="/blog/llm/knowledge-cards/function-calling/" data-link-title="Function Calling" data-link-desc="模型訓練階段建立的「呼叫工具」能力：知道何時該呼叫、傳什麼參數">function calling</a> 的關係</h2>
<p>兩個概念可獨立、也可疊用：</p>
<table>
  <thead>
      <tr>
          <th>路線</th>
          <th>機制</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pure function calling（無 constrained decoding）</td>
          <td>靠模型訓練、不強制合法、可能有解析失敗</td>
      </tr>
      <tr>
          <td>Pure constrained decoding（無 function calling 訓練）</td>
          <td>推論時強制合法、但模型不一定知道「何時該呼叫工具」</td>
      </tr>
      <tr>
          <td>Function calling + constrained decoding</td>
          <td>訓練教模型何時呼叫、grammar 強制呼叫格式合法</td>
      </tr>
  </tbody>
</table>
<p>主流商業 API（Anthropic / OpenAI / Gemini）的 function calling 通常<strong>內部已用 constrained decoding</strong>、開發者無感。本地推論用 vLLM / SGLang + XGrammar 也是預設組合。</p>
<h2 id="失敗模式">失敗模式</h2>
<h3 id="1-grammar-太嚴讓模型該說的話說不出來">1. Grammar 太嚴讓模型「該說的話說不出來」</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Schema 強制 type 是 enum [&#34;A&#34;, &#34;B&#34;, &#34;C&#34;]
</span></span><span class="line"><span class="ln">2</span><span class="cl">但真實答案是「none of the above」
</span></span><span class="line"><span class="ln">3</span><span class="cl">→ 模型強制選 A/B/C、輸出語義錯誤</span></span></code></pre></div><p><strong>緩解</strong>：enum 加 fallback option（&ldquo;unknown&rdquo; / &ldquo;none&rdquo;）、schema 別過度約束</p>
<h3 id="2-cfg-太複雜編譯失敗--慢">2. CFG 太複雜、編譯失敗 / 慢</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">復雜 CFG（如完整 SQL grammar）pre-compile 數秒
</span></span><span class="line"><span class="ln">2</span><span class="cl">production cold start 多花這數秒</span></span></code></pre></div><p><strong>緩解</strong>：cache compiled grammar、用較簡單 grammar 版本（如「INSERT only」而非完整 SQL）</p>
<h3 id="3-grammar-跟-model-訓練分佈不符">3. Grammar 跟 model 訓練分佈不符</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Schema 要求很罕見的 JSON 結構
</span></span><span class="line"><span class="ln">2</span><span class="cl">模型訓練沒見過這結構
</span></span><span class="line"><span class="ln">3</span><span class="cl">即使 grammar 強制合法、語義可能空洞</span></span></code></pre></div><p><strong>緩解</strong>：grammar 用模型訓練過的形態（function call spec、common JSON）、自定義 schema 加 few-shot example</p>
<h3 id="4-streaming-跟-grammar-衝突">4. Streaming 跟 grammar 衝突</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Streaming 邊生邊輸出
</span></span><span class="line"><span class="ln">2</span><span class="cl">Grammar 中段 token 可能要 backtrack 修正
</span></span><span class="line"><span class="ln">3</span><span class="cl">streaming UX 跳字</span></span></code></pre></div><p><strong>緩解</strong>：用 incremental-parsing grammar（XGrammar 支援）、避免 backtrack 場景</p>
<h3 id="5-constrained-decoding-蓋過-function-calling-訓練">5. Constrained decoding 蓋過 function calling 訓練</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">模型訓練用 OpenAI function spec、應用強制套 Anthropic tools 的 grammar
</span></span><span class="line"><span class="ln">2</span><span class="cl">模型輸出「合法但語意空洞」（schema 對、欄位胡亂填）</span></span></code></pre></div><p><strong>緩解</strong>：grammar spec 跟模型訓練 spec 一致、別人工維護兩份不同 schema</p>
<h2 id="何時不該用-constrained-decoding">何時不該用 constrained decoding</h2>
<ol>
<li><strong>自由 / 創意輸出</strong>：寫作、brainstorming、grammar 限制模型表達</li>
<li><strong>可靠的 model + simple format</strong>：模型本身能穩定輸出 JSON、grammar overhead 不必要</li>
<li><strong>Grammar 太嚴有語義錯</strong>：見失敗模式 1</li>
<li><strong>Streaming + 複雜 grammar</strong>：streaming UX 受影響</li>
</ol>
<h2 id="主流實作詳細">主流實作詳細</h2>
<table>
  <thead>
      <tr>
          <th>實作</th>
          <th>適合場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>XGrammar</strong></td>
          <td>Production 高吞吐（vLLM / SGLang / TensorRT-LLM 預設）</td>
      </tr>
      <tr>
          <td><strong>outlines</strong></td>
          <td>Python script、開發 / 實驗、HF Transformers 用</td>
      </tr>
      <tr>
          <td><strong>lm-format-enforcer</strong></td>
          <td>動態 grammar、運行時切 schema</td>
      </tr>
      <tr>
          <td><strong>guidance</strong></td>
          <td>Microsoft 系、想要 high-level API</td>
      </tr>
      <tr>
          <td><strong>llama.cpp grammar</strong></td>
          <td>本地 GGUF 模型、GBNF 語法</td>
      </tr>
      <tr>
          <td><strong>OpenAI Structured Outputs</strong></td>
          <td>OpenAI API、JSON schema、開發者無感</td>
      </tr>
      <tr>
          <td><strong>Anthropic JSON mode</strong></td>
          <td>Anthropic API、簡化版</td>
      </tr>
  </tbody>
</table>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>Constrained decoding 在 sampling 哪一步插入（softmax 之前）的 framing</li>
<li>三種 grammar 類型（JSON schema / regex / CFG）的分類</li>
<li>Token mask 機制（不合法 token logit 設 -∞）</li>
<li>「正確實作下加速、不是拖慢」的反直覺結論</li>
<li>5 大失敗模式分類</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>XGrammar / outlines 等實作的具體效能跟功能</li>
<li>主流推論伺服器的預設 grammar engine</li>
<li>JSON schema spec 標準化（新版會出）</li>
<li>Function calling + constrained decoding 是否會被 native multimodal 取代</li>
</ul>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/going-deeper-theory/" data-link-title="3.11 想學更深：推薦公開課程" data-link-desc="Karpathy、Stanford CS224N / CS25 / CS336、DeepLearning.AI、Hugging Face：LLM 理論深入學習的完整路線">3.11 想學更深</a>、整個模組三理論基礎走完。</p>
]]></content:encoded></item><item><title>3.11 想學更深：推薦公開課程</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/going-deeper-theory/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/going-deeper-theory/</guid><description>&lt;p>本模組前十章把 LLM 理論基礎走過一遍：神經網路、embedding、attention、Transformer 架構、訓練流程、sampling、tokenization、cross-language、reasoning models、speculative decoding 內部。深入學習需要更系統的課程、實作練習、跟 paper 閱讀。本章整理「LLM 理論深入」這條學習路線上的高品質資源、標出每門課的定位與適合的讀者。&lt;/p>
&lt;p>本章跟&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">模組二 2.4 數學基礎公開課&lt;/a> 互補：那邊是數學工具、這邊是 LLM 理論機制。兩者組合涵蓋從零基礎到能跟業界研究接軌的完整路線。&lt;/p>
&lt;h2 id="路線總覽">路線總覽&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>內容&lt;/th>
 &lt;th>適合背景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>1&lt;/td>
 &lt;td>視覺化 + 直觀理解&lt;/td>
 &lt;td>任何工程背景&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>2&lt;/td>
 &lt;td>動手實作 LLM&lt;/td>
 &lt;td>想直接看完整系統&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>3&lt;/td>
 &lt;td>NLP + Transformer 系統課&lt;/td>
 &lt;td>想紮實打底&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>4&lt;/td>
 &lt;td>LLM 完整 lifecycle&lt;/td>
 &lt;td>想做 LLM 應用 / 訓練&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>5&lt;/td>
 &lt;td>最新研究進展&lt;/td>
 &lt;td>想跟業界 / 學界進度&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="階段-13blue1brown-llm-視覺化系列">階段 1：3Blue1Brown LLM 視覺化系列&lt;/h2>
&lt;p>Grant Sanderson 的「Neural Networks」+「But what is a GPT?」系列、視覺化動畫解釋 Transformer 內部運作。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>影片&lt;/th>
 &lt;th>涵蓋&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>What is a neural network? (Chapter 1)&lt;/td>
 &lt;td>Neural network 基礎、forward / backward 直覺&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gradient descent (Chapter 2)&lt;/td>
 &lt;td>梯度下降直觀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>What is backpropagation? (Chapter 3-4)&lt;/td>
 &lt;td>Backprop 完整推導&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>But what is a GPT? (Chapter 5)&lt;/td>
 &lt;td>Transformer / GPT 高層次運作&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Attention in Transformers (Chapter 6)&lt;/td>
 &lt;td>Attention 機制的視覺化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>How LLMs might store facts (Chapter 7)&lt;/td>
 &lt;td>FFN 在 Transformer 中的角色、模型怎麼「記住」事實&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>為什麼從這裡開始&lt;/strong>：影片把抽象的 attention、embedding、residual stream 變成可視覺化的幾何運動。看完這個系列、本模組前 4 章的概念都能 grasp 到直觀層次。&lt;/p>
&lt;p>&lt;strong>前置條件&lt;/strong>：高中代數 + 對矩陣有基本概念。已有 ML / Neural Network 基礎的讀者可跳過 Essence of Linear Algebra、直接看 Neural Networks 5 集系列。&lt;/p>
&lt;p>連結：YouTube 上搜尋 &lt;code>3Blue1Brown Neural Networks&lt;/code>、官方頻道是 youtube.com/c/3blue1brown。每集 15 ~ 30 分鐘、總共約 4 小時。&lt;/p>
&lt;h2 id="階段-2andrej-karpathy-的-neural-networks-zero-to-hero">階段 2：Andrej Karpathy 的 Neural Networks: Zero to Hero&lt;/h2>
&lt;p>Andrej Karpathy（OpenAI 前研究員、Tesla 前 AI 主管）的 YouTube 系列、在「動手實作 LLM」場景下是最完整的公開教材之一。完整實作從 micrograd（自己刻 autograd）到 GPT-2 訓練。&lt;/p>
&lt;p>&lt;strong>前置條件&lt;/strong>：Python 基礎、PyTorch 基本語法、看懂模組二的 chain rule 與 backprop 概念（&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">2.2 calculus&lt;/a>）。沒寫過 PyTorch 的讀者建議先做完 PyTorch 60 分鐘 tutorial 再進。&lt;/p></description><content:encoded><![CDATA[<p>本模組前十章把 LLM 理論基礎走過一遍：神經網路、embedding、attention、Transformer 架構、訓練流程、sampling、tokenization、cross-language、reasoning models、speculative decoding 內部。深入學習需要更系統的課程、實作練習、跟 paper 閱讀。本章整理「LLM 理論深入」這條學習路線上的高品質資源、標出每門課的定位與適合的讀者。</p>
<p>本章跟<a href="/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">模組二 2.4 數學基礎公開課</a> 互補：那邊是數學工具、這邊是 LLM 理論機制。兩者組合涵蓋從零基礎到能跟業界研究接軌的完整路線。</p>
<h2 id="路線總覽">路線總覽</h2>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>內容</th>
          <th>適合背景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>視覺化 + 直觀理解</td>
          <td>任何工程背景</td>
      </tr>
      <tr>
          <td>2</td>
          <td>動手實作 LLM</td>
          <td>想直接看完整系統</td>
      </tr>
      <tr>
          <td>3</td>
          <td>NLP + Transformer 系統課</td>
          <td>想紮實打底</td>
      </tr>
      <tr>
          <td>4</td>
          <td>LLM 完整 lifecycle</td>
          <td>想做 LLM 應用 / 訓練</td>
      </tr>
      <tr>
          <td>5</td>
          <td>最新研究進展</td>
          <td>想跟業界 / 學界進度</td>
      </tr>
  </tbody>
</table>
<h2 id="階段-13blue1brown-llm-視覺化系列">階段 1：3Blue1Brown LLM 視覺化系列</h2>
<p>Grant Sanderson 的「Neural Networks」+「But what is a GPT?」系列、視覺化動畫解釋 Transformer 內部運作。</p>
<table>
  <thead>
      <tr>
          <th>影片</th>
          <th>涵蓋</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>What is a neural network? (Chapter 1)</td>
          <td>Neural network 基礎、forward / backward 直覺</td>
      </tr>
      <tr>
          <td>Gradient descent (Chapter 2)</td>
          <td>梯度下降直觀</td>
      </tr>
      <tr>
          <td>What is backpropagation? (Chapter 3-4)</td>
          <td>Backprop 完整推導</td>
      </tr>
      <tr>
          <td>But what is a GPT? (Chapter 5)</td>
          <td>Transformer / GPT 高層次運作</td>
      </tr>
      <tr>
          <td>Attention in Transformers (Chapter 6)</td>
          <td>Attention 機制的視覺化</td>
      </tr>
      <tr>
          <td>How LLMs might store facts (Chapter 7)</td>
          <td>FFN 在 Transformer 中的角色、模型怎麼「記住」事實</td>
      </tr>
  </tbody>
</table>
<p><strong>為什麼從這裡開始</strong>：影片把抽象的 attention、embedding、residual stream 變成可視覺化的幾何運動。看完這個系列、本模組前 4 章的概念都能 grasp 到直觀層次。</p>
<p><strong>前置條件</strong>：高中代數 + 對矩陣有基本概念。已有 ML / Neural Network 基礎的讀者可跳過 Essence of Linear Algebra、直接看 Neural Networks 5 集系列。</p>
<p>連結：YouTube 上搜尋 <code>3Blue1Brown Neural Networks</code>、官方頻道是 youtube.com/c/3blue1brown。每集 15 ~ 30 分鐘、總共約 4 小時。</p>
<h2 id="階段-2andrej-karpathy-的-neural-networks-zero-to-hero">階段 2：Andrej Karpathy 的 Neural Networks: Zero to Hero</h2>
<p>Andrej Karpathy（OpenAI 前研究員、Tesla 前 AI 主管）的 YouTube 系列、在「動手實作 LLM」場景下是最完整的公開教材之一。完整實作從 micrograd（自己刻 autograd）到 GPT-2 訓練。</p>
<p><strong>前置條件</strong>：Python 基礎、PyTorch 基本語法、看懂模組二的 chain rule 與 backprop 概念（<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">2.2 calculus</a>）。沒寫過 PyTorch 的讀者建議先做完 PyTorch 60 分鐘 tutorial 再進。</p>
<h3 id="核心集數">核心集數</h3>
<table>
  <thead>
      <tr>
          <th>集數</th>
          <th>時長</th>
          <th>涵蓋</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>The spelled-out intro to neural networks and backpropagation</td>
          <td>2.5 hr</td>
          <td>從零實作 autograd、理解 backprop</td>
      </tr>
      <tr>
          <td>The spelled-out intro to language modeling</td>
          <td>2.5 hr</td>
          <td>Bigram model、character-level 預測</td>
      </tr>
      <tr>
          <td>Building makemore: MLP</td>
          <td>1.5 hr</td>
          <td>簡單 MLP 做 character 預測</td>
      </tr>
      <tr>
          <td>Building makemore: Activations &amp; BatchNorm</td>
          <td>1 hr</td>
          <td>訓練深度網路的細節</td>
      </tr>
      <tr>
          <td>Building makemore: Backprop from scratch</td>
          <td>2 hr</td>
          <td>手刻 backprop 跑通</td>
      </tr>
      <tr>
          <td>Building makemore: WaveNet</td>
          <td>1 hr</td>
          <td>Hierarchical 結構</td>
      </tr>
      <tr>
          <td>Let&rsquo;s build GPT from scratch</td>
          <td>2 hr</td>
          <td><strong>從零實作 GPT、Transformer 完整 forward + backward</strong></td>
      </tr>
      <tr>
          <td>Let&rsquo;s build the GPT Tokenizer</td>
          <td>2 hr</td>
          <td>BPE tokenizer 詳細實作</td>
      </tr>
      <tr>
          <td>Let&rsquo;s reproduce GPT-2 (124M)</td>
          <td>4 hr</td>
          <td>完整訓練 pipeline、跑出 GPT-2 級別模型</td>
      </tr>
      <tr>
          <td>Let&rsquo;s build LLaMA from scratch</td>
          <td>進行中</td>
          <td>Llama 架構、RoPE、SwiGLU 等</td>
      </tr>
  </tbody>
</table>
<h3 id="為什麼這系列重要">為什麼這系列重要</h3>
<ul>
<li><strong>講者深度高</strong>：Karpathy 講解的節奏細到可以跟著手刻、實作完能對 Transformer 每個 module 的角色有具體理解。</li>
<li><strong>完整可執行 code</strong>：每個影片都有 GitHub repo、可跟著跑。</li>
<li><strong>從零實作</strong>：不依賴黑箱 framework、所有東西都自己刻、理解深度。</li>
<li><strong>涵蓋完整</strong>：autograd → MLP → CNN → Transformer → 完整 GPT-2 訓練。</li>
</ul>
<p>完成這系列、你能：</p>
<ul>
<li>對應到模組三 <a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2 attention</a> 跟 <a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer-architecture</a> 的每個 module、解釋它在 code 中的角色。</li>
<li>用 PyTorch 從零實作一個簡單 LLM。</li>
<li>看懂主流 LLM 的 architecture code（Llama、Mistral 等）。</li>
</ul>
<p>連結：YouTube 搜尋 <code>Karpathy Neural Networks Zero to Hero</code>、官方索引在 karpathy.ai。</p>
<p>預估時間：完整跑完 30 ~ 50 小時（含跟著寫 code）、4 ~ 8 週投入。</p>
<h2 id="階段-3stanford-cs224n-natural-language-processing-with-deep-learning">階段 3：Stanford CS224N Natural Language Processing with Deep Learning</h2>
<p>Stanford 的 NLP + Deep Learning 旗艦課、由 Chris Manning、Tatsu Hashimoto 等講授。每年更新材料、在「LLM 系統教學」場景下是最完整的學術課程之一。</p>
<p><strong>前置條件</strong>：微積分（chain rule、partial derivative）、線性代數（matrix multiplication、eigenvalue）、Python + PyTorch。沒有這些基礎建議先補完模組二再進。</p>
<h3 id="內容">內容</h3>
<ul>
<li>Word vectors（word2vec、GloVe）</li>
<li>RNN、LSTM、GRU</li>
<li>Attention、Transformer</li>
<li>BERT、GPT、T5</li>
<li>預訓練、fine-tuning、RLHF</li>
<li>Multimodal、tool use、agent</li>
<li>最新 LLM 進展</li>
</ul>
<h3 id="為什麼選這門">為什麼選這門</h3>
<ul>
<li><strong>教材深度</strong>：每堂課有 slides + 推薦 paper、可深入研究。</li>
<li><strong>作業扎實</strong>：5 個 programming assignment、從 word2vec 到實作 Transformer。</li>
<li><strong>每年更新</strong>：跟最新研究進展對齊。</li>
</ul>
<p>連結：Stanford CS224N 課程網站。YouTube 上有歷年錄影。</p>
<p>預估時間：跟著影片 + 作業約 80 ~ 120 小時、10 週投入。</p>
<h2 id="階段-4stanford-cs336-language-modeling-from-scratch">階段 4：Stanford CS336 Language Modeling from Scratch</h2>
<p>2024 年 Stanford 新開的 LLM 從零訓練課、後續每年更新。Percy Liang、Tatsu Hashimoto 講授、涵蓋從資料到部署的完整 LLM lifecycle。引用時請註明你看的是哪一年的版本（內容逐年更新、跨年版本可能有差異）。</p>
<p><strong>前置條件</strong>：完成 CS224N 或同等課程、有 distributed training 概念、了解 GPU memory hierarchy。屬於進階課、不適合作為 LLM 入門起點。</p>
<h3 id="內容-1">內容</h3>
<ul>
<li>訓練資料：收集、過濾、deduplication</li>
<li>Tokenizer 訓練</li>
<li>模型架構選擇</li>
<li>大規模分散式訓練</li>
<li>評估方法</li>
<li>Alignment（SFT、DPO、RLHF）</li>
<li>Inference 優化</li>
<li>部署、安全</li>
</ul>
<h3 id="為什麼這門特別">為什麼這門特別</h3>
<ul>
<li><strong>完整 lifecycle</strong>：少數涵蓋「資料 → 訓練 → 評估 → 部署」全鏈的課。</li>
<li><strong>業界視角</strong>：講者跟前沿實驗室（Anthropic、Stanford CRFM 等）合作密切。</li>
<li><strong>最新內容</strong>：2024 開課、覆蓋最新 LLM 技術。</li>
</ul>
<p>連結：Stanford CS336 課程網站。YouTube 上有錄影。</p>
<p>預估時間：80 ~ 100 小時、10 週投入。</p>
<h2 id="階段-5stanford-cs25-transformers-united">階段 5：Stanford CS25 Transformers United</h2>
<p>Stanford 的 Transformer 專題課、每集邀請業界 / 學界專家、涵蓋 Transformer 在不同領域的應用。每年更新、講者更迭。</p>
<h3 id="涵蓋領域">涵蓋領域</h3>
<ul>
<li>Transformer 各種變體（Vision Transformer、Audio Transformer 等）</li>
<li>Diffusion + Transformer</li>
<li>Long context 技術</li>
<li>Mixture of Experts</li>
<li>多模態 LLM</li>
<li>Agent / Tool use</li>
<li>最新研究進展</li>
</ul>
<h3 id="為什麼有價值">為什麼有價值</h3>
<ul>
<li><strong>業界視角</strong>：講者多是 OpenAI、Anthropic、Google DeepMind、Meta 等實驗室的核心研究員。</li>
<li><strong>跟前沿同步</strong>：每年內容隨主題更新。</li>
<li><strong>適合「想知道現在發生什麼」</strong>：補課堂教學跟不上的最新進展。</li>
</ul>
<p>連結：YouTube 搜尋 <code>Stanford CS25 Transformers United</code>。</p>
<p>預估時間：每集 1 小時、可挑感興趣的看、不一定看完整系列。</p>
<h2 id="階段-6mit-6s191-introduction-to-deep-learning">階段 6：MIT 6.S191 Introduction to Deep Learning</h2>
<p>MIT 入門 DL 課、每年寒假開課並錄影上傳。涵蓋 RNN、CNN、Transformer、Diffusion、LLM 等廣度。</p>
<ul>
<li><strong>深度</strong>：較 Stanford CS224N 淺、適合入門。</li>
<li><strong>廣度</strong>：覆蓋 DL 所有主要分支、不只 NLP。</li>
<li><strong>更新頻率</strong>：每年新版、跟最新進展。</li>
</ul>
<p>連結：introtodeeplearning.com。</p>
<p>預估時間：每集 1 小時、約 7 ~ 10 集、總時數 10 ~ 15 小時。</p>
<h2 id="階段-7deeplearningai-specializations">階段 7：DeepLearning.AI Specializations</h2>
<p>Andrew Ng 創辦的 DeepLearning.AI 提供多個 LLM 相關 specialization、Coursera 上有付費 + 免費 audit 選項。</p>
<h3 id="推薦課程">推薦課程</h3>
<table>
  <thead>
      <tr>
          <th>Specialization</th>
          <th>涵蓋</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Deep Learning Specialization</td>
          <td>DL 基礎、CNN、RNN、Sequence Models</td>
      </tr>
      <tr>
          <td>Natural Language Processing Specialization</td>
          <td>NLP 從基礎到 Transformer</td>
      </tr>
      <tr>
          <td>Generative AI with Large Language Models</td>
          <td>LLM lifecycle、prompt、fine-tuning、RLHF</td>
      </tr>
      <tr>
          <td>各種 short courses（免費 audit）</td>
          <td>1 ~ 2 小時的專題、LangChain、RAG、Agents 等</td>
      </tr>
  </tbody>
</table>
<p><strong>Short courses 特別推薦</strong>：免費 + 短、跟最新工具同步。例：</p>
<ul>
<li><code>ChatGPT Prompt Engineering for Developers</code></li>
<li><code>LangChain for LLM Application Development</code></li>
<li><code>Building Systems with the ChatGPT API</code></li>
<li><code>Functions, Tools and Agents with LangChain</code></li>
<li><code>Fine-tuning LLMs</code></li>
<li><code>Pretraining LLMs</code></li>
</ul>
<p>連結：deeplearning.ai 的 short courses 頁面。</p>
<h2 id="階段-8hugging-face-nlp-course">階段 8：Hugging Face NLP Course</h2>
<p>Hugging Face 官方教材、實作取向。涵蓋 Transformers library、tokenizer 訓練、模型 fine-tuning、deployment。</p>
<ul>
<li><strong>連結</strong>：huggingface.co/learn/nlp-course</li>
<li><strong>特性</strong>：免費、用 Hugging Face 生態系實作、適合工程師</li>
<li><strong>章節</strong>：12 章、約 30 ~ 40 小時</li>
</ul>
<p>完成這門課、你能用 Transformers library 做：</p>
<ul>
<li>載入跟用任何 Hugging Face 模型</li>
<li>自己訓練 tokenizer</li>
<li>Fine-tune 模型（含 LoRA）</li>
<li>部署到 Inference Endpoints</li>
</ul>
<h2 id="必讀-papers">必讀 Papers</h2>
<p>讀完課程後、跟最新研究進度的方式是讀 paper。以下是 LLM 領域的「必讀經典」、按時間順序：</p>
<table>
  <thead>
      <tr>
          <th>Paper</th>
          <th>重要性</th>
          <th>對應模組三章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Attention Is All You Need (Vaswani et al., 2017)</td>
          <td>Transformer 原始 paper</td>
          <td><a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2 attention</a></td>
      </tr>
      <tr>
          <td>BERT (Devlin et al., 2018)</td>
          <td>Bidirectional pretraining</td>
          <td><a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer architecture</a></td>
      </tr>
      <tr>
          <td>GPT-2 paper (Radford et al., 2019)</td>
          <td>Decoder-only 規模化的開端</td>
          <td><a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer architecture</a></td>
      </tr>
      <tr>
          <td>Scaling Laws (Kaplan et al., 2020)</td>
          <td>模型 / 資料 / 算力之間的 scaling 關係</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>GPT-3 paper (Brown et al., 2020)</td>
          <td>In-context learning 的湧現</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>Chinchilla (Hoffmann et al., 2022)</td>
          <td>修正 scaling laws、改變訓練配比</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>InstructGPT (Ouyang et al., 2022)</td>
          <td>RLHF 的標誌性實作</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>LLaMA (Touvron et al., 2023)</td>
          <td>Open-weight 大模型的標竿</td>
          <td><a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer architecture</a></td>
      </tr>
      <tr>
          <td>LLaMA 2 (Touvron et al., 2023)</td>
          <td>Open chat model</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>DPO (Rafailov et al., 2023)</td>
          <td>RLHF 的簡化替代</td>
          <td><a href="/blog/llm/03-theoretical-foundations/training-pipeline/" data-link-title="3.4 訓練流程：pre-train → SFT → RLHF" data-link-desc="LLM 的三階段訓練：預訓練、指令微調、人類反饋強化學習；各階段目標與最新替代方案">3.4 training pipeline</a></td>
      </tr>
      <tr>
          <td>Mixture of Experts (Shazeer et al., 2017、Mixtral 2024)</td>
          <td>MoE 路線</td>
          <td><a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer architecture</a></td>
      </tr>
      <tr>
          <td>RoPE (Su et al., 2021)</td>
          <td>現代 LLM 主流位置編碼</td>
          <td><a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 transformer architecture</a></td>
      </tr>
      <tr>
          <td>Flash Attention (Dao et al., 2022)</td>
          <td>Attention 高效實作</td>
          <td><a href="/blog/llm/03-theoretical-foundations/attention-mechanism/" data-link-title="3.2 Attention 機制" data-link-desc="Query / Key / Value、scaled dot-product attention、multi-head attention：Transformer 的核心運算">3.2 attention</a></td>
      </tr>
  </tbody>
</table>
<p>讀 paper 的順序建議：先讀 abstract + intro + conclusion 抓研究問題與結論、再看 method 細節、最後看 experiment 與 ablation。初學者可優先讀 Transformer 原始 paper + GPT-2 + Chinchilla + InstructGPT 四篇、覆蓋「架構 / 預訓練 / scaling / alignment」骨架；Flash Attention、MoE 等工程細節 paper 可後補。</p>
<p>訂閱 arXiv <code>cs.CL</code>、<code>cs.LG</code> daily list、或關注 Hugging Face Daily Papers、X / Twitter 上的 ML researcher、能持續跟最新進展。</p>
<h2 id="書籍補充">書籍補充</h2>
<table>
  <thead>
      <tr>
          <th>書名</th>
          <th>涵蓋</th>
          <th>免費</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Speech and Language Processing by Jurafsky &amp; Martin</td>
          <td>NLP 完整教科書、第 3 版含 LLM</td>
          <td>是</td>
      </tr>
      <tr>
          <td>Build a Large Language Model From Scratch by Sebastian Raschka</td>
          <td>從零實作 GPT-style LLM</td>
          <td>否（紙本）</td>
      </tr>
      <tr>
          <td>Hands-On Large Language Models by Jay Alammar</td>
          <td>視覺化 + 實作</td>
          <td>否</td>
      </tr>
      <tr>
          <td>The Illustrated Transformer by Jay Alammar</td>
          <td>部落格文章、視覺化解釋 Transformer</td>
          <td>是</td>
      </tr>
  </tbody>
</table>
<p>Jay Alammar 的 <code>The Illustrated Transformer</code>、<code>The Illustrated GPT-2</code> 等部落格文章、是視覺化解釋的經典。免費、google 直接搜尋。</p>
<h2 id="建議的時間投入">建議的時間投入</h2>
<table>
  <thead>
      <tr>
          <th>目標</th>
          <th>預估時間（投入 5 ~ 10 小時 / 週）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>看完 3Blue1Brown GPT 系列</td>
          <td>1 ~ 2 週</td>
      </tr>
      <tr>
          <td>完成 Karpathy zero-to-hero</td>
          <td>4 ~ 8 週</td>
      </tr>
      <tr>
          <td>完成 Stanford CS224N</td>
          <td>10 週</td>
      </tr>
      <tr>
          <td>完成 Stanford CS336</td>
          <td>10 週</td>
      </tr>
      <tr>
          <td>完成 Hugging Face NLP Course</td>
          <td>4 ~ 6 週</td>
      </tr>
      <tr>
          <td>讀完上面 12 篇必讀 paper</td>
          <td>4 ~ 8 週</td>
      </tr>
  </tbody>
</table>
<p>寫 code 場景的使用者通常用「3Blue1Brown + Karpathy zero-to-hero + 跟最新 paper」這個組合就能跟 LLM 進展接軌、約 6 ~ 12 週投入。想做研究 / 自己訓練模型、再進入 Stanford CS336、CS224N、必讀 paper 等正式學習路徑。</p>
<h2 id="建議的學習順序">建議的學習順序</h2>
<p>對「想理解 LLM 內部、不打算自己訓練」的工程師：</p>
<ol>
<li>看 3Blue1Brown GPT 系列（1 ~ 2 週）</li>
<li>看 Karpathy <code>Let's build GPT from scratch</code>（1 週）</li>
<li>看 Karpathy <code>Let's reproduce GPT-2</code>（2 週）</li>
<li>看 Stanford CS25 感興趣的集數（自由）</li>
</ol>
<p>對「想做 LLM 應用開發」的工程師：</p>
<ol>
<li>同上</li>
<li>
<ul>
<li>DeepLearning.AI short courses（LangChain、RAG、Agents、Prompt Engineering）</li>
</ul>
</li>
<li>
<ul>
<li>Hugging Face NLP Course</li>
</ul>
</li>
</ol>
<p>對「想做 LLM 訓練 / fine-tuning」的研究者：</p>
<ol>
<li>同上</li>
<li>
<ul>
<li>Karpathy 完整 zero-to-hero 系列</li>
</ul>
</li>
<li>
<ul>
<li>Stanford CS224N（系統補課）</li>
</ul>
</li>
<li>
<ul>
<li>Stanford CS336（完整 lifecycle）</li>
</ul>
</li>
<li>
<ul>
<li>必讀 paper</li>
</ul>
</li>
</ol>
<h2 id="小結">小結</h2>
<p>讀到這裡、本系列指南就完整收尾。你應該能：</p>
<ul>
<li>在 Mac 上跑本地 LLM 寫 code（模組零 + 模組一）</li>
<li>判讀任何 LLM 相關資訊（模組零 0.6 五個框架）</li>
<li>理解 LLM 推論的數學基礎（模組二）</li>
<li>理解 LLM 內部運作機制（模組三）</li>
<li>知道想再深入該往哪走（本章 + <a href="/blog/llm/02-math-foundations/going-deeper-math/" data-link-title="2.4 想學更深：推薦公開課程" data-link-desc="MIT、Stanford、Harvard 等公開課程：數學基礎跟 LLM 預備知識的完整學習路線">模組二 2.4</a>）</li>
</ul>
<p>回到 <a href="/blog/llm/" data-link-title="LLM 寫 code 工程實務指南：從心智模型到應用架構" data-link-desc="以寫 code 場景為主、涵蓋本地推論（Mac / PC）、雲端混用、LLM 數學與理論基礎、應用層架構（RAG / tool use / agent / VLM / 靜態 deployment）、reasoning model 與 speculative decoding、本地 dev 安全、跨工具世代不變的原理">LLM 寫 code 實務指南首頁</a> 看完整地圖。</p>
]]></content:encoded></item><item><title>3.0 神經網路基礎</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/neural-network-basics/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/neural-network-basics/</guid><description>&lt;p>神經網路（Neural Network、NN）是 LLM 的底層架構。完整描述需要從「單一 neuron 怎麼算」開始、堆疊成 layer、串成 multi-layer network、再加上訓練機制（forward pass 跑預測、backward pass 算 gradient）。本章把這條鏈走過一遍、為後續章節的 embedding、attention、Transformer 架構建立詞彙基底。&lt;/p>
&lt;p>本章預設讀者熟悉&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">線性代數&lt;/a>（矩陣乘法、向量內積）跟&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">微積分&lt;/a>（gradient、chain rule）。沒讀過模組二的讀者、可以先讀本章看哪些術語陌生再回頭補。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、你應該能：&lt;/p>
&lt;ol>
&lt;li>解釋「一個 layer 在做什麼」用線性代數的話。&lt;/li>
&lt;li>區分 activation function 的常見選擇（ReLU、GELU、SiLU）的差異。&lt;/li>
&lt;li>解釋為什麼神經網路需要非線性 activation。&lt;/li>
&lt;li>看到「N-layer Transformer」時、能對應到模型結構。&lt;/li>
&lt;/ol>
&lt;h2 id="單一-neuronlinear--activation">單一 neuron：linear + activation&lt;/h2>
&lt;p>單一 neuron（神經元）的核心定義是「對輸入做線性組合、再經過非線性函式」：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">output = activation(w · x + b)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其中：&lt;/p>
&lt;ul>
&lt;li>&lt;code>x&lt;/code>：輸入向量&lt;/li>
&lt;li>&lt;code>w&lt;/code>：權重向量&lt;/li>
&lt;li>&lt;code>b&lt;/code>：bias（純量）&lt;/li>
&lt;li>&lt;code>w · x&lt;/code>：&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積&lt;/a>&lt;/li>
&lt;li>&lt;code>activation&lt;/code>：非線性函式（如 ReLU、sigmoid、tanh）&lt;/li>
&lt;/ul>
&lt;p>直覺：先把輸入做加權求和、再用非線性函式扭曲一下。沒有非線性、堆 N 個 neuron 等同於一個線性變換、表達能力有限。&lt;/p>
&lt;h2 id="layer把-n-個-neuron-並排">Layer：把 N 個 neuron 並排&lt;/h2>
&lt;p>Layer（層）的核心定義是「把多個 neuron 並排處理同一個輸入」、結構上等同於矩陣乘法 + 向量加 bias + 逐元素 activation：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">output = activation(W @ x + b)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其中：&lt;/p>
&lt;ul>
&lt;li>&lt;code>W&lt;/code>：權重矩陣、shape &lt;code>(output_dim, input_dim)&lt;/code>&lt;/li>
&lt;li>&lt;code>x&lt;/code>：輸入向量、shape &lt;code>(input_dim,)&lt;/code>&lt;/li>
&lt;li>&lt;code>b&lt;/code>：bias 向量、shape &lt;code>(output_dim,)&lt;/code>&lt;/li>
&lt;li>&lt;code>W @ x&lt;/code>：&lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">矩陣乘法&lt;/a>&lt;/li>
&lt;li>結果 &lt;code>output&lt;/code>：shape &lt;code>(output_dim,)&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>例：input dim = 4096、output dim = 4096 的 layer、權重矩陣有 16,777,216 個參數。&lt;/p>
&lt;p>這種「&lt;code>activation(W @ x + b)&lt;/code>」結構叫 &lt;strong>linear layer&lt;/strong>、&lt;strong>fully-connected layer&lt;/strong>、或 &lt;strong>dense layer&lt;/strong>、是神經網路最基本的 building block。&lt;/p>
&lt;h2 id="activation-function引入非線性">Activation Function：引入非線性&lt;/h2>
&lt;p>Activation function（激活函式）的核心責任是「在每個 layer 後引入非線性、讓網路能表達複雜函式」。沒有它、N 個線性 layer 等同於一個線性 layer。&lt;/p>
&lt;p>主流 activation function：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>函式&lt;/th>
 &lt;th>公式&lt;/th>
 &lt;th>特性&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>ReLU&lt;/td>
 &lt;td>max(0, x)&lt;/td>
 &lt;td>簡單、快、深度網路標準選擇&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GELU&lt;/td>
 &lt;td>x × Φ(x)、Φ 是高斯 CDF&lt;/td>
 &lt;td>ReLU 的平滑版、Transformer 內 FFN 常用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SiLU / Swish&lt;/td>
 &lt;td>x × sigmoid(x)&lt;/td>
 &lt;td>跟 GELU 類似、Llama 系列用&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>sigmoid&lt;/td>
 &lt;td>1 / (1 + e^{-x})&lt;/td>
 &lt;td>早期常用、現在多半被 ReLU 系取代&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>tanh&lt;/td>
 &lt;td>(e^x - e^{-x}) / (e^x + e^{-x})&lt;/td>
 &lt;td>早期 RNN 常用、輸出在 -1 到 1 之間&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>softmax&lt;/td>
 &lt;td>exp(xᵢ) / Σⱼ exp(xⱼ)&lt;/td>
 &lt;td>不是逐元素 activation、用在輸出層轉機率分佈&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Transformer 內部主要用 GELU 或 SiLU。Sigmoid 跟 tanh 在深度 30+ 的網路中容易造成 &lt;a href="https://tarrragon.github.io/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">gradient vanishing&lt;/a>、Transformer 系列因此採用 GELU / SiLU；淺層網路（&amp;lt; 10 層）兩者影響較小、Sigmoid / tanh 仍可用。&lt;/p></description><content:encoded><![CDATA[<p>神經網路（Neural Network、NN）是 LLM 的底層架構。完整描述需要從「單一 neuron 怎麼算」開始、堆疊成 layer、串成 multi-layer network、再加上訓練機制（forward pass 跑預測、backward pass 算 gradient）。本章把這條鏈走過一遍、為後續章節的 embedding、attention、Transformer 架構建立詞彙基底。</p>
<p>本章預設讀者熟悉<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">線性代數</a>（矩陣乘法、向量內積）跟<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">微積分</a>（gradient、chain rule）。沒讀過模組二的讀者、可以先讀本章看哪些術語陌生再回頭補。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、你應該能：</p>
<ol>
<li>解釋「一個 layer 在做什麼」用線性代數的話。</li>
<li>區分 activation function 的常見選擇（ReLU、GELU、SiLU）的差異。</li>
<li>解釋為什麼神經網路需要非線性 activation。</li>
<li>看到「N-layer Transformer」時、能對應到模型結構。</li>
</ol>
<h2 id="單一-neuronlinear--activation">單一 neuron：linear + activation</h2>
<p>單一 neuron（神經元）的核心定義是「對輸入做線性組合、再經過非線性函式」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">output = activation(w · x + b)</span></span></code></pre></div><p>其中：</p>
<ul>
<li><code>x</code>：輸入向量</li>
<li><code>w</code>：權重向量</li>
<li><code>b</code>：bias（純量）</li>
<li><code>w · x</code>：<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">內積</a></li>
<li><code>activation</code>：非線性函式（如 ReLU、sigmoid、tanh）</li>
</ul>
<p>直覺：先把輸入做加權求和、再用非線性函式扭曲一下。沒有非線性、堆 N 個 neuron 等同於一個線性變換、表達能力有限。</p>
<h2 id="layer把-n-個-neuron-並排">Layer：把 N 個 neuron 並排</h2>
<p>Layer（層）的核心定義是「把多個 neuron 並排處理同一個輸入」、結構上等同於矩陣乘法 + 向量加 bias + 逐元素 activation：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">output = activation(W @ x + b)</span></span></code></pre></div><p>其中：</p>
<ul>
<li><code>W</code>：權重矩陣、shape <code>(output_dim, input_dim)</code></li>
<li><code>x</code>：輸入向量、shape <code>(input_dim,)</code></li>
<li><code>b</code>：bias 向量、shape <code>(output_dim,)</code></li>
<li><code>W @ x</code>：<a href="/blog/llm/02-math-foundations/linear-algebra-for-llm/" data-link-title="2.0 線性代數：向量、矩陣、空間" data-link-desc="LLM 內部運算的基底：向量、矩陣、向量空間、內積、norm、矩陣乘法的角色">矩陣乘法</a></li>
<li>結果 <code>output</code>：shape <code>(output_dim,)</code></li>
</ul>
<p>例：input dim = 4096、output dim = 4096 的 layer、權重矩陣有 16,777,216 個參數。</p>
<p>這種「<code>activation(W @ x + b)</code>」結構叫 <strong>linear layer</strong>、<strong>fully-connected layer</strong>、或 <strong>dense layer</strong>、是神經網路最基本的 building block。</p>
<h2 id="activation-function引入非線性">Activation Function：引入非線性</h2>
<p>Activation function（激活函式）的核心責任是「在每個 layer 後引入非線性、讓網路能表達複雜函式」。沒有它、N 個線性 layer 等同於一個線性 layer。</p>
<p>主流 activation function：</p>
<table>
  <thead>
      <tr>
          <th>函式</th>
          <th>公式</th>
          <th>特性</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ReLU</td>
          <td>max(0, x)</td>
          <td>簡單、快、深度網路標準選擇</td>
      </tr>
      <tr>
          <td>GELU</td>
          <td>x × Φ(x)、Φ 是高斯 CDF</td>
          <td>ReLU 的平滑版、Transformer 內 FFN 常用</td>
      </tr>
      <tr>
          <td>SiLU / Swish</td>
          <td>x × sigmoid(x)</td>
          <td>跟 GELU 類似、Llama 系列用</td>
      </tr>
      <tr>
          <td>sigmoid</td>
          <td>1 / (1 + e^{-x})</td>
          <td>早期常用、現在多半被 ReLU 系取代</td>
      </tr>
      <tr>
          <td>tanh</td>
          <td>(e^x - e^{-x}) / (e^x + e^{-x})</td>
          <td>早期 RNN 常用、輸出在 -1 到 1 之間</td>
      </tr>
      <tr>
          <td>softmax</td>
          <td>exp(xᵢ) / Σⱼ exp(xⱼ)</td>
          <td>不是逐元素 activation、用在輸出層轉機率分佈</td>
      </tr>
  </tbody>
</table>
<p>Transformer 內部主要用 GELU 或 SiLU。Sigmoid 跟 tanh 在深度 30+ 的網路中容易造成 <a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">gradient vanishing</a>、Transformer 系列因此採用 GELU / SiLU；淺層網路（&lt; 10 層）兩者影響較小、Sigmoid / tanh 仍可用。</p>
<p><a href="/blog/llm/02-math-foundations/probability-and-information/" data-link-title="2.1 機率與資訊論" data-link-desc="LLM 輸出的本質是機率分佈：softmax、cross-entropy、KL divergence、perplexity 在訓練與推論中的角色">Softmax</a> 是特殊 activation、用在輸出層把 logits 轉成機率分佈、不在中間 layer 用。</p>
<h2 id="multi-layer-network串接-n-個-layer">Multi-Layer Network：串接 N 個 layer</h2>
<p>Multi-layer network（多層網路）的核心結構是「N 個 layer 串接、前一層的 output 是下一層的 input」：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">h₁ = activation₁(W₁ @ x + b₁)
</span></span><span class="line"><span class="ln">2</span><span class="cl">h₂ = activation₂(W₂ @ h₁ + b₂)
</span></span><span class="line"><span class="ln">3</span><span class="cl">...
</span></span><span class="line"><span class="ln">4</span><span class="cl">output = activation_N(W_N @ h_{N-1} + b_N)</span></span></code></pre></div><p>「深度」（depth）指 layer 數量。Transformer LLM 的 layer 數通常 30 ~ 80：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>Layer 數</th>
          <th>Hidden Dim</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT-2 small</td>
          <td>12</td>
          <td>768</td>
      </tr>
      <tr>
          <td>Llama 3.3 8B</td>
          <td>32</td>
          <td>4096</td>
      </tr>
      <tr>
          <td>Llama 3.3 70B</td>
          <td>80</td>
          <td>8192</td>
      </tr>
      <tr>
          <td>Gemma 4 31B</td>
          <td>約 50</td>
          <td>約 5120</td>
      </tr>
  </tbody>
</table>
<p>每層都是線性變換 + activation；堆疊起來表達能力強。但深度高也意味著訓練難度高（<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">gradient vanishing / explosion</a>）、需要 residual connection 跟 layer norm 等技術配合。</p>
<h2 id="forward-pass從-input-算到-output">Forward Pass：從 input 算到 output</h2>
<p>Forward pass（前向傳播）的核心定義是「資料從 input 流經各層、產生 output 的計算過程」。每個 layer 順序做矩陣乘法 + activation。</p>
<p>LLM 的 forward pass 概略流程：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">input tokens → embedding layer → 數十個 Transformer block → output layer → logits</span></span></code></pre></div><p>每個 Transformer block 內部又包含 attention + feed-forward + 兩個 layer norm。詳細展開見 <a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 Transformer 架構</a>。</p>
<p>寫 code 場景的推論完全是 forward pass、不涉及 backward pass。每生一個 token 跑一次 forward pass、由 <a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> 決定速度上限。</p>
<h2 id="backward-pass從-loss-算-gradient">Backward Pass：從 loss 算 gradient</h2>
<p>Backward pass（反向傳播）的核心定義是「用 <a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">chain rule</a>、從 loss 倒推每個權重的 gradient」。它是訓練神經網路的基礎。</p>
<p>流程：</p>
<ol>
<li><strong>Forward</strong>：input → output → loss。</li>
<li><strong>Backward</strong>：從 loss 開始、逐層算 local gradient、用 chain rule 累積。</li>
<li><strong>Update</strong>：用 gradient 更新權重（<a href="/blog/llm/02-math-foundations/calculus-and-optimization/" data-link-title="2.2 微積分與最佳化" data-link-desc="從 gradient、chain rule 到 SGD / Adam：LLM 訓練如何更新數十億參數">gradient descent</a>）。</li>
</ol>
<p>實作上、PyTorch / MLX 等 framework 用 autograd 自動算 backward、開發者只寫 forward。</p>
<p>推論時無 backward pass、所以推論的記憶體跟算力需求遠低於訓練。</p>
<h2 id="bias可選的常數項">Bias：可選的常數項</h2>
<p>Bias 的核心定義是「neuron 的 <code>w · x + b</code> 中的 <code>+ b</code>」、讓 neuron 的輸出可以平移。</p>
<p>在 hidden_dim ≥ 4096 規模下、bias 對品質的邊際貢獻被觀察為近零、近年大型 LLM 普遍取消 bias 參數：</p>
<ul>
<li>Llama 系列、Gemma 系列、Qwen 系列都把 bias 設為 0、不訓練 bias 參數。</li>
<li>理由：實驗發現此規模下拿掉 bias 對品質影響微小、但能省記憶體與計算。</li>
</ul>
<p>某些早期 LLM（GPT-2 等）跟舊架構仍用 bias、小規模網路 / 特殊任務下 bias 仍有實際貢獻。看模型 config 可知這個模型是否含 bias 參數。</p>
<h2 id="hidden-layer-與-hidden-dimension">Hidden Layer 與 Hidden Dimension</h2>
<p>Hidden layer 的核心定義是「介於 input layer 跟 output layer 之間的中間 layer」。Hidden dimension（hidden_dim、d_model）是這些 layer 的輸出向量維度、規格見前一節 <a href="#multi-layer-network%e4%b8%b2%e6%8e%a5-n-%e5%80%8b-layer">Multi-Layer Network</a> 的表格。</p>
<p>Hidden dim 是模型「表達能力」的主要維度之一。每個 token 在模型內部都是一個 hidden_dim 維向量、layer 越大越能編碼複雜資訊。</p>
<h2 id="為什麼需要這麼多-parameter">為什麼需要這麼多 parameter</h2>
<p>LLM 參數量主要來自 layer 數 × 每層權重矩陣大小、其中 FFN 層約佔 2/3。每個 layer 的權重矩陣大小是 <code>hidden_dim × hidden_dim</code>（feed-forward layer 通常 <code>hidden_dim × 4 × hidden_dim</code>、4 倍的由來見 <a href="/blog/llm/03-theoretical-foundations/transformer-architecture/" data-link-title="3.3 Transformer 架構細節" data-link-desc="Decoder-only 結構、Transformer block、positional encoding、layer norm、residual stream">3.3 Transformer 架構</a>）、加上 attention 的 Q/K/V projection 等、單一 layer 已有上億參數。</p>
<p>Gemma 4 31B 約 50 layer、每層約 600M 參數、合計約 31B。70B / 405B 模型也是類似結構放大。</p>
<p>參數數量越多、模型「能學到的 pattern」越多。預訓練資料 trillion token 級別、需要大模型才能完整「記住」這些 pattern。實務上邊際收益隨參數量遞減（同代架構下參數翻倍、benchmark 提升通常 &lt; 5%）、且推論成本線性增加；這就是為什麼 31B / 70B 級別停滯一段時間後、業界把焦點轉向 <a href="/blog/llm/knowledge-cards/moe-cpu-offload/" data-link-title="MoE CPU 卸載" data-link-desc="把 Mixture-of-Experts 模型不活躍的專家層權重放在系統 RAM、用到再走 PCIe 拉回 GPU、讓有限 VRAM 跑得了更大模型">MoE</a> 等「不增加每 token 算量」的擴張路徑。</p>
<h2 id="何時這套基礎不適用">何時這套基礎不適用</h2>
<p>本章的「neuron → linear layer → forward / backward pass」假設「純 dense Transformer」架構、實務上有幾類架構走不同的計算路徑、判讀新架構時要對應調整：</p>
<table>
  <thead>
      <tr>
          <th>架構</th>
          <th>跟本章基礎的差異</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MoE（Mixture of Experts）</td>
          <td>每個 token 只啟用部分專家層、forward pass 中 router 動態決定哪些 dense layer 跑</td>
      </tr>
      <tr>
          <td>SSM（如 Mamba）</td>
          <td>用 state-space 遞迴取代 attention、forward 結構跟「層層 dense」不同</td>
      </tr>
      <tr>
          <td>Diffusion 模型</td>
          <td>U-Net 結構含 down-sampling + up-sampling、跟純 stack 的 Transformer 拓撲不同</td>
      </tr>
      <tr>
          <td>Recurrent LLM 變體（如 RWKV）</td>
          <td>走 recurrent state、不純做 forward stack</td>
      </tr>
  </tbody>
</table>
<p>判讀新架構時、先把它跟本章的 dense Transformer baseline 對照、找出在哪一步岔開（哪個 layer 結構、forward 順序、parameter sharing）、再深入差異點。</p>
<h2 id="下一章">下一章</h2>
<p>下一章：<a href="/blog/llm/03-theoretical-foundations/embedding-spaces/" data-link-title="3.1 Embedding 空間" data-link-desc="token 怎麼變成向量、為什麼相似 token 在向量空間中靠近、embedding 是怎麼學出來的">3.1 embedding 空間</a>、從「token 怎麼變成向量」開始。</p>
]]></content:encoded></item></channel></rss>