一張3090兩天,我把GPT-2從頭訓了一遍:普通人離"煉丹"到底還有多遠

把這次實驗當成一面鏡子:它既照出了消費級硬體賦予個體的驚人能力,也照出了從"能跑"到"能用"之間那條還跨不過去的溝。

一、事情的起點

讀完 Sebastian Raschka 的《Build a Large Language Model From Scratch》後,一個念頭揮之不去:

如果不靠雲、不靠叢集,僅憑一張家裡的消費級顯示卡,普通人到底能不能從頭"煉"出一個像點樣的基礎模型?

粗略的直覺是不行。但 Andrej Karpathy 已經用 nanoChat 證明過一次——一個 5.61 億參數的模型,8 張 H100 跑 4 小時、花 100 美元就能訓完。他把門檻踩到了地上。

那我們再退一步:1.63 億參數、GPT-2 small 那個量級,單張 24GB 的遊戲顯示卡,有沒有戲?

二、先把靶子釘死

要復現的是 2019 年 OpenAI 那版 GPT-2 small,配置嚴格照抄:

  • 詞表 50257(沿用 GPT-2 分詞器)
  • 上下文長度 1024 token
  • 嵌入維度 768、12 個注意力頭、12 層 Transformer
  • dropout 0.1
  • 一個現代實踐上的取捨:去掉 QKV 投影裡的偏置項

最終參數量卡在 1.63 億。不多不少,正好卡在"單卡顯存能塞下"和"能學出點東西"的甜蜜點上。

三、資料這一關比硬體還狠

原版 GPT-2 用的是約 100 億 token 的 WebText,早沒人維護了。現在 Hugging Face 上現成的 FineWeb 資料集把這個量級補上了,更講究的還有 FineWeb-Edu——只留"教育性網頁"的子集。

真正麻煩的是一個細節:把 FineWeb 整個拉下來看文本長度分佈,會發現大量文檔本身就超過 1024 token。如果粗暴按文檔截斷再 padding,直接扔掉 29% 的 token。

兩種做法:

  1. 裁了 pad——簡單,但浪費資料;
  2. 把所有文本用分隔符拼成超長流,再切成 1024 token 的片段——複雜,但更接近原版 GPT-2 當時的訓練方式。

選第二種。

四、24GB 顯存是條死線

RTX 3090 的顯存決定了 batch size 上限,也就決定了吞吐。寫個測試腳本在不同精度下實測:

精度 最大 batch 吞吐
FP32 5 12599 token/s
TF32(開張量核心) 5 15402 token/s
自動混合精度 AMP 6 約 20000 token/s

最後一檔是甜點:吞吐拉到接近 2 萬 token/s,batch 還能再往上推一格。這是整個專案能不能在一個週末跑完的生死線。

五、訓多少?Chinchilla 定律給的答案

原版 GPT-2 論文語焉不詳,外界估算它在那 100 億 token 上跑了約 40 個 epoch——顯然不是單卡能碰的量級。

DeepMind 的 Chinchilla 定律給了一個計算最優的經驗值:訓練 token 數 ≈ 參數量的 20 倍。

1.63 億 × 20 ≈ 32.6 億 token。FineWeb 的 100 億樣本足夠覆蓋,意味著單 epoch 就能完成,不用反覆遍歷。

賬算一下:32.6 億 ÷ 20000 ≈ 16.3 萬秒,約 45 小時。一個週末,正好。

六、基建比訓練本身還磨人

真開跑之前,三件事必須先落地:

資料預處理:從 FineWeb 裡抽 32.6 億訓練 token + 1960 萬驗證 token,拼接、切段、存成張量格式。訓練集約 13GB。

檢查點機制:一跑就是兩天,崩了不能重來。每個檢查點要存模型權重、優化器狀態、梯度縮放器狀態和訓練進度——一份就接近 2GB。每半小時存一次,磁盤是貴,但中斷重跑更貴。

驗證節奏:每 7020 步跑一次驗證,單次驗證吃 1960 萬 token、約 5 分鐘。佔總時長的比例合理,但不能再頻繁。

