LLM 課程文件

LoRA (低秩自適應)

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Ask a Question Open In Colab

LoRA (低秩適應)

微調大型語言模型是一個資源密集型過程。LoRA 是一種允許我們使用少量引數微調大型語言模型的技術。它透過向注意力權重新增和最佳化較小的矩陣來工作,通常可將可訓練引數減少約 90%。

理解 LoRA

LoRA(低秩適應)是一種引數高效的微調技術,它凍結了預訓練模型的權重,並將可訓練的秩分解矩陣注入到模型的層中。LoRA 不是在微調期間訓練所有模型引數,而是透過低秩分解將權重更新分解為更小的矩陣,從而顯著減少可訓練引數的數量,同時保持模型效能。例如,當應用於 GPT-3 175B 時,與完全微調相比,LoRA 將可訓練引數減少了 10,000 倍,GPU 記憶體需求減少了 3 倍。您可以在 LoRA 論文中閱讀更多關於 LoRA 的資訊。

LoRA 透過向 Transformer 層新增成對的秩分解矩陣來工作,通常側重於注意力權重。在推理過程中,這些介面卡權重可以與基礎模型合併,從而不會產生額外的延遲開銷。LoRA 對於將大型語言模型適應特定任務或領域特別有用,同時保持資源需求可管理。

LoRA 的主要優勢

  1. 記憶體效率:

    • 只有介面卡引數儲存在 GPU 記憶體中
    • 基礎模型權重保持凍結,並可以以較低精度載入
    • 允許在消費級 GPU 上微調大型模型
  2. 訓練功能:

    • PEFT/LoRA 本機整合,設定最少
    • 支援 QLoRA(量化 LoRA),以獲得更好的記憶體效率
  3. 介面卡管理:

    • 檢查點期間介面卡權重儲存
    • 將介面卡合併回基礎模型的功能

使用 PEFT 載入 LoRA 介面卡

PEFT 是一個提供統一介面來載入和管理 PEFT 方法(包括 LoRA)的庫。它允許您輕鬆載入和切換不同的 PEFT 方法,從而更輕鬆地嘗試不同的微調技術。

介面卡可以透過 load_adapter() 載入到預訓練模型上,這對於嘗試未合併權重的不同介面卡很有用。使用 set_adapter() 函式設定活動介面卡權重。要返回基礎模型,您可以使用 unload() 解除安裝所有 LoRA 模組。這使得在不同的特定任務權重之間切換變得容易。

from peft import PeftModel, PeftConfig

config = PeftConfig.from_pretrained("ybelkada/opt-350m-lora")
model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path)
lora_model = PeftModel.from_pretrained(model, "ybelkada/opt-350m-lora")

lora_load_adapter

使用 trl 和 SFTTrainer 微調 LLM 與 LoRA

trl 中的 SFTTrainer 透過 PEFT 庫提供了與 LoRA 介面卡的整合。這意味著我們可以像使用 SFT 那樣微調模型,但使用 LoRA 來減少我們需要訓練的引數數量。

我們將在示例中使用 PEFT 的 LoRAConfig 類。設定只需要幾個配置步驟

  1. 定義 LoRA 配置(秩、alpha、dropout)
  2. 建立帶有 PEFT 配置的 SFTTrainer
  3. 訓練並儲存介面卡權重

LoRA 配置

讓我們來了解一下 LoRA 配置和關鍵引數。

引數 描述
r (秩) 用於權重更新的低秩矩陣的維度。通常在 4-32 之間。較低的值提供更高的壓縮率,但表達能力可能較弱。
lora_alpha LoRA 層的縮放因子,通常設定為秩值的 2 倍。較高的值會導致更強的適應效果。
lora_dropout LoRA 層的 dropout 機率,通常為 0.05-0.1。較高的值有助於防止訓練期間過擬合。
偏差 (bias) 控制偏差項的訓練。“none”、“all”或“lora_only”選項。“none”對於記憶體效率而言最常見。
target_modules 指定要應用 LoRA 的模型模組。可以是“all-linear”或特定模組,如“q_proj,v_proj”。更多模組可實現更大的適應性,但會增加記憶體使用。
實施 PEFT 方法時,從 LoRA 的小秩值(4-8)開始,並監控訓練損失。使用驗證集來防止過擬合,並在可能的情況下將結果與完全微調基線進行比較。不同方法的有效性可能因任務而異,因此實驗是關鍵。

