Karpathy Python GPT 實作指南

理解 LLM 的最小可行教學工具:從零開始構建 GPT 的純 Python 實現

Karpathy Python GPT 實作指南

研究日期

2026-02-13

簡介

Karpathy 的 Python GPT 是 Andrej Karpathy 創建的一系列約 200-300 行純 Python GPT 實現的統稱,最著名的包括 microGPT(243 行)、minGPT(300 行)、nanoGPT(600 行)。這些項目完全無需依賴 PyTorch 或其他深度學習框架,只用 Python 標準庫(osmathrandom),展示了 LLM 的算法本質。

為什麼值得學?

  • 透明度高:沒有框架黑盒,每個組件都清清楚楚地寫在眼前
  • 理解核心原理:從 Token Embedding 到 Attention,從 Autograd 到 Transformer,逐行理解機制
  • 適合教育目的:不是為生產環境設計,而是為學習者理解"這個算法如何運作"
  • 可作為跳板:理解這個純 Python 版本後,更容易掌握 PyTorch/HuggingFace 等框架的優化

主要特性

  • 零依賴:只需 Python 標準庫,無需安裝任何大型框架
  • 完整 GPT 架構:包含 Token & Position Embeddings、Multi-head Self-Attention、MLP Feed-forward blocks
  • 自定義 Autograd:手動實現反向傳播,鏈式法則自己推導
  • Adam 優化器:完整實現帶 learning rate decay 的自適應優化
  • 從零訓練到推理:包含數據載入、訓練循環、生成採樣的完整流程
  • RMSNorm:替代 LayerNorm,使用均方根歸一化
  • 移除所有 biases:簡化架構,減少參數量

工作原理

Autograd 系統

Value 類實現了一個手動計算圖系統:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Value:
    def __init__(self, data):
        self.data = data      # 節點存儲的標量值
        self.grad = 0         # 該參數的梯度(反向傳播時計算)
        self._children = []   # 子節點列表(用於拓撲排序)
        self._local_grads = [] # 局部梯度列表

    def __add__(self, other):
        # 前向傳播時累積數據
        return Value(self.data + other.data, (self, other), (1, 1))

    def backward(self):
        # 反向傳播時,按照拓撲排序構建計算圖
        # 先處理所有子節點,再計算當前節點的梯度
        ...

核心思想

  • 節點之間形成計算圖
  • 反向傳播時按照拓撲排序(從輸出往回)
  • 每個節點只計算一次梯度(避免重複計算)
  • 支持鏈式法則自動微分

Attention 機制

Multi-head Self-Attention 的實現展示了 Q/K/V 矩陣運算:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 每個 attention head
q_h = q[hs:hs+head_dim]      # 查詢向量的切片
k_h = [ki[hs:hs+head_dim] for ki in keys]  # 鍵向量的切片
v_h = [vi[hs:hs+head_dim] for vi in values]  # 值向量的切片

# Attention scores
attn_logits = [sum(q_h[j] * k_h[t][j] for j in range(head_dim)) 
               for t in range(len(k_h))] / head_dim**0.5

# 加權求和(Softmax)
attn_weights = softmax(attn_logits)

# 輸出
head_out = [sum(attn_weights[t] * v_h[t][j] for t in range(len(v_h))) 
            for j in range(head_dim)]

