語言大模型是透過大規模資料集訓練而來可以幫我們進行文字生成、內容總結,但對於一些小眾知識、內部資料模型不一定知道怎麼回答,這時候可能會胡言亂語。目前要想在特定領域小眾知識或私密資料時模型能夠表現出比較好的水平目前主要有兩種方式可以實現:模型微調、外掛知識庫也就是RAG模式,RAG模式之前我們有介紹過,本篇文章主要是介紹模型微調。
模型微調訓練是將知識庫(私有知識)的內容整理成訓練資料集,將這些整理好的資料集來訓練大語言模型,最終讓模型“學會”該知識庫的內容,至於效果如何很大程度取決於該資料集的質量和訓練的調參以及基礎模型的質量,這種方式流程較複雜、算力要求高相對比外掛知識庫RAG方式門檻更高;
目前大模型是透過引數規模、訓練資料規模、算力規模堆積起來的語言大模型小的有幾億引數量大的達到幾千億引數量乃至萬億引數量,一般公司也只能執行推理百億規模模型,從0訓練一個大模型無論是算力或是資料都不具備這樣的能力,模型微調所需要的技術、算力資源就要少得多。下圖為LLaMA-Factory官方估計的大模型微調所需要視訊記憶體資源情況。
微調概念
大模型訓練完成之後超引數已經固定下來了,大模型在特定領域知識上可能表現不佳這時候想要大模型在該領域知識範圍達到比較好的水平,可以透過在預訓練大模型的基礎上使用該特定領域知識再次訓練模型已達到調整超引數使得大模型讀懂該領域知識的目的。
微調目的: 調整超引數使大模型在特定領域知識內達到比較好的水平;
微調型別: 全量微調(Full Fine-tuning)、引數高效微調(Parameter-Efficient Fine-Tuning, PEFT)
全量微調: 透過預訓練模型的所有引數進行訓練調整適配特定領域知識,但需要有足夠規模的計算資源。
引數高效微調(PEFT): 最小化微調引數數量,只需要微調更新模型的部分引數調整所依賴的計算資源比全量微調小得多。PEFT主要演算法包括Prefix Tuning、Prompt Tuning 、Adapter Tuning 、IA3 (Intrinsic Adapter 3) 、LORA (Low-Rank Adaptation) 、Q-LoRA(Quantized Low-Rank Adapter) 和DoRA(Weight-Decomposed Low-Rank Adaptation 、GaLore(Gradient Low-Rank Projection) 、BAdam 等方式。
Adapter Tuning: 這是一種透過在模型的層之間插入小型的神經網路模組(稱為adapters)來實現微調的技術。這些adapters包含可訓練的權重,而模型的原始引數保持不變。Adapter Tuning透過學習降維後的特徵,有效地減少了引數數量,同時使用skip-connection技術,即使在最差情況下,Adapter層也可以退化為identity,從而保持模型的穩定性。
Prompt Tuning: 這是一種透過在輸入序列前新增額外的Token來適配下游任務的方法。這些額外的Token是可訓練的,而預訓練語言模型的引數保持不變。Prompt Tuning透過構建或選擇適當的提示(Prompt),引導模型生成符合期望的輸出。
IA3 (Intrinsic Adapter 3): IA3是一種新的高效微調方法,它在凍結大模型引數的情況下,透過在輸入時給定一些樣本包含資料和標籤,同時給一個待預測資料,由模型輸出這條資料的預測值。這個過程中模型的引數不發生變化。IA3提出了一個新的高效微調方法,基於T0模型提出了T-Few,在下游任務中不需要對任務進行額外模型調整,即可進行少樣本學習。IA3 將模型的啟用(自我注意和編碼器-解碼器注意力塊中的鍵和值,以及位置前饋網路的中間啟用)乘以三個學習向量,可訓練引數數量比 LoRA 還要少。
LORA (Low-Rank Adaptation): LORA透過對基座模型引數中的每個矩陣W增加兩個低秩矩陣A和B,其中A是 n * r 的,B是 r * n 的。新模型的引數為W_new = W + A * B,凍結固定W,只調整A和B。LORA通常只調整Attention中的矩陣,不調整FFN。預訓練模型的原始權重矩陣被凍結,在訓練期間只有較小的矩陣會更新減少訓練引數量,同時保持模型效能。
微調工具
比較常見的微調框架工具有LLaMA-Factory、PEFT等,LLaMA-Factory提供了全流程微調的解決方案包括全量微調、高效微調等還提供了基礎資料集的支援,微調指令碼與Web介面。而PEFT只是一個高效微調框架可以很方便與Transformers等整合使用。
PEFT微調
這裡使用PEFT框架對Qwen2.5-0.5B模型進行LORA微調,看其在特定領域知識內是否會有明顯改善。LoRA(Low-Rank Adaptation)的核心思想是透過在模型的特定層或模組中插入低秩矩陣來近似全引數微調的效果。
對引數矩陣W增加兩個低秩矩陣A和B,其中A是 n * r 的,B是 r * n 的,這裡已Qweb2.5-0.5B為例介紹LoRA微調的總體實現,原模型結構如下:
Qwen2ForCausalLM(
(model): Qwen2Model(
(embed_tokens): Embedding(151936, 896)
(layers): ModuleList(
(0-23): 24 x Qwen2DecoderLayer(
(self_attn): Qwen2SdpaAttention(
(q_proj): Linear(in_features=896, out_features=896, bias=True)
(k_proj): Linear(in_features=896, out_features=128, bias=True)
(v_proj): Linear(in_features=896, out_features=128, bias=True)
(o_proj): Linear(in_features=896, out_features=896, bias=False)
(rotary_emb): Qwen2RotaryEmbedding()
)
(mlp): Qwen2MLP(
(gate_proj): Linear(in_features=896, out_features=4864, bias=False)
(up_proj): Linear(in_features=896, out_features=4864, bias=False)
(down_proj): Linear(in_features=4864, out_features=896, bias=False)
(act_fn): SiLU()
)
(input_layernorm): Qwen2RMSNorm((896,), eps=1e-06)
(post_attention_layernorm): Qwen2RMSNorm((896,), eps=1e-06)
)
)
(norm): Qwen2RMSNorm((896,), eps=1e-06)
(rotary_emb): Qwen2RotaryEmbedding()
)
(lm_head): Linear(in_features=896, out_features=151936, bias=False)
)
在載入基座模型後可使用LoraConfig配置具體需要進行LoRA微調的引數如:target_modules、秩、alpha、dropout等值。
target_modules: 需要進行微調的模組,可選值有q_proj、k_proj、v_proj、o_proj、gate_proj等。
r: 秩,直接影響了低秩矩陣的大小,決定了微調的引數量
alpha: 縮放因子,用於調節低秩矩陣對模型權重的貢獻程度,多大可能會過擬合。
dropout: 值在0和1之間,隨機丟棄某些權重的機率。
model = AutoModelForCausalLM.from_pretrained(
model_name,
low_cpu_mem_usage=True
)
config = LoraConfig(
r=8, lora_alpha=128, lora_dropout=0.0,
target_modules=["q_proj", "k_proj", "v_proj"] #, "o_proj", "gate_proj", "up_proj", "down_proj"]
)
model = get_peft_model(model, config)
知道了秩r的值、需要微調的模組以及該模組的輸入輸出,即可計算出微調的過程中訓練的引數量是多少,LoRA核心思想是透過在模型的特定層或模組中插入低秩矩陣來近似全引數微調的效果。對於每個目標模組,LoRA增加的引數量計算公式為:
引數量 =輸入維度 * r + r * 輸出維度= r × ( 輸入維度 + 輸出維度 ) 。
以上微調LoraConfig配置為例,透過該配置微調Qwen2.5-0.5B所增加的引數量計算結果如下:
r = 8 q = 896 * 896 k = 896 * 128 v = 896 * 128 有24個解碼層
q =24*(896*8+8*896)
k =24*(896*8+8*128)
v =24*(896*8+8*128)
帶入上面公式可得到q、k、v每個模組的引數量,q+k+v所得的就是當前模型微調的總引數量也是可訓練的總引數量:737280;
透過AutoModelForCausalLM模型print_trainable_parameters方法輸出可知Qwen2.5-0.5B總引數量為:4億9千萬,透過LORA微調實際可微調的引數為439萬佔比為0.88%,凍結了99%的引數,可透過下面方法驗證計算結果是否正確;
#列印模型可訓練引數資訊
model.print_trainable_parameters()
trainable params: 737,280 || all params: 494,770,048 || trainable%: 0.1490
all params 為模型總引數量,trainable params為可訓練引數量,trainable可訓練引數比為0.1490%,all params為原來模型引數量+本次微調新增引數量。
本篇文章只介紹了微調的基本概念,後續將介紹微調的具體流程與程式碼實現。
參考資料:
peft