要把一個上百億參數的大型語言模型調整成貼合自家任務的樣子,傳統做法是全參數微調(full fine-tuning),也就是把整個模型的每一個權重都拿出來重新訓練。這個做法效果好,但代價驚人:訓練 GPT-3 等級的 175B 模型,光是把權重、梯度與最佳化器狀態全塞進顯存,就需要好幾張 A100 才夠;每微調一個任務,又得存下一份完整的模型副本。LoRA 與整個 PEFT(Parameter-Efficient Fine-Tuning,參數高效微調)家族,正是為了打破這道成本高牆而生——它們的核心洞見是:適配一個既有的大模型,其實不需要動到那麼多參數。理解這套方法,是今天任何想把開源模型客製化的人都繞不開的一課。
📖 學
全參數微調為何愈來愈負擔不起
一個模型的參數量決定了微調的三重成本。第一重是顯存:訓練時除了模型權重本身,還要為每個參數保存梯度,以及 Adam 這類最佳化器所需的動量與方差狀態,後者往往佔用比權重本身還多的空間。以 FP16 訓練一個 7B 模型為例,光權重就約 14GB,加上梯度與最佳化器狀態,總需求輕易衝破 60GB,遠超單張消費級顯示卡的容量。第二重是儲存:每個下游任務都產生一份與基座同樣大的權重檔,十個任務就是十份完整副本,部署與版本管理極為笨重。第三重是切換成本:線上服務若要同時支援多種任務,載入與卸載整份模型的開銷讓多租戶場景幾乎不可行。
這些成本催生了一個關鍵問題:微調時模型到底「學到了多少新東西」?研究者觀察到,把預訓練模型適配到特定任務時,權重的「更新量」其實具有很低的內在維度(intrinsic dimension)。換句話說,那個代表「從通用模型變成任務專用模型」的權重變化矩陣 ΔW,雖然形狀跟原權重一樣龐大,但它真正承載的資訊卻可以用低秩結構近似。這正是 LoRA 的理論起點。
LoRA 的核心:把更新分解成兩個低秩矩陣
LoRA(Low-Rank Adaptation,低秩適配)由 Edward Hu 等人在 2021 年提出(arXiv:2106.09685)。它的做法優雅而簡單:凍結預訓練模型的原始權重 W₀,完全不動它;真正要學的權重更新 ΔW,則被分解成兩個小矩陣的乘積 ΔW = B × A。假設原權重 W₀ 的形狀是 d×d(例如 4096×4096),傳統微調要訓練整個 d×d 的更新;而 LoRA 讓 A 的形狀是 r×d、B 的形狀是 d×r,其中 r(秩,rank)是一個遠小於 d 的數字,常見取值是 8、16、32、64。
這個分解帶來的參數縮減是數量級的。以 d=4096、r=8 為例,全參數更新需要 4096×4096 ≈ 1678 萬個參數;而 LoRA 只需 A 的 8×4096 加上 B 的 4096×8,合計約 6.5 萬個參數,不到原本的 0.4%。前向傳播時,模型的輸出變成 h = W₀x + BAx,也就是原始權重的輸出再加上低秩路徑的貢獻。訓練時只有 A 與 B 有梯度、需要最佳化器狀態,凍結的 W₀ 完全不佔用這些額外空間,顯存需求因此大幅下降。
一個實作上的巧思是初始化:A 用隨機高斯分布初始化,B 則初始化為全零。這樣一來訓練開始的第一步 BA = 0,模型的行為與原始預訓練模型完全一致,不會因為隨機擾動而破壞基座已學到的能力,訓練過程也更穩定。
rank 與 alpha:兩個關鍵超參數
rank(秩 r)控制低秩路徑的「容量」。r 越大,A 與 B 能表達的更新越豐富,理論上能捕捉更複雜的任務適配,但參數量與顯存也隨之增加,且過大的 r 有過擬合風險,甚至失去低秩近似的效率優勢。實務上多數任務用 r=8 到 r=16 就有不錯效果;需要學習大量新知識或風格差異很大的任務,才需要往 r=64 甚至更高調。值得注意的是,論文的一個重要發現是:即使 r 很小(例如 r=1 或 r=2),LoRA 在許多任務上仍能逼近全參數微調的表現,這強力佐證了權重更新確實是低秩的。
alpha(縮放係數 α)則控制低秩路徑對輸出的影響強度。實際計算時,BAx 這一項會乘上一個縮放因子 α/r。這個設計的用意是:當你調整 r 時,不必連帶重新調整學習率,因為縮放會自動補償 r 變化帶來的量級差異。常見的經驗法則是把 α 設為 r 的兩倍(例如 r=8 配 α=16),但這只是起點而非鐵律,實務中 α 與學習率需要一起搭配調整。可以把 α/r 理解成一個「音量旋鈕」:太小則適配不足、模型學不進新任務,太大則可能蓋過基座能力、造成訓練不穩。
QLoRA:4-bit 量化基座再疊 LoRA
QLoRA 由 Dettmers 等人在 2023 年提出(arXiv:2305.14314),把省顯存這件事推到了新的極限。它的組合拳是:先把凍結的基座模型量化成 4-bit,再在這個 4-bit 基座上訓練 LoRA 適配器。因為基座本身佔的顯存被壓縮成約四分之一,而它反正是凍結不訓練的,量化帶來的精度損失可以透過 LoRA 的可訓練參數來補償。這讓 QLoRA 能在單張 48GB 顯示卡上微調 65B 參數的模型——這在過去是要好幾張高階卡才辦得到的事。
QLoRA 有三個技術支柱。第一是 4-bit NormalFloat(NF4),一種專為常態分布資料設計的量化資料型別;神經網路權重通常近似常態分布,NF4 在資訊理論上對這類分布是最佳配置,精度優於一般的 4-bit 浮點。第二是雙重量化(double quantization),連量化過程本身產生的量化常數也再量化一次,進一步榨出每個參數約 0.4 bit 的空間。第三是分頁最佳化器(paged optimizers),利用 NVIDIA 統一記憶體機制,在顯存尖峰時把最佳化器狀態暫存到 CPU 記憶體,避免爆顯存導致訓練中斷。訓練時,梯度會反向傳播穿過凍結的 4-bit 基座,流入 LoRA 適配器;運算的當下權重會反量化回較高精度來計算,但不需長期保存這份高精度副本。這套整合已在 Hugging Face 的 PEFT、transformers 與 bitsandbytes 函式庫中原生支援。
PEFT 家族:LoRA 之外還有這些選擇
LoRA 只是 PEFT 這個大家族的成員之一,理解它的兄弟方法有助於看清設計光譜。Adapter(適配器)是更早期的路線:在 Transformer 每一層之間插入小型的瓶頸式神經網路模組,只訓練這些新增模組。它有效,但因為是「串接」在主幹上,推論時會增加額外的前向計算,帶來延遲——這正是 LoRA 刻意避開的問題,因為 LoRA 的 BA 可以在部署時直接合併回 W₀。
Prefix-tuning(前綴微調)與 Prompt-tuning(提示微調)走的是另一條路:不改動模型權重,而是在輸入序列前面加上一串可訓練的「虛擬 token」向量,讓模型透過這些學來的前綴去引導生成方向。它們的可訓練參數更少,但通常在複雜任務上的表達力不如 LoRA,且會佔用一部分寶貴的上下文長度。此外還有 IA³ 這類方法,透過學習少量縮放向量去逐元素調整內部激活值。整體而言,LoRA 之所以成為當前主流,是因為它在參數效率、表達能力與零推論延遲(可合併)三者間取得了最好的平衡。
可插拔的多 LoRA:一個基座,無限分身
LoRA 適配器體積極小的特性,催生了強大的部署彈性。一個訓練好的 LoRA 檔案通常只有幾 MB 到幾十 MB,相較於動輒數十 GB 的完整模型微不足道。這意味著你可以在同一個基座模型上,掛載數十甚至上千個針對不同任務、不同風格、不同客戶訓練的 LoRA,像換鏡頭一樣即時切換。線上服務端更有 S-LoRA 這類技術,能在單一 GPU 上同時服務數千個並發的 LoRA 適配器,把基座模型的權重共享到極致,每個請求只需帶上自己那份輕巧的適配器。
這種可插拔性還帶來運維上的好處:更新某個任務的能力時,只需重新訓練並替換對應的小適配器,基座完全不動,版本管理清爽。部署時你有兩種選擇——若追求零額外延遲,可以把 LoRA 合併回基座得到一份獨立模型;若追求靈活切換,則保持適配器獨立、動態載入。這種「一個底座、無數分身」的架構,是全參數微調在成本上完全無法企及的。
與全參數微調的取捨,以及何時該用
LoRA 並非全參數微調的完美替代品,而是一組明確的權衡。優勢面:顯存需求大降(常見可省 3 倍以上,配合 QLoRA 更多)、儲存極省、訓練更快、可插拔多任務、且因為凍結基座而較不容易發生災難性遺忘(catastrophic forgetting)。代價面:當任務需要模型學習大量全新知識、或與預訓練分布差異極大時,低秩約束可能成為天花板,此時全參數微調仍有小幅但實在的性能優勢;此外 rank、alpha、要對哪些層(通常是注意力的 query/value 投影,有時擴及全部線性層)加 LoRA,都需要一定的調參經驗。
實務上的選擇原則大致如此:資源有限、任務是「風格對齊」或「領域適配」而非「注入海量新知」、需要同時維護多個任務版本、或想在單張消費級顯卡上作業——這些情境幾乎都該首選 LoRA 或 QLoRA。反之,若你有充裕算力、追求極致單任務性能、且該任務與基座能力落差極大(例如讓通用模型學會全新語言或高度專門的領域推理),則全參數微調仍值得考慮。對絕大多數團隊而言,LoRA/QLoRA 已經是把開源模型客製化的預設起手式,先用它跑出堪用結果,只有在確認低秩容量成為瓶頸時,才升級到更重的做法。
🧠 記
- LoRA 凍結原始權重 W₀,只訓練把更新量 ΔW 分解出的兩個低秩矩陣 A、B,前向為 h = W₀x + BAx。
- rank(r)控制低秩路徑容量,常用 8/16/32/64;論文發現即使 r 極小,多數任務仍能逼近全參數微調。
- alpha(α)透過 α/r 縮放低秩路徑影響力,經驗上常設為 r 的兩倍,需與學習率一起調。
- 初始化時 A 用高斯、B 設為零,使訓練起點 BA=0、行為等同原模型,確保穩定不破壞基座。
- QLoRA = 4-bit 量化凍結基座 + LoRA,三支柱為 NF4、雙重量化、分頁最佳化器,可在單張 48GB 卡微調 65B 模型。
- PEFT 家族還有 Adapter(插入瓶頸模組、有推論延遲)、Prefix/Prompt-tuning(訓練虛擬前綴、佔上下文)、IA³ 等。
- LoRA 適配器僅數 MB,可在同一基座上掛載大量適配器即時切換(如 S-LoRA 服務數千並發)。
- 取捨:LoRA 省顯存/儲存、抗遺忘、可插拔;但學海量新知或分布差異極大時,全參數微調仍略勝一籌。
✍️ 實踐
- 用 Hugging Face 的
peft套件對一個 7B 開源模型(如 Llama 或 Mistral)設定LoraConfig,指定r=8、lora_alpha=16,先跑通一次最小微調流程。 - 固定其他條件,分別以 r=4、8、16、32 各訓練一輪,記錄驗證集表現與顯存佔用,親眼觀察「低秩就夠用」的臨界點在哪。
- 開啟
load_in_4bit=True搭配 bitsandbytes 走 QLoRA 路線,對照同一模型 LoRA 與 QLoRA 的顯存差異,確認能否塞進你手邊的顯卡。 - 針對兩個不同任務各訓練一個 LoRA 適配器,實作在同一基座上動態載入/卸載,體驗可插拔多任務的切換流程。
- 把訓練好的 LoRA 用
merge_and_unload()合併回基座,比較合併前後的推論延遲,理解「零額外延遲」部署選項的實際差異。 - 針對一個明顯需要新知識的任務(例如特定專業領域問答),同時跑 LoRA 與一次小規模全參數微調,量化兩者性能差距,培養「何時該升級」的判斷力。
🔗 延伸學習
- LoRA: Low-Rank Adaptation of Large Language Models (arXiv:2106.09685)
- QLoRA: Efficient Finetuning of Quantized LLMs (arXiv:2305.14314)
- Hugging Face PEFT 量化文件
- Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA
💬 問 AI
我想把一個開源大型語言模型微調成貼合我任務的版本,請幫我判斷該用哪種 PEFT 方法。
我的情況:
- 基座模型與參數量:【待填,例如 Llama-3 8B】
- 可用硬體:【待填,例如單張 RTX 4090 24GB】
- 任務性質:【待填,例如客服風格對齊 / 特定領域問答 / 注入新知識】
- 資料量與是否需同時維護多個任務版本:【待填】
請提供三點:
1. 建議用 LoRA、QLoRA 還是全參數微調,並說明理由與取捨。
2. 給出具體的起始超參數(rank、alpha、學習率、要加 LoRA 的層)與大致顯存估算。
3. 列出可能的失敗徵兆(如欠擬合、災難性遺忘)與對應的調整方向。