LLM

LLM 相關知識

精度 (Precision)

精度決定了用多少位元(bits)來表示一個數字,位元數越多,表示越精確,但佔用記憶體也越多。

精度類型位元數記憶體大小說明
FP3232-bit4 bytes標準單精度浮點數,訓練時最常用
FP1616-bit2 bytes半精度,速度快但範圍小
BF1616-bit2 bytesGoogle 開發,數值範圍與 FP32 相同
INT88-bit1 byte整數量化,推理常用
INT44-bit0.5 bytes極度壓縮,適合在消費級 GPU 上跑大模型

浮點數的儲存格式分三個部分:

1
符號位 (Sign) | 指數位 (Exponent) | 尾數位 (Mantissa)

FP32 (32 bytes)

1
2
符號(1位) | 指數(8位)    | 尾數(23位)
    0    | 1000 0000   | 000 0000 0000 0000 0000 0000

FP16 (16 bytes)

1
2
符號(1位) | 指數(5位) | 尾數(10位)
    0    | 1 0000   | 000 0000 00

INT8 (8 bytes)

1
0000 0010

可以看出精度越下降,代表該數字的位元也會減少,模型中的權重也是透過數值儲存,因次若使用較低精度,會造成一定程度的資訊遺漏。

舉例:2.3 2.3 為一循環小數,所以會有小數點

|精度實際儲存的值|誤差| |FP32|2.29999995231628…|約 0.000000048| |FP16|2.30078125|約 0.00078 |BF16|2.296875|約 0.003 |INT8|2|誤差 0.3(直接截斷小數!)

當模型具有數億參數時,即使原本的誤差很小,也會被放大,因此需要進行量化

量化(Quantization)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
訓練好的模型 (FP32)
        ↓ 量化
壓縮後的模型 (INT8 / INT4)
推理速度更快、記憶體更省
=============================================
原始 FP32 值:  2.3
              ↓ 乘以縮放係數 (scale factor)
INT8 儲存:    23  ← 儲存成整數
              ↓ 推理時再除回來
還原的值:     2.3  ← 盡量接近原始值

量化的兩種類型

  • PTQ (Post-Training Quantization) 模型訓練完之後才進行量化,不需要重新訓練
1
FP32 模型 → 直接轉換 → INT8/INT4 模型
  • QAT (Quantization-Aware Training) 在訓練過程中就模擬量化的誤差
1
訓練時就「假裝」自己是低精度 → 模型學會適應誤差

主流量化格式比較

格式全名主要用途特點
GGUFGPT-Generated Unified Format本地部署llama.cpp 使用,CPU 也能跑
GPTQGPT QuantizationGPU 推理精度損失小,速度快
AWQActivation-aware Weight QuantizationGPU 推理比 GPTQ 更準確
BNBQBitsAndBytes Quantization訓練/推理整合進 HuggingFace,使用方便

GGUF(最適合本地部署) 專為 llama.cpp 設計,可以在沒有強力 GPU 的情況下運行:

  1. CPU + GPU 混合運算
  2. 支援 Mac M系列晶片
  3. 量化等級多樣(Q2 到 Q8)
  4. Ollama、LM Studio 都使用這個格式

GPTQ(GPU 推理首選) 針對 每一層 做最佳化量化:

1
2
3
4
5
6
7
核心思路:
1. 把權重分成小組(group)
2. 對每組找出最佳的量化參數
3. 用 Hessian 矩陣計算哪些權重最重要
4. 重要的權重 → 誤差補償,確保精度

結果:INT4 精度接近 FP16

AWQ(目前最先進之一) GPTQ 的進化版,關鍵洞察:

1
2
3
4
5
6
7
8
不是所有權重都一樣重要!

普通權重(99%)→ 直接量化到 INT4
重要權重(1%) → 保持高精度 或 縮放保護

怎麼找重要權重?
→ 觀察「激活值(Activation)」
→ 激活值大的地方,對應的權重就是重要的

懶人包:

1
2
3
4
5
6
7
8
想在本地跑模型(Mac / 普通電腦)
        → 用 GGUF + Ollama 或 LM Studio

想在 GPU 伺服器上快速推理
        → 用 GPTQ 或 AWQ

想邊訓練邊省記憶體
        → 用 BitsAndBytes(4-bit / 8-bit)

微調 (QLoRA)

1. 為什麼需要 QLoRA?

全量微調(Full Fine-tuning)需要更新模型所有權重,對於數十億參數的 LLM 來說,所需的 GPU 記憶體遠超過一般硬體能負擔。

QLoRA 的目標是:在消費級 GPU 上也能微調大型模型,例如在單張 RTX 4090 上微調 13B 模型。


2. QLoRA 的兩個核心概念

QLoRA = Quantization(量化)+ Low Rank Adaptation(低秩適應)

2-1. 量化(Quantization)

將 Base Model 的權重從 BF16 壓縮為 INT4,大幅節省記憶體。

