前言
微調(diào)是指調(diào)整大型語言模型(LLM)的參數(shù)以適應特定任務的過程。這是通過在與任務相關的數(shù)據(jù)集上訓練模型來完成的。所需的微調(diào)量取決于任務的復雜性和數(shù)據(jù)集的大小。
在深度學習中,微調(diào)是一種重要的技術(shù),用于改進預訓練模型的性能。除了微調(diào)ChatGPT之外,還有許多其他預訓練模型可以進行微調(diào)。
PEFT是什么
PEFT(Parameter-Efficient Fine-Tuning)是hugging face開源的一個參數(shù)高效微調(diào)大模型的工具,里面集成了4種微調(diào)大模型的方法,可以通過微調(diào)少量參數(shù)就達到接近微調(diào)全量參數(shù)的效果,使得在GPU資源不足的情況下也可以微調(diào)大模型。
微調(diào)方法
微調(diào)可以分為全微調(diào)和重用兩個方法:
??全微調(diào)(Full Fine-tuning):全微調(diào)是指對整個預訓練模型進行微調(diào),包括所有的模型參數(shù)。在這種方法中,預訓練模型的所有層和參數(shù)都會被更新和優(yōu)化,以適應目標任務的需求。這種微調(diào)方法通常適用于任務和預訓練模型之間存在較大差異的情況,或者任務需要模型具有高度靈活性和自適應能力的情況。Full Fine-tuning需要較大的計算資源和時間,但可以獲得更好的性能。
??部分微調(diào)(Repurposing):部分微調(diào)是指在微調(diào)過程中只更新模型的頂層或少數(shù)幾層,而保持預訓練模型的底層參數(shù)不變。這種方法的目的是在保留預訓練模型的通用知識的同時,通過微調(diào)頂層來適應特定任務。Repurposing通常適用于目標任務與預訓練模型之間有一定相似性的情況,或者任務數(shù)據(jù)集較小的情況。由于只更新少數(shù)層,Repurposing相對于Full Fine-tuning需要較少的計算資源和時間,但在某些情況下性能可能會有所降低。
微調(diào)預訓練模型的方法:
??微調(diào)所有層:將預訓練模型的所有層都參與微調(diào),以適應新的任務。
??微調(diào)頂層:只微調(diào)預訓練模型的頂層,以適應新的任務。
??凍結(jié)底層:將預訓練模型的底層固定不變,只對頂層進行微調(diào)。
??逐層微調(diào):從底層開始,逐層微調(diào)預訓練模型,直到所有層都被微調(diào)。
??遷移學習:將預訓練模型的知識遷移到新的任務中,以提高模型性能。這種方法通常使用微調(diào)頂層或凍結(jié)底層的方法。
Fine tuning
經(jīng)典的Fine tuning方法包括將預訓練模型與少量特定任務數(shù)據(jù)一起繼續(xù)訓練。在這個過程中,預訓練模型的權(quán)重被更新,以更好地適應任務。所需的Fine-tuning量取決于預訓練語料庫和任務特定語料庫之間的相似性。如果兩者相似,可能只需要少量的Fine tuning。如果兩者不相似,則可能需要更多的Fine tuning。
Prompt Tuning(P-tuning)
Prompt Tuning 是2021年谷歌在論文《The Power of Scale for Parameter-Efficient Prompt Tuning》中提出的微調(diào)方法。參數(shù)高效性微調(diào)方法中實現(xiàn)最簡單的方法還是Prompt tuning(也就是我們常說的P-Tuning),固定模型前饋層參數(shù),僅僅更新部分embedding參數(shù)即可實現(xiàn)低成本微調(diào)大模型。
經(jīng)典的Prompt tuning方式不涉及對底層模型的任何參數(shù)更新。相反,它側(cè)重于精心制作可以指導預訓練模型生成所需輸出的輸入提示或模板。主要結(jié)構(gòu)是利用了一個prompt encoder(BiLSTM+MLP),將一些pseudo prompt先encode(離散token)再與input embedding進行拼接,同時利用LSTM進行 Reparamerization 加速訓練,并引入少量自然語言提示的錨字符(Anchor,例如Britain)進一步提升效果。然后結(jié)合(capital,Britain)生成得到結(jié)果,再優(yōu)化生成的encoder部分。
但是P-tuning v1有兩個顯著缺點:任務不通用和規(guī)模不通用。在一些復雜的自然語言理解NLU任務上效果很差,同時預訓練模型的參數(shù)量不能過小。具體的效果論文中提到以下幾點:
? Prompt 長度影響:模型參數(shù)達到一定量級時,Prompt 長度為1也能達到不錯的效果,Prompt 長度為20就能達到極好效果。
? Prompt初始化方式影響:Random Uniform 方式明顯弱于其他兩種,但是當模型參數(shù)達到一定量級,這種差異也不復存在。
??預訓練的方式:LM Adaptation 的方式效果好,但是當模型達到一定規(guī)模,差異又幾乎沒有了。
??微調(diào)步數(shù)影響:模型參數(shù)較小時,步數(shù)越多,效果越好。同樣隨著模型參數(shù)達到一定規(guī)模,zero shot 也能取得不錯效果。當參數(shù)達到100億規(guī)模與全參數(shù)微調(diào)方式效果無異。
代碼示例:
from?peft?import?PromptTuningConfig,?get_peft_model peft_config?=?PromptTuningConfig(task_type="SEQ_CLS",?num_virtual_tokens=10) model?=?AutoModelForCausalLM.from_pretrained(model_name_or_path,?return_dict=True) model?=?get_peft_model(model,?peft_config)
Prefix Tuning
2021年論文《Prefix-Tuning: Optimizing Continuous Prompts for Generation》中提出了 Prefix Tuning 方法。與Full-finetuning 更新所有參數(shù)的方式不同,該方法是在輸入 token 之前構(gòu)造一段任務相關的 virtual tokens 作為 Prefix,然后訓練的時候只更新 Prefix 部分的參數(shù),而 Transformer 中的其他部分參數(shù)固定。
prefix-tuning技術(shù),相對于fine-tuning,在調(diào)節(jié)模型的過程中只優(yōu)化一小段可學習的continuous task-specific vector(prefix)而不是整個模型的參數(shù)。該方法其實和構(gòu)造 Prompt 類似,只是 Prompt 是人為構(gòu)造的“顯式”的提示,并且無法更新參數(shù),而Prefix 則是可以學習的“隱式”的提示。手動嘗試最優(yōu)的提示無異于大海撈針,于是便有了自動離散提示搜索的方法,但提示是離散的,神經(jīng)網(wǎng)絡是連續(xù)的,所以尋找的最優(yōu)提示可能是次優(yōu)的。
代碼示例:
peft_config?=?PrefixTuningConfig(task_type="CAUSAL_LM",?num_virtual_tokens=20) model?=?AutoModelForCausalLM.from_pretrained(model_name_or_path,?return_dict=True) model?=?get_peft_model(model,?peft_config)
GPT在P-tuning的加持下可達到甚至超過BERT在NLU領域的性能。下圖是細致的對比:
P-tuning v2
V2版本主要是基于P-tuning和prefix-tuning技術(shù),引入Deep Prompt Encoding和Multi-task Learning等策略進行優(yōu)化的。實驗表明,僅精調(diào)0.1%參數(shù)量,在330M到10B不同參數(shù)規(guī)模LM模型上,均取得和Fine-tuning相比肩的性能。
論文《P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks》從標題就可以看出,P-Tuning v2 的目標就是要讓 Prompt Tuning 能夠在不同參數(shù)規(guī)模的預訓練模型、針對不同下游任務的結(jié)果上都達到匹敵 Fine-tuning 的結(jié)果。也就是說當前 Prompt Tuning 方法在這兩個方面都存在局限性。
不同模型規(guī)模:Prompt Tuning 和 P-tuning 這兩種方法都是在預訓練模型參數(shù)規(guī)模夠足夠大時,才能達到和Fine-tuning 類似的效果,而參數(shù)規(guī)模較小時效果則很差。
不同任務類型:Prompt Tuning 和 P-tuning 這兩種方法在 sequence tagging 任務上表現(xiàn)都很差。
v1到v2的可視化:藍色部分為參數(shù)凍結(jié),橙色部分為可訓練部分,可以看到右側(cè)的p-tuning v2中,將continuous prompt加在序列前端,并且每一層都加入可訓練的prompts。在左圖v1模型中,只將prompt插入input embedding中,會導致可訓練的參數(shù)被句子的長度所限制。此外P-Tuning v2還包括以下改進:
??移除了Reparamerization加速訓練方式;
??采用了多任務學習優(yōu)化:基于多任務數(shù)據(jù)集的Prompt進行預訓練,然后再適配的下游任務。
??舍棄了詞匯Mapping的Verbalizer的使用,重新利用[CLS]和字符標簽,跟傳統(tǒng)finetune一樣利用cls或者token的輸出做NLU,以增強通用性,可以適配到序列標注任務。
P-Tuning v2幾個關鍵設計因素:
? Reparameterization:Prefix Tuning 和 P-tuning 中都有 MLP 來構(gòu)造可訓練的 embedding。論文發(fā)現(xiàn)在自然語言理解領域,面對不同的任務以及不同的數(shù)據(jù)集,這種方法可能帶來完全相反的結(jié)論。
? Prompt Length:不同的任務對應的最合適的 Prompt Length 不一樣,比如簡單分類任務下 length=20 最好,而復雜的任務需要更長的 Prompt Length。
? Multi-task Learning 多任務對于 P-Tuning v2 是可選的,但可以利用它提供更好的初始化來進一步提高性能。
? Classification Head 使用 LM head 來預測動詞是 Prompt Tuning 的核心,但我們發(fā)現(xiàn)在完整的數(shù)據(jù)設置中沒有必要這樣做,并且這樣做與序列標記不兼容。P-tuning v2 采用和 BERT 一樣的方式,在第一個 token 處應用隨機初始化的分類頭。
代碼示例:
peft_config?=?PrefixTuningConfig(task_type="SEQ_CLS",?num_virtual_tokens=20) model?=?AutoModelForSequenceClassification.from_pretrained(model_name_or_path,?return_dict=True) model?=?get_peft_model(model,?peft_config)
AdaLoRA
預訓練語言模型中的不同權(quán)重參數(shù)對下游任務的貢獻是不同的。因此需要更加智能地分配參數(shù)預算,以便在微調(diào)過程中更加高效地更新那些對模型性能貢獻較大的參數(shù)。
具體來說,通過奇異值分解將權(quán)重矩陣分解為增量矩陣,并根據(jù)新的重要性度量動態(tài)地調(diào)整每個增量矩陣中奇異值的大小。這樣可以使得在微調(diào)過程中只更新那些對模型性能貢獻較大或必要的參數(shù),從而提高了模型性能和參數(shù)效率。
代碼示例:
peft_config?=?AdaLoraConfig(peft_type="ADALORA",?task_type="SEQ_2_SEQ_LM",?r=8,?lora_alpha=32,?target_modules=["q",?"v"],lora_dropout=0.01) model?=?AutoModelForCausalLM.from_pretrained(model_name_or_path,?return_dict=True) model?=?get_peft_model(model,?peft_config)
GPT4模型微調(diào)分類
1. Adapter-based Methods(基于適配器的方法):
《Parameter-Efficient Transfer Learning for NLP》提出針對 BERT 的 PEFT微調(diào)方式,拉開了 PEFT 研究的序幕。他們指出,在面對特定的下游任務時,如果進行 Full-Fintuning(即預訓練模型中的所有參數(shù)都進行微調(diào)),太過低效;而如果采用固定預訓練模型的某些層,只微調(diào)接近下游任務的那幾層參數(shù),又難以達到較好的效果。
于是他們設計了如下圖所示的 Adapter 結(jié)構(gòu),將其嵌入 Transformer 的結(jié)構(gòu)里面,在訓練時,固定住原來預訓練模型的參數(shù)不變,只對新增的 Adapter 結(jié)構(gòu)進行微調(diào)。同時為了保證訓練的高效性(也就是盡可能少的引入更多參數(shù)),他們將 Adapter 設計為這樣的結(jié)構(gòu):
首先是一個 down-project 層將高維度特征映射到低維特征;然后過一個非線形層之后,再用一個 up-project 結(jié)構(gòu)將低維特征映射回原來的高維特征;同時也設計了 skip-connection 結(jié)構(gòu),確保了在最差的情況下能夠退化為identity(類似殘差結(jié)構(gòu))。
這種方法節(jié)省了資源,因為它不需要對整個模型進行微調(diào)。示例有AdapterDrop、Parallel Adapter、Residual Adapter等。
2. Prompt-based Methods(基于提示的方法):
這個分支側(cè)重于使用連續(xù)的提示(如嵌入向量)來調(diào)整模型的行為,而不是直接修改模型的權(quán)重。這類方法通常用于生成任務,例如文本生成。提示可以視為模型輸入的一部分,它們會被訓練以激發(fā)模型生成特定的輸出。示例包括Prefix-tuning、Prompt tuning等,參加上文介紹。
3. Low-rank Adaptation(低秩適配):
低秩適配方法致力于將模型權(quán)重的改變限制在一個低秩子空間內(nèi)。這通常涉及對模型的權(quán)重矩陣進行分解,只微調(diào)其中的一小部分參數(shù)。這樣可以有效減少計算資源的消耗,同時仍然允許模型有足夠的靈活性來學習新任務。LoRA和它的變種,如Q-LoRA、Delta-LoRA、LoRA-FA等,都屬于這個類別。
4. Sparse Methods(稀疏方法):
這個分支包括那些僅更新模型中一小部分參數(shù)的方法。這些參數(shù)被選為最有可能影響到任務性能的,而其他參數(shù)則保持不變。稀疏方法的優(yōu)點在于它們通常能夠更高效地利用資源。例如有Intrinsic SAID、Fish Mask、BitFit等。
5. Others(其他方法):
這一分支可能包括不易歸類到上述任何一類的其他方法,或者是結(jié)合了多種技術(shù)的混合方法。這些方法可能包括特定的結(jié)構(gòu)改變、算法優(yōu)化等,用以提高微調(diào)過程的效率或者效果。
大模型微調(diào)步驟總結(jié)
大模型微調(diào)如上文所述有很多方法,并且對于每種方法都會有不同的微調(diào)流程、方式、準備工作和周期。然而大部分的大模型微調(diào),都有以下幾個主要步驟,并需要做相關的準備:
準備數(shù)據(jù)集:
收集和準備與目標任務相關的訓練數(shù)據(jù)集。確保數(shù)據(jù)集質(zhì)量和標注準確性,并進行必要的數(shù)據(jù)清洗和預處理。
選擇預訓練模型/基礎模型:
根據(jù)目標任務的性質(zhì)和數(shù)據(jù)集的特點,選擇適合的預訓練模型。
設定微調(diào)策略:
根據(jù)任務需求和可用資源,選擇適當?shù)奈⒄{(diào)策略??紤]是進行全微調(diào)還是部分微調(diào),以及微調(diào)的層級和范圍。
設置超參數(shù):
確定微調(diào)過程中的超參數(shù),如學習率、批量大小、訓練輪數(shù)等。這些超參數(shù)的選擇對微調(diào)的性能和收斂速度有重要影響。
初始化模型參數(shù):
根據(jù)預訓練模型的權(quán)重,初始化微調(diào)模型的參數(shù)。對于全微調(diào),所有模型參數(shù)都會被隨機初始化;對于部分微調(diào),只有頂層或少數(shù)層的參數(shù)會被隨機初始化。
進行微調(diào)訓練:
使用準備好的數(shù)據(jù)集和微調(diào)策略,對模型進行訓練。在訓練過程中,根據(jù)設定的超參數(shù)和優(yōu)化算法,逐漸調(diào)整模型參數(shù)以最小化損失函數(shù)。
模型評估和調(diào)優(yōu):
在訓練過程中,使用驗證集對模型進行定期評估,并根據(jù)評估結(jié)果調(diào)整超參數(shù)或微調(diào)策略。這有助于提高模型的性能和泛化能力。
測試模型性能:
在微調(diào)完成后,使用測試集對最終的微調(diào)模型進行評估,以獲得最終的性能指標。這有助于評估模型在實際應用中的表現(xiàn)。
模型部署和應用:
將微調(diào)完成的模型部署到實際應用中,并進行進一步的優(yōu)化和調(diào)整,以滿足實際需求。
審核編輯:黃飛
?
評論
查看更多