關鍵點

  • head_dim 的作用:將嵌入維度分配到各個 attention head
  • 除以 head_dim** **0.5:縮放因子(保持數值穩定性)
  • Softmax 之前除以 `head_dim** 是為了保持注意力權重的歸一化

Transformer 完整流程

  1. 輸入處理

    • Token Embedding:將 token ID 映射到嵌入向量
    • Position Embedding:加入位置信息
    • 兩者相加得到輸入
  2. Transformer 層循環(對於 1 層):

    • Pre-norm(RMSNorm)
    • Multi-head Attention
    • 殘差連接 + 層歸一化
    • MLP(2 個線性層 + ReLU 激活)
    • Post-norm(RMSNorm)
    • 殘差連接
  3. 輸出層

    • 線性投影到詞彙大小
    • Logits → Softmax → 預測下一個 token

RMSNorm 實現

1
2
3
4
def rmsnorm(x):
    ms = sum(xi * xi for xi in x) / len(x)  # 均方
    scale = (ms + 1e-5) ** -0.5            # 數值穩定性
    return [xi * scale for xi in x]

為什麼用 RMSNorm 而不是 LayerNorm?

  • RMSNorm 不需要存儲移動平均(節省內存)
  • 更簡單的實現
  • 在 GPT-2/3 中被廣泛採用

訓練循環

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 取單個文檔
doc = docs[step % len(docs)]

# Tokenize
tokens = [BOS] + [uchars.index(ch) for ch in doc] + [BOS]

# Forward pass(累積 loss)
for pos in range(n):
    token_id, target_id = tokens[pos], tokens[pos + 1]
    logits = gpt(token_id, pos, keys, values)
    probs = softmax(logits)
    loss_t = -probs[target_id].log()
    losses.append(loss_t)

# Backward pass(計算梯度)
loss = (1 / n) * sum(losses)
loss.backward()

# Adam 優化器更新
for i, p in enumerate(params):
    # m, v: 一階、二階矩
    m[i] = beta1 * m[i] + (1 - beta1) * p.grad
    v[i] = beta2 * v[i] + (1 - beta2) * p.grad ** 2
    # bias correction
    m_hat = m[i] / (1 - beta1 ** (step + 1))
    v_hat = v[i] / (1 - beta2 ** (step + 1))
    p.data -= lr_t * m_hat / (v_hat ** 0.5 + eps_adam)

推理生成

1
2
3
4
5
6
7
8
temperature = 0.5  # 控制創造性
for sample_idx in range(20):
    logits = gpt(token_id, pos_id, keys, values)
    probs = softmax([l / temperature for l in logits])  # 溫度縮放
    token_id = random.choices(range(vocab_size), weights=probs)[0]
    if token_id == BOS:
        break
    sample.append(uchars[token_id])

主要使用案例

1. 教育用途

  • 大學課程:作為計算機科學或 AI 課程的教學材料
  • 在線教程:學習者可以從 GitHub 下載代碼直接運行
  • 技術博客:解釋 Transformer 工作原理的博客文章

2. 快速原型驗證

  • 算法實驗:驗證新的 attention 機制或正規化方法
  • 論文重現:閱讀論文後用這個框架快速實驗
  • 改進想法測試:在完整框架前先測試想法的核心算法

3. 理解框架實現的對比

  • 對比 PyTorch:用 microGPT 理解 torch.nn.Module 是如何封裝的
  • 對比 HuggingFace:理解 GPT2Model 的 API 設計
  • 性能基準測試:純 Python 版本作為基準,評估框架開銷

安裝與設定

快速開始

1
2
3
# 只需 Python,無需 pip install
curl -O microgpt.py https://gist.githubusercontent.com/karpathy/8627fe009c40f57531cb18360106ce95/raw
python microgpt.py

首次運行

1
2
3
# 會自動下載示例數據集
# 訓練 1000 步(約需數分鐘)
# 輸出 20 個生成的名字

調整參數

1
2
3
4
5
6
n_embd = 16      # 嵌入維度
n_head = 4       # attention heads 數量
n_layer = 1       # Transformer 層數
block_size = 16   # 最大序列長度
learning_rate = 0.01
num_steps = 1000

運行推理

1
2
3
# 修改溫度或輸入
temperature = 0.8  # 更高的創造性
python microgpt.py --temperature 0.8 --seed 42

自定義數據集

1
2
# 使用自己的文本文件
python microgpt.py --data my_custom_dataset.txt

最佳實踐

從小模型開始

  • 保持默認參數先跑通,理解行為
  • 理解計算圖:重點研究 Value.backward() 方法(拓撲排序)
  • 對比框架實現:將此實現與 PyTorch 版本對照

理解計算圖

  • 重點研究 Value.backward() 方法(拓撲排序 + 鏈式法則)
  • 看梯度是如何從 loss 回傳到每一個參數的
  • 理解為什麼需要 requires_grad

對比框架實現

  • 將此實現與 PyTorch 版本對照,理解框架封裝了什麼
  • 研究 Q/K/V 矩陣運算 → softmax → 加權求和的對應關係

實驗極限

  • 嘗試增大 n_layern_embd
  • 但會遇到性能瓶頸(純 Python 運行慢)
  • 理解性能瓶頸所在

用作跳板

  • 理解後過渡到 nanoGPT(PyTorch 實現,可實際應用)
  • 或使用 HuggingFace Transformers 進行實際應用開發

性能優化

優化技巧

  1. 減少參數量:移除 biases、使用較小的嵌入維度
  2. 訓練優化:使用更好的初始化、調整 batch size
  3. 推理優化:使用 KV Cache 避免重複計算

常見問題與解決

問題 解決方案
Loss 不下降 檢查學習率是否過大/過小,確認梯度計算是否正確
生成內容重複 降低 temperature,增加訓練步數
訓練不收斂 減少學習率,檢查數據質量
運行太慢 microGPT 本身就很慢(純 Python),這是預期的

適合人群

  • LLM 工程師:想理解推理性能瓶頸(為什麼 attention 是 O(n²))
  • Infra 工程師:想自己寫 kernel 優化矩陣運算
  • AI 研究者:想改架構、改 attention 機制
  • 想深入原理的人:不是「會用就行」,而是「懂為什麼」

進階功能

微調預訓練模型

  • 擴展更大的模型
  • 多 GPU 訓練
  • 自訂義數據集

多 GPU 支持

  • 並行化訓練
  • 分布式推理

自訂義注意力機制

  • Flash Attention
  • 線性 Attention
  • 稀疏 Attention

常見問題與解答

Q: microGPT 與 nanoGPT 有什麼區別?

A: nanoGPT 是 Karpathy 用 PyTorch 重寫的版本,增加了更多層數、更好的性能、GPU 支援等生產級特性。microGPT 是教育用的純 Python 版本。

Q: 為什麼沒有使用 PyTorch?

A: 為了讓代碼完全透明,每個算法步驟都能看懂。PyTorch 的自動求導雖然方便,但隱藏了底層原理。

Q: 可以用於生產環境嗎?

A: 不推薦。性能極低,無 GPU 支援,無 batch 處理。適合學習和原型驗證。

Q: 如何擴展到更多層?

A: 在配置中增加 n_layer 參數,並在初始化 state_dict 時為每個層創建相應的參數矩陣。

Q: 為什麼使用 RMSNorm 而不是 LayerNorm?

A: RMSNorm 不需要存儲移動平均(節省內存),實現更簡單。這是 GPT-2/3 的選擇。

Q: 可以改用其他激活函數嗎?

A: 可以。只要將 x.relu() 改成你想要的激活函數(如 GELU、Swish),並相應調整導數即可。

參考資料

官方文檔與源碼

相關項目與資源

技術文章

總結

microGPT 系列是 LLM 的「Hello World」

  • ✅ 完全理解 GPT 的本質(只需 200-300 行純 Python)
  • ✅ 無框架依賴,任何 Python 環境可運行
  • ✅ 最佳的教育和實驗工具
  • ❌ 不適合生產環境(太慢、無 GPU 支持、無 batch)

學習路徑建議

  1. 先行 microGPT 理解基本流程
  2. 研究 nanoGPT 學習 PyTorch 實現的優化
  3. 使用 HuggingFace Transformers 進行實際應用開發
  4. 對比兩個版本,理解框架封裝的價值和開銷

這不是一個「可以直接上生產」的項目,而是一個「讀完之後你會變強」的項目。約 200-300 行,但每一個字節都在教你 Transformer 的底層原理。