PEFT 文件
正交微調(OFT 與 BOFT)
並獲得增強的文件體驗
開始使用
正交微調(OFT 與 BOFT)
本概念指南簡要概述了 OFT、OFTv2 和 BOFT,這是一種引數高效的微調技術,利用正交矩陣對預訓練權重矩陣進行乘法變換。
為了實現高效微調,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 微調模型,您需要:
- 例項化一個基礎模型。
- 建立一個配置(`OFTConfig` 或 `BOFTConfig`),在其中定義 OFT/BOFT 特定的引數。
- 使用 `get_peft_model()` 包裝基礎模型以獲得一個可訓練的 `PeftModel`。
- 像訓練基礎模型一樣訓練 `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)