1
BF16 權重(原始)→ 量化 → INT4 權重(凍結,不參與訓練)
  • INT4 代表每個數值只用 4 個 bit 儲存
  • 量化後精度會有損失,但這個損失在量化時就已接受

2-2. LoRA(低秩適應)

不直接修改原始權重,而是在旁邊外掛兩個小矩陣 A 和 B,只訓練這兩個矩陣。

1
2
3
4
5
原始權重 W(凍結)
        +
LoRA 矩陣:ΔW = A × B(可訓練,BF16)
實際效果 = W + ΔW

3. LoRA 的核心假設

微調時,權重的更新量 ΔW 本身就是低秩的

代表模型學習新任務所需的「調整方向」很少,不需要動到整個高維度的權重矩陣。

低秩分解的意義

1
2
3
4
5
6
原始 ΔW:4096 × 4096 = 16,777,216 個參數

改用低秩分解(r = 16):
  A:4096 × 16
  B:16 × 4096
  合計:131,072 個參數(省了 128 倍)

4. 兩個部分的分工

部分格式是否訓練目的
Base Model 權重INT4❌ 凍結節省記憶體
LoRA 矩陣(A、B)BF16✅ 訓練學習新知識

5. 動態反量化(Dynamic Dequantization)

前向傳播時,INT4 的 Base Model 不是直接用 INT4 做計算,而是逐層、即時還原成 BF16:

1
2
3
4
5
6
7
8
9
進入第 N 層
INT4 權重 → 暫時還原成 BF16(動態反量化)
做矩陣乘法
還原的 BF16 權重立刻丟棄(不常駐記憶體)
進入第 N+1 層 → 重複同樣流程

為什麼逐層而非一次全部還原? 若一次全部還原,記憶體用量等同直接載入 BF16 模型,失去量化省記憶體的意義。


6. LoRA 插入的位置

Transformer 每一層的結構

1
2
3
4
5
6
7
8
9
Transformer Layer
  ├─ Self-Attention
  │     ├─ Wq(Query)
  │     ├─ Wk(Key)
  │     ├─ Wv(Value)
  │     └─ Wo(Output)
  └─ FFN
        ├─ W_up
        └─ W_down

LoRA 掛載位置的選擇

設定插入位置
保守Wq、Wv
常見(推薦)Wq、Wk、Wv、Wo
激進Attention 全部 + FFN
  • LoRA 每一層 Transformer 都會掛,不是只有最後一層
  • Attention 負責調整「關注模式」,FFN 負責儲存知識
  • 需要注入大量新知識時,才需要在 FFN 加 LoRA

為什麼 Wo 也需要加?

Attention 使用 Multi-Head 機制,每個 Head 各自運算後 Concat 在一起,Wo 負責整合所有 Head 的結果並壓回原始維度。若只調整 Wq/Wk/Wv 而不調整 Wo,新學到的關注模式無法被有效傳遞。


7. 超參數 r(秩)

r 決定 LoRA 矩陣的維度大小,代表「給模型可以調整的方向數量」。

情境建議 r
風格、語氣調整8 ~ 16
特定領域知識注入16 ~ 64
複雜指令、多任務64 ~ 128

r = 16 是穩健的起點。

問題說明
r 太小學習空間不足,任務能力不足
r 太大接近全量微調,失去省資源優勢,可能過擬合

8. LoRA 的合併(Merge)

為什麼要合併?

若不合併,推論時每層都要分別計算 Base 輸出和 LoRA 輸出再相加,速度較慢。

合併的數學

1
W_new = W_original + A × B

合併後 A、B 矩陣可以丟棄,只保留 W_new。

合併流程(因 INT4 無法直接與 BF16 相加)

1
2
3
4
5
6
7
INT4 權重
  ↓ 反量化
BF16 權重
BF16 + (A × B) = W_new(BF16)
  ↓ 視需求
重新量化為 INT4(用於部署)

也可以選擇不合併的情境

  • 同一個 Base Model 需要切換多個 LoRA(不同任務)
  • 仍在持續微調階段
  • 快速實驗比較不同 LoRA 效果

9. QLoRA 完整生命週期

1
2
3
4
5
6
7
8
9
原始 BF16 模型
  ↓ 量化
INT4 Base Model(凍結)
  ↓ 掛上 LoRA 矩陣(BF16)
  ↓ 微調訓練(只更新 LoRA)
  ↓ 反量化 + 合併 LoRA
合併後 BF16 模型
  ↓ 重新量化
部署用 INT4 模型

10. 精度選擇總結

階段格式原因
推論(Inference)INT4、GGUF 等省記憶體、加速
微調 Base ModelINT4(凍結)省記憶體
微調 LoRA 矩陣BF16梯度計算需要足夠精度
合併後部署INT4 / GGUF重新量化以節省資源

精度損失只發生在往下降的時候,往上升不會新增損失,只是無法找回已丟失的資訊。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy