如何從頭開始編寫LoRA代碼,這有一份教程
LoRA(Low-Rank Adaptation)作為一種用于微調(diào) LLM(大語言模型)的流行技術(shù),最初由來自微軟的研究人員在論文《 LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 》中提出。不同于其他技術(shù),LoRA 不是調(diào)整神經(jīng)網(wǎng)絡(luò)的所有參數(shù),而是專注于更新一小部分低秩矩陣,從而大大減少了訓(xùn)練模型所需的計(jì)算量。
由于 LoRA 的微調(diào)質(zhì)量與全模型微調(diào)相當(dāng),很多人將這種方法稱之為微調(diào)神器。自發(fā)布以來,相信很多人都對這項(xiàng)技術(shù)感到好奇,想要從頭開始編寫代碼從而更好的理解該研究。以前苦于沒有合適的文檔說明,現(xiàn)在,教程來了。
這篇教程的作者是知名機(jī)器學(xué)習(xí)與 AI 研究者 Sebastian Raschka,他表示在各種有效的 LLM 微調(diào)方法中,LoRA 仍然是自己的首選。為此,Sebastian 專門寫了一篇博客《Code LoRA From Scratch》,從頭開始構(gòu)建 LoRA,在他看來,這是一種很好的學(xué)習(xí)方法。
簡單來說,本文通過從頭編寫代碼的方式來介紹低秩自適應(yīng)(LoRA),實(shí)驗(yàn)中 Sebastian 對 DistilBERT 模型進(jìn)行了微調(diào),并用于分類任務(wù)。
LoRA 與傳統(tǒng)微調(diào)方法的對比結(jié)果顯示,使用 LoRA 方法在測試準(zhǔn)確率上達(dá)到了 92.39%,這與僅微調(diào)模型最后幾層相比(86.22% 的測試準(zhǔn)確率)顯示了更好的性能。
Sebastian 是如何實(shí)現(xiàn)的,我們接著往下看。
從頭開始編寫 LoRA
用代碼的方式表述一個(gè) LoRA 層是這樣的:
其中,in_dim 是想要使用 LoRA 修改的層的輸入維度,與此對應(yīng)的 out_dim 是層的輸出維度。代碼中還添加了一個(gè)超參數(shù)即縮放因子 alpha,alpha 值越高意味著對模型行為的調(diào)整越大,值越低則相反。此外,本文使用隨機(jī)分布中的較小值來初始化矩陣 A,并用零初始化矩陣 B。
值得一提的是,LoRA 發(fā)揮作用的地方通常是神經(jīng)網(wǎng)絡(luò)的線性(前饋)層。舉例來說,對于一個(gè)簡單的 PyTorch 模型或具有兩個(gè)線性層的模塊(例如,這可能是 Transformer 塊的前饋模塊),其前饋(forward)方法可以表述為:
在使用 LoRA 時(shí),通常會(huì)將 LoRA 更新添加到這些線性層的輸出中,又得到代碼如下:
如果你想通過修改現(xiàn)有 PyTorch 模型來實(shí)現(xiàn) LoRA ,一種簡單方法是將每個(gè)線性層替換為 LinearWithLoRA 層:
以上這些概念總結(jié)如下圖所示:
為了應(yīng)用 LoRA,本文將神經(jīng)網(wǎng)絡(luò)中現(xiàn)有的線性層替換為結(jié)合了原始線性層和 LoRALayer 的 LinearWithLoRA 層。
如何上手使用 LoRA 進(jìn)行微調(diào)
LoRA 可用于 GPT 或圖像生成等模型。為了簡單說明,本文采用一個(gè)用于文本分類的小型 BERT(DistilBERT) 模型來說明。
由于本文只訓(xùn)練新的 LoRA 權(quán)重,因而需要將所有可訓(xùn)練參數(shù)的 requires_grad 設(shè)置為 False 來凍結(jié)所有模型參數(shù):
接下來,使用 print (model) 檢查一下模型的結(jié)構(gòu):
由輸出可知,該模型由 6 個(gè) transformer 層組成,其中包含線性層:
此外,該模型有兩個(gè)線性輸出層:
通過定義以下賦值函數(shù)和循環(huán),可以選擇性地為這些線性層啟用 LoRA:
使用 print (model) 再次檢查模型,以檢查其更新的結(jié)構(gòu):
正如上面看到的,線性層已成功地被 LinearWithLoRA 層取代。
如果使用上面顯示的默認(rèn)超參數(shù)來訓(xùn)練模型,則會(huì)在 IMDb 電影評論分類數(shù)據(jù)集上產(chǎn)生以下性能:
- 訓(xùn)練準(zhǔn)確率:92.15%
- 驗(yàn)證準(zhǔn)確率:89.98%
- 測試準(zhǔn)確率:89.44%
在下一節(jié)中,本文將這些 LoRA 微調(diào)結(jié)果與傳統(tǒng)微調(diào)結(jié)果進(jìn)行了比較。
與傳統(tǒng)微調(diào)方法的比較
在上一節(jié)中,LoRA 在默認(rèn)設(shè)置下獲得了 89.44% 的測試準(zhǔn)確率,這與傳統(tǒng)的微調(diào)方法相比如何?
為了進(jìn)行比較,本文又進(jìn)行了一項(xiàng)實(shí)驗(yàn),以訓(xùn)練 DistilBERT 模型為例,但在訓(xùn)練期間僅更新最后 2 層。研究者通過凍結(jié)所有模型權(quán)重,然后解凍兩個(gè)線性輸出層來實(shí)現(xiàn)這一點(diǎn):
只訓(xùn)練最后兩層得到的分類性能如下:
- 訓(xùn)練準(zhǔn)確率:86.68%
- 驗(yàn)證準(zhǔn)確率:87.26%
- 測試準(zhǔn)確率:86.22%
結(jié)果顯示,LoRA 的表現(xiàn)優(yōu)于傳統(tǒng)微調(diào)最后兩層的方法,但它使用的參數(shù)卻少了 4 倍。微調(diào)所有層需要更新的參數(shù)比 LoRA 設(shè)置多 450 倍,但測試準(zhǔn)確率只提高了 2%。
優(yōu)化 LoRA 配置
前面講到的結(jié)果都是 LoRA 在默認(rèn)設(shè)置下進(jìn)行的,超參數(shù)如下:
假如用戶想要嘗試不同的超參數(shù)配置,可以使用如下命令:
不過,最佳超參數(shù)配置如下:
在這種配置下,得到結(jié)果:
- 驗(yàn)證準(zhǔn)確率:92.96%
- 測試準(zhǔn)確率:92.39%
值得注意的是,即使 LoRA 設(shè)置中只有一小部分可訓(xùn)練參數(shù)(500k VS 66M),但準(zhǔn)確率還是略高于通過完全微調(diào)獲得的準(zhǔn)確率。
原文鏈接:https://lightning.ai/lightning-ai/studios/code-lora-from-scratch?cnotallow=f5fc72b1f6eeeaf74b648b2aa8aaf8b6