大規(guī)模語言模型高效參數微調--BitFit/Prefix/Prompt 微調系列
2018 年谷歌發(fā)布了 BERT,一經面世便一舉擊敗 11 個 NLP 任務的 State-of-the-art (Sota) 結果,成為了 NLP 界新的里程碑; BERT 的結構如下圖所示, 左邊是 BERT 模型預訓練過程, 右邊是對于具體任務的微調過程。其中, 微調 階段是后續(xù)用于一些下游任務的時候進行微調, 例如: 文本分類, 詞性標注, 問答系統(tǒng)等, BERT 無需調整結構 就可以在不同的任務上進行微調。通過”預訓練語言模型 + 下游任務微調”的任務設計, 帶來了強大的模型效 果。從此,“預訓練語言模型 + 下游任務微調”便成為了 NLP 領域主流訓練范式。
BERT 結構圖,左邊是預訓練過程,右邊是具體任務微調過程
但是, 以 GPT3 為代表的大規(guī)模語言模型(LLM) 參數規(guī)模變得越來越大, 這使得在消費級硬件上進行全量 微調變得不可行。下表展示了在一張 A100 GPU (80G 顯存) 以及 CPU 內存 64GB 以上的硬件上進行模型全量 微調以及參數高效微調對于 CPU/GPU 內存的消耗情況。
全量參數微調與參數高效微調顯存占用對比
除此之外, 模型全量微調還會損失多樣性, 存在災難性遺忘的問題。因此, 如何高效的進行模型微調就成了業(yè)界研究的重點,這也為參數高效微調技術的快速發(fā)展帶來了研究空間。
參數高效微調是指微調少量或額外的模型參數, 固定大部分預訓練模型(LLM) 參數, 從而大大降低了計 算和存儲成本, 同時, 也能實現與全量參數微調相當的性能。參數高效微調方法甚至在某些情況下比全量微調 效果更好,可以更好地泛化到域外場景。
高效微調技術可以粗略分為以下三大類,如下圖所示:增加額外參數(A)、選取一部分參數更新(S)、引入重參數化(R)。 而在增加額外參數這類方法中,又主要分為類適配器(Adapter-like)方法和軟提示(Soft prompts)兩個小類。
常見的參數高效微調技術有 BitFit 、Prefix Tuning 、Prompt Tuning 、P-Tuning 、Adapter Tuning 、LoRA 等, 后 面章節(jié)將對一些主流的參數高效微調方法進行講解。
常見的參數高效微調技術和方法
BitFit/Prefix/Prompt 微調系列
BitFit
雖然對每個任務進行全量微調非常有效, 但它也會為每個預訓練任務生成一個獨特的大型模型, 這使得很 難推斷微調過程中發(fā)生了什么變化,也很難部署,特別是隨著任務數量的增加,很難維護。
理想狀況下,我們希望有一種滿足以下條件的高效微調方法:
上述的問題取決于微調過程能多大程度引導新能力的學習以及暴露在預訓練 LM 中學到的能力。雖然, 之 前的高效微調方法 Adapter-Tuning 、Diff-Pruning 也能夠部分滿足上述的需求。一種參數量更小的稀疏的微調方 法 BitFit 可以滿足上述所有需求。
BitFit 是一種稀疏的微調方法, 它訓練時只更新 bias 的參數或者部分 bias 參數。對于 Transformer 模型而言, 凍結大部分 transformer-encoder 參數, 只更新 bias 參數跟特定任務的分類層參數。涉及到的 bias 參數有 attention 模塊中計算 query,key,value 跟合并多個 attention 結果時涉及到的bias,MLP 層中的bias,Layernormalization 層的 bias 參數,預訓練模型中的bias參數如下圖所示。
圖片
PLM 模塊代表了一個特定的 PLM 子層, 例如注意力或 FFN,圖中橙色塊表示可訓練的提示向量, 藍色 塊表示凍結的預訓練模型參數
在 Bert-Base/Bert-Large 這種模型里, bias 參數僅占模型全部參數量的 0.08%~0.09%。但是通過在 Bert-Large 模型上基于 GLUE 數據集進行了 BitFit、Adapter 和 Diff-Pruning 的效果對比發(fā)現, BitFit 在參數量遠小于Adapter、 Diff-Pruning 的情況下,效果與 Adapter 、Diff-Pruning 想當,甚至在某些任務上略優(yōu)于 Adapter 、Diff-Pruning。
通過實驗結果還可以看出, BitFit 微調結果相對全量參數微調而言, 只更新極少量參數的情況下, 在多個數 據集上都達到了不錯的效果, 雖不及全量參數微調, 但是遠超固定全部模型參數的 Frozen 方式。同時, 通過對 比 BitFit 訓練前后的參數, 發(fā)現很多 bias 參數并沒有太多變化(例如:跟計算 key 所涉及到的 bias 參數)。發(fā)現 計算 query 和將特征維度從 N 放大到 4N 的 FFN 層(intermediate) 的 bias 參數變化最為明顯, 只更新這兩類 bias 參數也能達到不錯的效果,反之,固定其中任何一者,模型的效果都有較大損失。
Prefix Tuning
在 Prefix Tuning 之前的工作主要是人工設計離散的模版或者自動化搜索離散的模版。對于人工設計的模版, 模版的變化對模型最終的性能特別敏感, 加一個詞、少一個詞或者變動位置都會造成比較大的變化。而對于自動 化搜索模版, 成本也比較高;同時, 以前這種離散化的 token 搜索出來的結果可能并不是最優(yōu)的。除此之外, 傳 統(tǒng)的微調范式利用預訓練模型去對不同的下游任務進行微調, 對每個任務都要保存一份微調后的模型權重, 一 方面微調整個模型耗時長;另一方面也會占很多存儲空間。基于上述兩點, Prefix Tuning 提出固定預訓練 LM,為LM 添加可訓練, 任務特定的前綴, 這樣就可以為不同任務保存不同的前綴, 微調成本也??; 同時, 這種 Prefix 實際就是連續(xù)可微的 Virtual Token (Soft Prompt/Continuous Prompt),相比離散的 Token ,更好優(yōu)化,效果更好。
那么 prefix 的含義是什么呢?prefix 的作用是引導模型提取 x 相關的信息, 進而更好地生成 y。例如, 我們 要做一個 summarization 的任務, 那么經過微調后, prefix 就能領悟到當前要做的是個“總結形式”的任務, 然后 引導模型去 x 中提煉關鍵信息;如果我們要做一個情感分類的任務, prefix 就能引導模型去提煉出 x 中和情感相 關的語義信息,以此類推。這樣的解釋可能不那么嚴謹,但大家可以大致體會一下 prefix 的作用。
Prefix Tuning 是在輸入 token 之前構造一段任務相關的 virtual tokens 作為 Prefix,然后訓練的時候只更新 Prefix 部分的參數,而 PLM 中的其他部分參數固定。針對不同的模型結構,需要構造不同的 Prefix:
- 針對自回歸架構模型:在句子前面添加前綴, 得到 z = [PREFIX; x; y],合適的上文能夠在固定 LM 的情況 下去引導生成下文(比如:GPT3 的上下文學習)。
- 針對編碼器-解碼器架構模型:Encoder 和 Decoder 都增加了前綴,得到 z = [PREFIX; x; PREFIX0; y]。Encoder 端增加前綴是為了引導輸入部分的編碼, Decoder 端增加前綴是為了引導后續(xù) token 的生成。
圖片
上部分的微調更新所有 Transformer 參數(紅色框),并且需要為每個任務存儲完整的模型副本。下部分 的 Prefix Tuning 凍結了 Transformer 參數并且只優(yōu)化前綴(紅色框)
該方法其實和構造 Prompt 類似, 只是 Prompt 是人為構造的“顯式”的提示, 并且無法更新參數, 而 Prefix 則是可以學習的“隱式”的提示。同時,為了防止直接更新 Prefix 的參數導致訓練不穩(wěn)定和性能下降的情況,在 Prefix 層前面加了 MLP 結構, 訓練完成后, 只保留 Prefix 的參數。除此之外, 通過消融實驗證實, 只調整 embedding 層的表現力不夠,將導致性能顯著下降,因此,在每層都加了 prompt 的參數,改動較大。
Prefix Tuning 雖然看起來方便,但也存在以下兩個顯著劣勢:
Prompt Tuning
大模型全量微調對每個任務訓練一個模型, 開銷和部署成本都比較高。同時, 離散的 prompts (指人工設計 prompts 提示語加入到模型) 方法, 成本比較高, 并且效果不太好。Prompt Tuning 通過反向傳播更新參數來學習 prompts,而不是人工設計 prompts;同時凍結模型原始權重, 只訓練 prompts 參數, 訓練完以后, 用同一個模型 可以做多任務推理。
圖片
模型調整需要為每個任務制作整個預訓練模型的特定任務副本下游任務和推理必須在分開批次。Prompt Tuning 只需要為每個任務存儲一個小的特定于任務的提示,并且使用原始預訓練模型啟用混合任務推理。
Prompt Tuning 可以看作是 Prefix Tuning 的簡化版本,它給每個任務定義了自己的 Prompt,然后拼接到數據 上作為輸入,但只在輸入層加入 prompt tokens,并且不需要加入 MLP 進行調整來解決難訓練的問題。
通過實驗發(fā)現,隨著預訓練模型參數量的增加,Prompt Tuning 的方法會逼近全參數微調的結果。同時, Prompt Tuning 還提出了 Prompt Ensembling,也就是在一個批次(Batch) 里同時訓練同一個任務的不同 prompt (即采用 多種不同方式詢問同一個問題) ,這樣相當于訓練了不同模型, 比模型集成的成本小多了。除此之外, Prompt Tuning 論文中還探討了 Prompt token 的初始化方法和長度對于模型性能的影響。通過消融實驗結果發(fā)現, 與隨機 初始化和使用樣本詞匯表初始化相比, Prompt Tuning 采用類標簽初始化模型的效果更好。不過隨著模型參數規(guī) 模的提升, 這種 gap 最終會消失。Prompt token 的長度在 20 左右時的表現已經不錯(超過 20 之后, 提升Prompt token 長度, 對模型的性能提升不明顯了),同樣的, 這個 gap 也會隨著模型參數規(guī)模的提升而減小(即對于超大 規(guī)模模型而言,即使 Prompt token 長度很短,對性能也不會有太大的影響)。