從原理到調(diào)參,小白也能讀懂的大模型微調(diào)LoRA,不懂線性代數(shù)也沒(méi)問(wèn)題 原創(chuàng)
身為一名AI工程師,我過(guò)去的工作主要集中在應(yīng)用層開(kāi)發(fā),對(duì)算法的理解并不深入。然而,近期我開(kāi)始對(duì)算法產(chǎn)生了濃厚的興趣,并轉(zhuǎn)向研究模型微調(diào)。在眾多微調(diào)算法中,Lora以其普遍應(yīng)用引起了我的關(guān)注,我計(jì)劃在本文中對(duì)它進(jìn)行詳細(xì)介紹。將Lora僅僅視為一種算法可能并不準(zhǔn)確,它更像是一種精妙的技巧或策略。下文將圍繞幾個(gè)核心問(wèn)題,全面探討和解析Lora技術(shù),希望這些內(nèi)容能為對(duì)模型微調(diào)感興趣的你提供有用的參考和幫助。
Lora是什么
假設(shè)大模型的原始的權(quán)重矩陣w是:
全量微調(diào)需要更新 5 * 4 = 20個(gè)參數(shù),假設(shè)微調(diào)后的參數(shù)是:
這個(gè)可以轉(zhuǎn)化為:
其中ΔW 可以分解為
- 矩陣 ( A ):尺寸 ( 5 * 2 ),共10個(gè)參數(shù)
- 矩陣 ( B ):尺寸 ( 2 * 4 ),共8個(gè)參數(shù)
- LoRA總參數(shù):( 10 + 8 = 18 ) 個(gè)
也就是說(shuō)通過(guò)LoRA微調(diào),調(diào)參對(duì)象從 W 變?yōu)?A、B,使得參數(shù)量從20個(gè)減少為18個(gè),這是簡(jiǎn)化的例子。在實(shí)際案例中,參數(shù)量可以減少為0.01%~3%左右。
為什么需要LoRA
LoRA最早出現(xiàn)在2021年由微軟研究院提出的一篇論文中(《LoRA: Low-Rank Adaptation of Large Language Models》),LoRA的核心思路是:與其每次都復(fù)制整個(gè)模型,不如只調(diào)整一小部分參數(shù),把成本降下來(lái)。它的目標(biāo)是解決大模型微調(diào)中的兩大痛點(diǎn):
- 資源消耗太大:大型語(yǔ)言模型動(dòng)輒幾億甚至幾千億參數(shù),全參數(shù)微調(diào)需要為每個(gè)新任務(wù)保存一份完整的模型副本。比如,一個(gè)10億參數(shù)的模型,假設(shè)每個(gè)參數(shù)用4字節(jié)(float32),光存儲(chǔ)就得4GB。多個(gè)任務(wù)下來(lái),硬盤(pán)和顯存都吃不消。
- 訓(xùn)練效率低下:全參數(shù)微調(diào)不僅占空間,還需要大量計(jì)算資源和時(shí)間。每次訓(xùn)練都得更新所有參數(shù)。
LoRA的核心亮點(diǎn)
- 參數(shù)少
- 在GPT-3上,?
?r = 8?
?的LoRA參數(shù)量占全微調(diào)的0.01%-0.1%,性能卻達(dá)到全微調(diào)的95%-99%。 - 在GLUE任務(wù)(BERT),?
?r = 16?
?的LoRA用0.1%參數(shù),平均得分僅比全微調(diào)低0.5-1分。 - 它只微調(diào)原始參數(shù)的1%甚至更少。
- 速度快
- 訓(xùn)練和部署都比全參數(shù)微調(diào)省時(shí)省力。
- 模塊化
- 訓(xùn)練好的LoRA“插件”可以隨時(shí)加載或卸載,不影響原始模型,特別適合多任務(wù)場(chǎng)景。
模塊化設(shè)計(jì)的優(yōu)點(diǎn)
- 避免災(zāi)難性遺忘
直接修改???W?
?? 可能導(dǎo)致模型在新任務(wù)上表現(xiàn)良好,但在原始任務(wù)上性能下降(即“災(zāi)難性遺忘”)。LoRA通過(guò)凍結(jié)核心??W?
?,保留了原始模型的能力。 - 存儲(chǔ)高效
一個(gè)大模型可以搭配多個(gè)LoRA模塊,每個(gè)模塊只占用MB級(jí)空間,相比全模型微調(diào)動(dòng)輒幾GB,節(jié)省顯著。 - 快速切換任務(wù)
任務(wù)切換只需加載不同LoRA文件,幾秒鐘搞定,不用重新訓(xùn)練。 - 兼容性強(qiáng)
原始模型完全不動(dòng),多個(gè)團(tuán)隊(duì)可以共享同一個(gè)基礎(chǔ)模型,只開(kāi)發(fā)自己的LoRA模塊。
為什么可以對(duì)增量權(quán)重 ΔW 低秩分解?
低秩分解的核心思想是:矩陣?yán)锏男畔⑼皇蔷鶆蚍植嫉?,很多維度是冗余的,只需要抓住"主要方向"就夠了。
1. 什么是矩陣的秩(Rank)?
在線性代數(shù)中,一個(gè)矩陣的秩(rank)是它的線性獨(dú)立行或列的數(shù)量。如果一個(gè)矩陣是"低秩"的,意味著它的信息可以用少量獨(dú)立方向表達(dá),而不是需要完整的維度。
比如下述矩陣,第5行 ??[1, 2, 0, 3, 0]?
?? 是第1行 ??[1, 0, 0, 2, 0]?
?? 和第2行 ??[0, 2, 0, 1, 0]?
? 的線性組合(第5行=第1行+第2行),第5行沒(méi)有提供更多的信息,理論上這個(gè)矩陣有前4行就能提供所有信息了,因此矩陣的行秩為4(列秩也為4,第5列全為0,沒(méi)有信息增量)。
2. 低秩分解的原理
奇異值分解(SVD)可以把任意矩陣分解成三個(gè)矩陣的乘積。對(duì)于一個(gè)形狀 ( d * k ) 的矩陣 ( W ),SVD可以寫(xiě)成:
- ( U ) 是 ( d * d ) 的正交矩陣
- (Σ ) 是 ( d * k ) 的對(duì)角矩陣(奇異值按降序排列)
- ( V^T ) 是 ( k * k ) 的正交矩陣(( V ) 的轉(zhuǎn)置)
其中 ( r ) 是矩陣的秩(非零奇異值的數(shù)量)。通過(guò)保留前 ( r ) 個(gè)最大的奇異值(低秩近似),可以用更少的參數(shù)近似原矩陣 ( W )。
任意矩陣(無(wú)論是實(shí)數(shù)還是復(fù)數(shù)、方陣還是非方陣、滿秩還是不滿秩)都可以通過(guò)奇異值分解(SVD)精確拆分為三個(gè)特定矩陣的乘積
舉個(gè)例子,針對(duì)上述矩陣 ( S ) 的SVD分解(計(jì)算過(guò)程略):
如果只保留前三個(gè)奇異值(7.03, 3, 2.15),重構(gòu)后的矩陣 ( S' ) 與原矩陣 ( S ) 幾乎一致(三個(gè)矩陣分別取前三列,前三行&前三列,前三行):
結(jié)果對(duì)比原始矩陣和重構(gòu)矩陣,直觀上來(lái)看,基本保持一致,這就是說(shuō):如果只保留最大的幾個(gè)奇異值,就能用更少的參數(shù)近似表示w。
3. 為什么可以對(duì)增量權(quán)重 ΔW 低秩分解?
研究發(fā)現(xiàn):
- 信息集中性:微調(diào)后的權(quán)重變化 ( ΔW) 的奇異值分布中,前10-20個(gè)奇異值占據(jù)了90%以上的信息(LoRA論文在GPT-3上的實(shí)驗(yàn)結(jié)論)。
- 結(jié)構(gòu)化特性:(ΔW ) 的變化不是隨機(jī)的,而是集中在少數(shù)"任務(wù)相關(guān)方向"上(例如讓模型學(xué)習(xí)法律術(shù)語(yǔ)只需調(diào)整少量語(yǔ)義方向)。
- 高效近似:直接用低秩矩陣 ( A * B ) 構(gòu)造 (ΔW ),無(wú)需完整SVD計(jì)算,參數(shù)量從 ( d * k ) 降至 ( (d + k) * r )。
直觀理解: 微調(diào)類似于讓一個(gè)已學(xué)會(huì)"說(shuō)話"的模型掌握某種"口音"。這種調(diào)整只需修改少數(shù)關(guān)鍵維度(如詞匯選擇),而非全部語(yǔ)言規(guī)則,因此低秩足夠。
舉個(gè)例子:
對(duì)一個(gè) ( 512 * 512 ) 的權(quán)重矩陣(262,144參數(shù)):
- 全微調(diào):更新全部262,144個(gè)參數(shù)。
- LoRA(( r=8 )):僅需 ( 512 * 8 + 8 * 512 = 8,192 ) 個(gè)參數(shù),即可捕捉主要變化。
4. 對(duì)原始權(quán)重 ( W ) 可以低秩分解嗎?
不行。預(yù)訓(xùn)練模型的權(quán)重 ( W ) 通常接近滿秩(奇異值分布平滑),低秩分解會(huì)丟失關(guān)鍵信息。而 ( ΔW ) 的秩天然較低,適合分解。
LoRA是如何更新參數(shù)的
本質(zhì)上,LoRA仍然使用反向傳播算法進(jìn)行參數(shù)更新,但僅針對(duì)新增的低秩矩陣 ( A ) 和 ( B ),而保持原始權(quán)重 ( W ) 凍結(jié)。
參數(shù)更新過(guò)程
(1)初始化
- ( W ) 使用預(yù)訓(xùn)練模型的權(quán)重,梯度計(jì)算被禁用(不更新)。
- ( A ) 用小的隨機(jī)高斯分布初始化
- ( B ) 初始化為全零矩陣,確保訓(xùn)練開(kāi)始時(shí) ( ΔW = 0 ),避免干擾原始模型。
(2)前向傳播
- 輸入數(shù)據(jù) ( X ) 通過(guò)調(diào)整后的權(quán)重計(jì)算輸出
- 根據(jù)任務(wù)目標(biāo) 計(jì)算損失函數(shù) ( L )(如交叉熵?fù)p失)。
(3)反向傳播
- 計(jì)算損失 ( L ) 對(duì) ( A ) 和 ( B ) 的梯度
- 不計(jì)算( W ) 的梯度(因其被凍結(jié))。
(4)參數(shù)更新
- 使用優(yōu)化器(如Adam)更新
(5)迭代優(yōu)化
- 重復(fù)步驟2-4,直到損失收斂或達(dá)到訓(xùn)練輪次。
- 訓(xùn)練完成后,( A ) 和 ( B ) 捕捉了任務(wù)特定的調(diào)整信息。
推理部署選項(xiàng)
- 合并權(quán)重:將 ( W' = W + A * B ) 合并為單一矩陣,直接用于推理(適合固定任務(wù))。
- 動(dòng)態(tài)加載:保持 ( W ) 和 ( A * B ) 分離,靈活切換不同任務(wù)的LoRA模塊(適合多任務(wù)場(chǎng)景)。
關(guān)鍵特點(diǎn)
- 參數(shù)高效:僅訓(xùn)練 ( A ) 和 ( B ),參數(shù)量從 ( d * k ) 降至 ( (d + k) * r )。
- 內(nèi)存節(jié)省:無(wú)需存儲(chǔ)全參數(shù)微調(diào)的梯度,顯存占用大幅降低。
- 兼容性:原始模型 ( W ) 保持不變,支持多任務(wù)共享。
LoRA可以用在Transformer的哪些層
LoRA是"好鋼要用在刀刃上"。并非模型的所有參數(shù)都需要微調(diào),選擇關(guān)鍵層進(jìn)行適配即可達(dá)到接近全參數(shù)微調(diào)的效果。LoRA目前主要可以應(yīng)用在transformer中的以下兩類層:
Transformer是谷歌在2017年推出的深度學(xué)習(xí)模型,專門(mén)處理序列數(shù)據(jù)。簡(jiǎn)單來(lái)說(shuō),序列數(shù)據(jù)就像排隊(duì)的小朋友,每個(gè)小朋友都有自己的位置和信息,Transformer能把這些信息處理得明明白白。后面有空我會(huì)專門(mén)出一個(gè)系列講解一下。
1. 注意力層(Self-Attention)
Transformer的核心是多頭注意力機(jī)制,每個(gè)注意力頭包含4個(gè)權(quán)重矩陣:
- ( W_q )(Query)
- ( W_k )(Key)
- ( W_v )(Value)
- ( W_o )(Output)
LoRA通常應(yīng)用在:
- ( W_q ) 和 ( W_v )(最高優(yōu)先級(jí)):
- 調(diào)整 ( W_q ) 可改變模型"關(guān)注哪些信息"。
- 調(diào)整 ( W_v ) 可影響"如何編碼關(guān)注的信息"。
- ( W_o )(次優(yōu)先級(jí)):
- 調(diào)整輸出投影矩陣,但收益通常不如 ( W_q ) 和 ( W_v ) 顯著。
實(shí)驗(yàn)結(jié)論(來(lái)自LoRA原論文):
- 僅微調(diào) ( W_q ) 和 ( W_v ) 即可達(dá)到全參數(shù)微調(diào)效果的90%以上。
- 添加 ( W_o ) 的LoRA對(duì)性能提升有限(<2%),但會(huì)增加參數(shù)量。
2. 前饋網(wǎng)絡(luò)層(FFN)
FFN包含兩個(gè)線性變換:
- ( W_1 ):升維(通常放大4倍,如d_model → 4×d_model)
- ( W_2 ):降維(4×d_model → d_model)
適用場(chǎng)景:
- 大模型(如GPT-3):添加FFN層的LoRA可進(jìn)一步提升性能。
- 復(fù)雜生成任務(wù):調(diào)整FFN能增強(qiáng)任務(wù)特定的特征表達(dá)。
不推薦使用LoRA的層
(1)嵌入層(Embedding):
- 參數(shù)量大但微調(diào)收益低,凍結(jié)可節(jié)省資源。
(2)LayerNorm/Bias:
- 參數(shù)少,直接全參數(shù)微調(diào)成本低。
- LayerNorm的縮放因子和偏置本身具有低秩特性,無(wú)需LoRA。
實(shí)際配置建議
模型規(guī)模 | 推薦LoRA目標(biāo)層 | 典型rank (r) |
小模型(如BERT) | 僅 ( W_q ), ( W_v ) | 8-16 |
大模型(如GPT-3) | ( W_q ), ( W_v ), FFN的 ( W_1 ) | 32-64 |
復(fù)雜生成任務(wù) | 所有注意力矩陣 + FFN | 64+ |
模塊化設(shè)計(jì)優(yōu)勢(shì)
- 任務(wù)切換:不同任務(wù)可獨(dú)立配置LoRA模塊(如翻譯任務(wù)用( W_q ), ( W_v ),摘要任務(wù)額外啟用FFN)。
- 資源分配:對(duì)關(guān)鍵層分配更高秩(如( r=32 )),次要層用低秩(如( r=8 ))。
LoRA訓(xùn)練時(shí)需要調(diào)整哪些超參數(shù)
以 LLaMA-Factory 的配置為例,說(shuō)明 LoRA 的關(guān)鍵超參數(shù)及其調(diào)參策略:
核心參數(shù)表
參數(shù)名 | 類型/范圍 | 含義 | 建議值 | 默認(rèn)值 |
? | ? | 微調(diào)類型選擇 | 必須設(shè)為 ? | ? |
? (r) | 正整數(shù) | LoRA的秩,決定矩陣A/B的列數(shù)/行數(shù) | 簡(jiǎn)單任務(wù):8-16 | 8 |
? (α) | 正整數(shù) | 縮放系數(shù),控制ΔW對(duì)原始權(quán)重W的影響強(qiáng)度 | 通常設(shè)為 ? | None |
? | 0.0-1.0 | LoRA層的Dropout概率 | 大數(shù)據(jù)集:0.0 | 0.0 |
? | 逗號(hào)分隔的字符串 | 應(yīng)用LoRA的模塊名稱(需匹配模型層名) | 默認(rèn):? | ? |
? | 逗號(hào)分隔的字符串 | 額外擴(kuò)展的LoRA目標(biāo)模塊(如FFN層) | 通常留空,大模型可加? | None |
調(diào)參技巧
- 秩(r)的選擇
- 小數(shù)據(jù)集(<5K樣本):r=8
- 大數(shù)據(jù)集(>50K樣本):r=32+
- 從小開(kāi)始:優(yōu)先嘗試r=8或16,逐步增加直至性能飽和。
- 數(shù)據(jù)量關(guān)聯(lián):
- 目標(biāo)層選擇策略
# 簡(jiǎn)單任務(wù)(如分類)
lora_target = "q_proj,v_proj"
# 復(fù)雜任務(wù)(如生成)
lora_target = "q_proj,k_proj,v_proj,o_proj,ffn.w1,ffn.w2"
3.改進(jìn)技術(shù)的適用場(chǎng)景
- LoRA+:訓(xùn)練速度要求高時(shí)啟用(設(shè)?
?lorapius_lr_ratio=8?
?)。 - DoRA:需要逼近全微調(diào)性能時(shí)開(kāi)啟(?
?use_dora=true?
?)。 - rsLoRA:當(dāng)r≥32時(shí)更穩(wěn)定(?
?use_rslora=true?
?)。
參數(shù)影響對(duì)比
超參數(shù) | 參數(shù)量影響 | 訓(xùn)練速度 | 性能影響 |
? ↑ | 線性增加 | 略微下降 | 先升后平 |
? ↑ | 無(wú)影響 | 無(wú)影響 | 調(diào)節(jié)強(qiáng)度 |
? | 增加約10% | 下降10%-20% | 提升1%-3% |
? | 無(wú)影響 | 初始化耗時(shí)增加 | 收斂更快 |
經(jīng)典配置示例
# GLUE任務(wù)(BERT-base)
lora_rank:16
lora_alpha:32
lora_target:"query,value"
lora_dropout:0.1
# GPT-3文本生成
lora_rank:64
lora_alpha:128
use_rslora:true
lora_target:"q_proj,v_proj,ffn.w1"
總結(jié)
LoRA是一種高效的大模型微調(diào)技術(shù),它通過(guò)低秩矩陣分解顯著地減少了參數(shù)量和計(jì)算資源的需求,同時(shí)又能保持接近全模型微調(diào)的性能。在接下來(lái)的文章中,我們將從實(shí)戰(zhàn)角度出發(fā),借由Llama-Factory來(lái)進(jìn)行模型微調(diào)。我希望能幫助讀者從零開(kāi)始,全面掌握模型微調(diào)的知識(shí)和技巧。
本文轉(zhuǎn)載自??AI 博物院?? 作者:longyunfeigu
