PEFT 文件

正交微調(OFT 與 BOFT)

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

正交微調(OFT 與 BOFT)

本概念指南簡要概述了 OFTOFTv2BOFT,這是一種引數高效的微調技術,利用正交矩陣對預訓練權重矩陣進行乘法變換。

為了實現高效微調,OFT 使用正交變換來表示權重更新。該正交變換透過一個與預訓練權重矩陣相乘的正交矩陣進行引數化。這些新矩陣可以被訓練以適應新資料,同時保持總體變化數量較少。原始權重矩陣保持凍結,不再進行任何調整。為了產生最終結果,原始權重和適配後的權重會相乘。

正交蝶形(Orthogonal Butterfly,BOFT)透過蝶形分解(Butterfly factorization)對 OFT 進行了推廣,進一步提高了其引數效率和微調靈活性。簡而言之,OFT 可以被視為 BOFT 的一個特例。與使用加性低秩權重更新的 LoRA 不同,BOFT 使用乘性正交權重更新。對比如下所示。

與 LoRA 相比,BOFT 具有一些優勢

  • BOFT 提出了一種簡單而通用的方法,用於將預訓練模型微調至下游任務,從而更好地保留預訓練知識並提高參數效率。
  • 透過正交性,BOFT 引入了一種結構性約束,即在微調過程中保持超球面能量不變。這可以有效減少對預訓練知識的遺忘。
  • BOFT 使用蝶形分解來高效地引數化正交矩陣,這產生了一個緊湊且富有表現力的學習空間(即假設類別)。
  • BOFT 中的稀疏矩陣分解帶來了額外的歸納偏置,這有利於泛化。

原則上,BOFT 可以應用於神經網路中權重矩陣的任何子集,以減少可訓練引數的數量。給定注入 BOFT 引數的目標層,可訓練引數的數量可以根據權重矩陣的大小確定。

將 OFT/BOFT 權重合併到基礎模型中

與 LoRA 類似,透過 OFT/BOFT 學到的權重可以使用 merge_and_unload() 函式整合到預訓練權重矩陣中。此函式將介面卡權重與基礎模型合併,使您能夠有效地將新合併的模型作為一個獨立模型使用。

這是因為在訓練期間,正交權重矩陣(上圖中的 R)和預訓練權重矩陣是分開的。但一旦訓練完成,這些權重實際上可以合併(相乘)成一個新的等效權重矩陣。

OFT / BOFT 的工具函式

PEFT 中 OFT / BOFT 的通用引數

與 PEFT 支援的其他方法一樣,要使用 OFT 或 BOFT 微調模型,您需要:

  1. 例項化一個基礎模型。
  2. 建立一個配置(`OFTConfig` 或 `BOFTConfig`),在其中定義 OFT/BOFT 特定的引數。
  3. 使用 `get_peft_model()` 包裝基礎模型以獲得一個可訓練的 `PeftModel`。
  4. 像訓練基礎模型一樣訓練 `PeftModel`。

OFT 特定引數

`OFTConfig` 允許您透過以下引數控制如何將 OFT 應用於基礎模型:

  • `r`:OFT 的秩,即每個注入層的 OFT 塊數。**更大**的 `r` 會導致更稀疏的更新矩陣和**更少**的可訓練引數。**注意**:您只能指定 `r` 或 `oft_block_size`,不能同時指定兩者,因為 `r` × `oft_block_size` = 層的維度。為簡單起見,我們讓使用者指定 `r` 或 `oft_block_size` 中的一個,然後推斷出另一個。預設設定為 `r = 0`,建議使用者設定 `oft_block_size` 以獲得更好的清晰度。
  • `oft_block_size`:不同層的 OFT 塊大小。**更大**的 `oft_block_size` 會導致更密集的更新矩陣和**更多**的可訓練引數。**注意**:請選擇能被層輸入維度(`in_features`)整除的 `oft_block_size`,例如 4, 8, 16。您只能指定 `r` 或 `oft_block_size`,不能同時指定兩者,因為 `r` × `oft_block_size` = 層的維度。為簡單起見,我們讓使用者指定 `r` 或 `oft_block_size` 中的一個,然後推斷出另一個。預設設定為 `oft_block_size = 32`。
  • `use_cayley_neumann`:指定是否使用 Cayley-Neumann 引數化(高效但近似)或原版 Cayley 引數化(精確但因矩陣求逆而計算成本高)。我們建議將其設定為 `True` 以獲得更好的效率,但由於近似誤差,效能可能會稍差。請根據您的需求測試兩種設定(`True` 和 `False`)。預設為 `False`。
  • `module_dropout`:乘性 dropout 的機率,透過在訓練期間將 OFT 塊設定為單位矩陣,類似於 LoRA 中的 dropout 層。
  • `bias`:指定是否應訓練 `bias` 引數。可以是 `"none"`、`"all"` 或 `"oft_only"`。
  • `target_modules`:要注入 OFT 矩陣的模組(例如,注意力塊)。
  • `modules_to_save`:除了 OFT 矩陣之外,要設定為可訓練並儲存在最終檢查點中的模組列表。這些通常包括為微調任務隨機初始化的模型的自定義頭部。