七、48 小時後,第一個結果出來了

連續跑了約 48 小時,驗證損失停在 3.94。

跑個生成測試,prompt 是 "Every effort moves you":

  • 未訓練模型:"…ワISIS Keectar handling holistic Supply query…"——純亂碼;
  • 本次訓出來的模型:"…towards a sustainable and holistic diet of water, protein, vitamins, and protein"——語義通順,但出現了小模型典型的重複(protein 說兩遍);
  • 原版 GPT-2 權重:"…as far as the hand can go until the end of your turn unless something interrupts your control flow…"——邏輯和想象力都明顯高一檔。

定量更扎心:同一個驗證集上,原版 GPT-2 small 損失 3.50、困惑度約 33.1;本次模型損失 3.94、困惑度 51.4。差距肉眼可見。

八、"更乾淨的資料"反而更差?

第一個自然的念頭是:換 FineWeb-Edu,"最有教育價值"的資料,模型是不是能更好?

於是又一個 48 小時跑起來。結果反直覺:

  • 在 FineWeb-Edu 自己的驗證集上,損失降到 3.693——看起來更好了;
  • 但把它拿回最初的 FineWeb 驗證集測,損失 4.16——反而顯著更差。

後續用 Alpaca 格式資料做指令微調、再讓 GPT-5.1 打分:FineWeb 版微調後 16.14 分,FineWeb-Edu 版只有 15.18。

"更乾淨"沒有直接變成"更強"。合理的推測是:教育子集砍掉了大量真實世界的語料多樣性,泛化能力反而被鎖死了。

九、那再多訓一倍呢?

在 FineWeb-Edu 版基礎上,再追加 32.6 億 token(總算到 65 億):

  • 驗證損失 3.693 → 3.661,提升不到 1%;
  • FineWeb 驗證集 4.16 → 4.13;
  • 指令微調評分 16.62,略好但有限。

雙倍時間、雙倍電費,沒有換來質變。收益遞減在 1.63 億這個量級上非常早地就出現了。

十、跟原版差在哪

把自研模型和 OpenAI 原版權重逐項擺開,差距來源基本清楚:

  • 資料量與輪次:原版約 4000 億 token(幾十 epoch),本次 32–65 億(1–2 epoch)。深度"研磨"資料這件事,單卡做不到;
  • 架構細節:原版保留了 QKV 偏置和權重綁定,本次按現代實踐去掉了。這些"復古"設計在當年的訓練動力學裡可能有特殊價值;
  • 訓練技巧:梯度裁剪、更復雜的學習率調度(如餘弦退火),本次沒完全用上;
  • batch size:原版全局 batch 512,單卡物理上只能到 6。更大的 batch 帶來更穩的梯度方向;
  • 精度:原版很可能全程 FP32,本次為了速度用了混合精度,數值穩定性上讓了一步。

十一、這面鏡子照出了什麼

最初那個問題的答案是"是":單張 3090、兩天時間、幾十塊電費,任何人都能從零訓出一個有基本語言能力的 GPT-2 級模型。這件事在五年前不可想象。

但邊界也同樣清楚:

  • Chinchilla 最優是一個高效的起點,不是終點;
  • 要逼近工業級模型,需要的是指數級增長的資料、算力和工程打磨;
  • 個人開發者能"學會煉丹",但很難"煉出工業級丹"。

最後那個模型會一本正經地搞錯《傲慢與偏見》的作者。它是一面鏡子:一邊照出開源生態和消費硬體給個體的能力天花板已經被頂得很高,另一邊照出從"能用"到"卓越"之間,那條仍然需要巨大投入才能跨過的溝。

對獨立開發者來說,這個結論其實不虧——你不需要自己訓出 GPT-5,你只需要知道這條溝在哪、知道哪些環節可以站在別人肩膀上、把自己的精力放在產品和玩法上。煉丹的故事聽個響就好,真要發產品,還是得用現成的強模型。

(本文觀點僅代表作者個人。)