將 TRL 與 PEFT 結合使用

PEFT 方法可以與 TRL 結合用於微調,以減少記憶體需求。我們可以在載入模型時將 LoraConfig 傳遞給模型。

from peft import LoraConfig

# TODO: Configure LoRA parameters
# r: rank dimension for LoRA update matrices (smaller = more compression)
rank_dimension = 6
# lora_alpha: scaling factor for LoRA layers (higher = stronger adaptation)
lora_alpha = 8
# lora_dropout: dropout probability for LoRA layers (helps prevent overfitting)
lora_dropout = 0.05

peft_config = LoraConfig(
    r=rank_dimension,  # Rank dimension - typically between 4-32
    lora_alpha=lora_alpha,  # LoRA scaling factor - typically 2x rank
    lora_dropout=lora_dropout,  # Dropout probability for LoRA layers
    bias="none",  # Bias type for LoRA. the corresponding biases will be updated during training.
    target_modules="all-linear",  # Which modules to apply LoRA to
    task_type="CAUSAL_LM",  # Task type for model architecture
)

上面,我們使用了 device_map="auto" 來自動將模型分配到正確的裝置。您也可以使用 device_map={"": device_index} 手動將模型分配到特定裝置。

我們還需要使用 LoRA 配置定義 SFTTrainer

# Create SFTTrainer with LoRA configuration
trainer = SFTTrainer(
    model=model,
    args=args,
    train_dataset=dataset["train"],
    peft_config=peft_config,  # LoRA configuration
    max_seq_length=max_seq_length,  # Maximum sequence length
    processing_class=tokenizer,
)

✏️ 試一試! 在上一節微調的模型基礎上,使用 LoRA 對其進行微調。使用 HuggingFaceTB/smoltalk 資料集來微調 deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B 模型,使用我們上面定義的 LoRA 配置。

合併 LoRA 介面卡

使用 LoRA 訓練後,您可能希望將介面卡權重合並回基礎模型,以便於部署。這會建立一個具有組合權重的單一模型,從而無需在推理期間單獨載入介面卡。

合併過程需要注意記憶體管理和精度。由於您需要同時載入基礎模型和介面卡權重,因此請確保有足夠的 GPU/CPU 記憶體可用。在 transformers 中使用 device_map="auto" 將根據您的硬體為模型找到正確的裝置。

在整個過程中保持一致的精度(例如,float16),與訓練期間使用的精度匹配,並以相同的格式儲存合併的模型以進行部署。

合併實現

訓練 LoRA 介面卡後,您可以將介面卡權重合並回基礎模型。操作方法如下:

import torch
from transformers import AutoModelForCausalLM
from peft import PeftModel

# 1. Load the base model
base_model = AutoModelForCausalLM.from_pretrained(
    "base_model_name", torch_dtype=torch.float16, device_map="auto"
)

# 2. Load the PEFT model with adapter
peft_model = PeftModel.from_pretrained(
    base_model, "path/to/adapter", torch_dtype=torch.float16
)

# 3. Merge adapter weights with base model
merged_model = peft_model.merge_and_unload()

如果儲存的模型出現大小不一致的情況,請確保您也儲存了分詞器

# Save both model and tokenizer
tokenizer = AutoTokenizer.from_pretrained("base_model_name")
merged_model.save_pretrained("path/to/save/merged_model")
tokenizer.save_pretrained("path/to/save/merged_model")

✏️ 試一試! 將介面卡權重合並回基礎模型。使用 HuggingFaceTB/smoltalk 資料集來微調 deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B 模型,使用我們上面定義的 LoRA 配置。

資源

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.