BOFT 特定引數

`BOFTConfig` 允許您透過以下引數控制如何將 BOFT 應用於基礎模型:

  • `boft_block_size`:不同層的 BOFT 矩陣塊大小,以 `int` 表示。**更大**的 `boft_block_size` 會導致更密集的更新矩陣和**更多**的可訓練引數。**注意**,請選擇能被大多數層的輸入維度(`in_features`)整除的 `boft_block_size`,例如 4, 8, 16。另外,請只指定 `boft_block_size` 或 `boft_block_num` 中的一個,不要同時指定或都留為 0,因為 `boft_block_size` × `boft_block_num` 必須等於層的輸入維度。
  • `boft_block_num`:不同層的 BOFT 矩陣塊數,以 `int` 表示。**更大**的 `boft_block_num` 會導致更稀疏的更新矩陣和**更少**的可訓練引數。**注意**,請選擇能被大多數層的輸入維度(`in_features`)整除的 `boft_block_num`,例如 4, 8, 16。另外,請只指定 `boft_block_size` 或 `boft_block_num` 中的一個,不要同時指定或都留為 0,因為 `boft_block_size` × `boft_block_num` 必須等於層的輸入維度。
  • `boft_n_butterfly_factor`:蝶形因子的數量。**注意**,當 `boft_n_butterfly_factor=1` 時,BOFT 與原版 OFT 相同;當 `boft_n_butterfly_factor=2` 時,OFT 的有效塊大小變為兩倍,塊數變為一半。
  • `bias`:指定是否應訓練 `bias` 引數。可以是 `"none"`、`"all"` 或 `"boft_only"`。
  • `boft_dropout`:指定乘性 dropout 的機率。
  • `target_modules`:要注入 OFT/BOFT 矩陣的模組(例如,注意力塊)。
  • `modules_to_save`:除了 OFT/BOFT 矩陣之外,要設定為可訓練並儲存在最終檢查點中的模組列表。這些通常包括為微調任務隨機初始化的模型的自定義頭部。

OFT 使用示例

要使用 OFT 進行量化微調,並結合 TRL 進行 `SFT`、`PPO` 或 `DPO` 微調,請遵循以下大綱:

from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from trl import SFTTrainer
from peft import OFTConfig

if use_quantization:
    bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch.bfloat16,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_storage=torch.bfloat16,
    )

model = AutoModelForCausalLM.from_pretrained(
    "model_name", 
    quantization_config=bnb_config
)
tokenizer = AutoTokenizer.from_pretrained("model_name")

# Configure OFT
peft_config = OFTConfig(
    oft_block_size=32,
    use_cayley_neumann=True,
    target_modules="all-linear",
    bias="none",
    task_type="CAUSAL_LM"
)

trainer = SFTTrainer(
    model=model,
    train_dataset=ds['train'],
    peft_config=peft_config,
    processing_class=tokenizer,
    args=training_arguments,
    data_collator=collator,
)

trainer.train()

BOFT 使用示例

關於 BOFT 方法在各種下游任務中的應用示例,請參考以下指南:

請檢視以下關於如何使用 BOFT 微調模型的分步指南:

對於影像分類任務,可以如下為 DinoV2 模型初始化 BOFT 配置:

import transformers
from transformers import AutoModelForSeq2SeqLM, BOFTConfig
from peft import BOFTConfig, get_peft_model

config = BOFTConfig(
    boft_block_size=4,
    boft_n_butterfly_factor=2,
    target_modules=["query", "value", "key", "output.dense", "mlp.fc1", "mlp.fc2"],
    boft_dropout=0.1,
    bias="boft_only",
    modules_to_save=["classifier"],
)

model = transformers.Dinov2ForImageClassification.from_pretrained(
    "facebook/dinov2-large",
    num_labels=100,
)

boft_model = get_peft_model(model, config)
< > 在 GitHub 上更新

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