梯度尖峰從何而來
平靜的小批量與震撼的一個
大多數小批量會產生幅度合理的梯度。對於已經大致擬合資料的模型,交叉熵損失維持在狹窄範圍內;反向傳播將該訊號以相似大小的梯度形式傳回。
有些小批量不會。三個梯度尖峰來源:
1. 異常值範例。 單一序列包含極為罕見的 token 組合,會產生遠離平均值的損失 & 遠離平均值的梯度。
2. 數值邊緣情況。 接近零的 softmax 分母、產生 NaN 的 layernorm、FP16 溢位。每種情況都可能產生比典型值大數個量級的梯度。
3. 分佈偏移。 在單一訓練過程中切換資料來源,會讓模型受到新分佈的衝擊。ANDREA 的 bandit 每 7 到 42 步重新調整來源權重。每一次切換都是一次小的分佈偏移。
ANDREA-120M v1:尖峰級聯
v1 沒有梯度裁剪。bandit 每 7 到 42 步的來源轉換,向模型餵入短暫的 repo-docs(清單結構)、然後 gutenberg(長篇散文)、然後 hermes3-general(問答)爆發。每一次轉換都會產生梯度尖峰:每個尖峰會將權重推向 120M 規模的退化吸引子。
關鍵實證事實。 ANDREA-12M 在沒有裁剪的情況下存活了相同的盜匪攻擊。較小的權重矩陣對梯度衝擊保持穩健;單一壞批次無法將 12M 參數推入失控吸引子,但卻能將 120M 參數推入。隨著模型規模擴大,裁剪變得更加重要。
全域 L2 範數裁剪
兩種選擇:每張量或全域
限制梯度大小的兩種方法:
每張量裁剪。 獨立裁剪每個梯度張量。嵌入梯度根據其自身範數裁剪;注意力梯度根據其自身範數裁剪。簡單,但會扭曲相對尺度:一個張量中的小峰值(現在梯度為零)與另一個張量中的巨大梯度(未受影響)配對。
全域 L2 範數裁剪。 將所有梯度視為一個大向量。計算每個參數的總 L2 範數。如果範數超過 max_norm,則以相同因子縮放每個梯度。保留張量間的相對大小。
ANDREA 使用全域裁剪。Pascanu 等人(2013)透過實證證明,全域裁剪在 Transformer 訓練中優於每個張量的裁剪。
數學公式
計算全域 L2 範數:
norm = sqrt(sum over all params of g_i^2)
如果 norm <= max_norm,梯度會不變地通過。如果 norm > max_norm,則將每個梯度按 max_norm / norm 縮放:
g_i_clipped = g_i * (max_norm / norm)
縮放後,新 norm 恰好等於 max_norm。ANDREA 使用 max_norm = 1.0。
計算縮放因子
為什麼梯度範數計算需要三個核心
樸素演算法無法在 GPU 上運行
全域 L2 範數計算的偽代碼:
total = 0
對每個參數 p:
對 p.grad 中的每個元素 g:
total += g * g
norm = sqrt(total)
在 GPU 上,這個天真的迴圈會因為兩個原因而失敗:
1. 順序累加。 單一 total 累加器迫使每個執行緒等待其他所有執行緒,敗壞了 GPU 並行性。
2. 異質張量。 ANDREA-120M 擁有形狀極為不同的張量:嵌入 (8449 x 768)、注意力 QKV (768 x 768)、層歸一化 (768)。單一核心無法有效迭代所有形狀。
ANDREA 的三核心管線
將工作分割成 microgpt_cuda.cu 中的三個 CUDA 核心:
核心 1: k_grad_norm_partial。 對每個參數張量,計算平方和的部分總和。每個執行緒區塊還原張量的一個區塊;結果寫入小型刮除緩衝區。並行性:每個區塊一個區塊,所有張量橫跨數百個區塊。
[BLOCK_TYPE SECTION/STEP]
__BLOCK_N__
<translated content>
Kernel 2: k_grad_norm_final。 將暫存緩衝區歸約為單一純量。取其平方根。一個小型核心,執行時間僅微秒級。
Kernel 3: k_grad_scale。 如果 norm > max_norm,計算 scale = max_norm / norm 並將每個梯度元素乘以 scale。遍歷每個梯度張量一次,完全平行化。
順序很重要:Pre-Adam
裁剪管線在 AdamW 更新 m、v 或任何參數之前執行。為什麼?
裁剪的梯度會饋入 AdamW 的指數移動平均。如果允許尖峰流入 m & v,它會腐蝕那些運行平均值,並在尖峰後的許多步驟中減緩恢復。裁剪在 Adam 之前,將尖峰的影響限制在單一壞步驟中。
為什麼是三個核心,而不是一個?
無剪切如何摧毀 v1
盜賊來源每 7 到 42 步驟轉換一次
ANDREA 的盜賊分階段運作。每個階段持續 7、14、21、28 或 42 步驟(隨機選擇)。在每個階段邊界,來源權重會轉移:也許 repo-docs 從 0.1 跳到 0.6,gutenberg 從 0.4 降到 0.1,hermes3-general 從 0.5 上升到 0.7。
每次轉換都是對模型的分佈衝擊。損失會短暫激增。梯度也隨之激增:原本針對 gutenberg 風格散文的模型現在看到 repo-docs 風格的列表結構,梯度攜帶的修正訊號可能達到典型大小的 10 倍或 100 倍。
v1 失敗模式
沒有裁剪,那些 10-100 倍的梯度尖峰會流入 AdamW 的 m & v 平均值。AdamW 的平滑化意味著尖峰效應在實際壞批次之後會持續許多步驟。結合沒有權重衰減(v1 中的純 Adam),尖峰驅動的權重更新會在各階段累積,直到權重漂移到一個退化的吸引子:一個 token 的 logit 主導 softmax,採樣輸出就是那個 token,訓練上下文包含那個 token,梯度強化了那個 token。重複鎖定。
v2 穩定性
v2 加入了 max_norm = 1.0 的裁剪,同時有 AdamW & LR 預熱。對 m & v 的尖峰效應被限制;權重無法以超過 lr max_norm = 0.0003 1.0 = 0.0003 的速度每步每參數漂移。在峰值時,階段轉換仍會產生尖峰,但這些尖峰在到達優化器之前就被限制住了。
結果:v2(在資料過濾 v2.5 & v3 潤飾之後)達到了事實回憶、多段落連貫性,& 在生物學 & 訊號處理樣本上獲得 9.5/10 的外部評分。
容量-脆性耦合
相同的強盜。相同的資料。相同的超參數,除了裁剪。為什麼 12M 沒有裁剪就能存活,而 120M 卻崩潰了?
兩個疊加因素:
1. 更大的權重矩陣儲存更多吸引子。 一個 768x768 的注意力投影有 590K 個參數;即使是每個參數的小漂移,也會產生注意力行為的有意義變化。一個 384x384 的注意力投影有 147K 個參數,並停留在更受限的子空間中。
2. 更多層數意味著更多乘法交互作用。 v3 有 12 個 transformer 層(相對於 12M 的 6 個)。峰值會通過 12 層疊加非線性作用傳播;每一層都能放大前一層的漂移。
脆性隨著容量疊加。超過某個規模閾值後,裁剪變得必要;ANDREA 將該閾值置於 12M 與 120M 參數之間。
診斷 v1 級聯效應
剪裁還適用於何處?
相關活動
三個相關活動連結到 clipping:
- 活動 10: AdamW。 Clipping 保護 AdamW 的 m 和 v 免受激增污染。沒有 clipping,一個壞批次會腐蝕優化器狀態長達 50+ 步。
- 活動 11: LR warmup。 Warmup 抑制 lr;clipping 抑制 g。結合使用:在第 1 步,最壞情況下的參數更新為 lr_after_warmup max_norm = 1.5e-7 1.0 = 1.5e-7,相較於沒有任一保護措施的 0.0003 * 50 = 0.015。最壞情況下早期更新幅度減少 100,000 倍。
- 活動 14:多臂老虎機。 老虎機階段長度(7 至 42 步)特別設計得較短,以防止任何單一來源主導;裁剪正是使那些頻繁轉換安全的關鍵。
裁剪是 Transformer 訓練中最划算的穩定性勝利:3 個小型 CUDA 核心,每步微秒級,決定了 120M+ 模型是收斂還是崩潰。