PEFT 文件
RandLora: 對大型模型進行全秩引數高效微調
並獲得增強的文件體驗
開始使用
RandLora: 對大型模型進行全秩引數高效微調
RandLora 是一種引數高效微調技術,與 LoRA 和 VeRA 類似,但它執行全秩更新以提高效能。當需要將大型模型適配到需要複雜更新的困難任務時,RandLora 特別有用,同時還能保持 LoRA 的引數效率。RandLora 的全秩更新是透過線性縮放隨機基來實現的。這些隨機基是多個低秩矩陣的集合,它們的秩之和大於或等於引數矩陣的全秩。RandLora 的可訓練引數是兩個對角矩陣(向量),它們與右側的低秩隨機基相乘,方式類似於 VeRA 的更新。為了保持低記憶體使用,RandLora 使用了一個自定義函式,防止在記憶體中為反向傳播儲存不必要的基。
RandLora 的一個顯著區別是,與其他 LoRA 類的 PEFT 演算法相反,增加 RandLora 的隨機基的秩會增加可訓練引數的數量。因為在 RandLora 中,基的數量 x 基的秩是恆定的,所以減小秩會增加隨機基的數量,從而增加與基相關的可訓練對角基的數量。
由於降低 RandLora 隨機基的秩會增加其數量,因此對於非常小的秩,RandLora 的訓練速度可能比 LoRA 慢,通常秩低於 4 會導致訓練時間大幅增加。然而,這不影響推理,因為 RandLora 介面卡可以合併到預訓練的權重矩陣中。
RandLora 還支援使用稀疏的三元隨機基(只包含 -1、0 和 1)進行訓練。這些基如 Bingham 等人和 Ping 等人的研究所述,理論上可以透過執行聚合而不是矩陣乘法來建立權重更新,從而減少計算需求。目前尚不支援此功能。儘管目前並未減少計算量,但在某些情況下,在 RandLora 中使用稀疏隨機基可以減少過擬合。對於有興趣使用稀疏三元基的使用者,建議使用 `sparse` 選項,而非可能降低效能的 `very_sparse` 選項。
與 VeRA 類似,在儲存 RandLora 的引數時,可以透過在 `VeraConfig` 中設定 `save_projection=False` 來避免儲存低秩矩陣。在這種情況下,這些矩陣將根據 `projection_prng_key` 引數的固定隨機種子進行恢復。這減少了檢查點的大小,但我們不能保證在所有裝置和所有未來版本的 PyTorch 上的可復現性。如果你想確保可復現性,請設定 `save_projection=True`(這是預設值)。
與 Vera 類似,為了處理不同形狀的適配層,RandLora 使用每個維度的最大所需大小來初始化共享的 A 和 B 矩陣。在前向傳播期間,會從這些共享矩陣中切出特定層的子矩陣 A 和 B,並按論文所述使用。例如,適配兩個形狀為 (100, 20) 和 (80, 50) 的線性層,將建立形狀分別為 (rank, 50) 和 (100, rank) 的 A 和 B 矩陣。然後,為了適配一個形狀為 (100, 20) 的層,將提取形狀為 (rank, 20) 和 (100, rank) 的子矩陣 A 和 B。
RandLora 目前有以下限制
- 僅支援 `nn.Linear` 層。
論文摘要如下:
低秩自適應(LoRA)及其變體在減少大型 Transformer 網路的可訓練引數數量和記憶體需求方面取得了令人矚目的成果,同時保持了微調效能。然而,權重更新的低秩特性固有地限制了微調模型的表示能力,從而可能在複雜任務上影響效能。這引出了一個關鍵問題:當觀察到 LoRA 與標準微調之間的效能差距時,這是由於可訓練引數數量減少還是秩不足所致?本文旨在透過引入 RandLora 來回答這個問題,這是一種引數高效的方法,它使用低秩、不可訓練的隨機矩陣的習得線性組合來執行全秩更新。我們的方法透過將最佳化限制在應用於固定隨機矩陣的對角縮放矩陣上,從而限制了可訓練引數的數量。這使我們能夠有效地克服低秩限制,同時在訓練期間保持引數和記憶體效率。透過在視覺、語言和視覺-語言基準上進行廣泛的實驗,我們系統地評估了 LoRA 和現有隨機基方法的侷限性。我們的發現表明,全秩更新在單獨的視覺和語言任務中是有益的,而在視覺-語言任務中更是如此,其中 RandLora 顯著減少——有時甚至消除——了標準微調與 LoRA 之間的效能差距,證明了其有效性。
RandLoraConfig
class peft.RandLoraConfig
< 原始碼 >( task_type: typing.Union[str, peft.utils.peft_types.TaskType, NoneType] = None peft_type: typing.Union[str, peft.utils.peft_types.PeftType, NoneType] = None auto_mapping: typing.Optional[dict] = None base_model_name_or_path: typing.Optional[str] = None revision: typing.Optional[str] = None inference_mode: bool = False r: int = 32 target_modules: typing.Union[list[str], str, NoneType] = None projection_prng_key: int = 0 save_projection: bool = True sparse: bool = False very_sparse: bool = False randlora_dropout: float = 0.0 fan_in_fan_out: bool = False randlora_alpha: int = 640 bias: str = 'none' modules_to_save: typing.Optional[list[str]] = None init_weights: bool = True layers_to_transform: typing.Union[list[int], int, NoneType] = None layers_pattern: typing.Optional[str] = None )
引數
- r (
int
, 可選, 預設為32
) — RandLora 的隨機基秩維度。與 LoRA 相反,此引數與可訓練引數的數量成反比,因為減小它會增加可訓練引數。 - target_modules (
Union[list[str], str]
) — 要應用 RandLora 的模組名稱。僅支援線性層。 - projection_prng_key (
int
) — RandLora PRNG 初始化金鑰。用於為新模型初始化 basis_A 和 basis_B,或在載入未包含這些投影的檢查點時使用。預設為 `0`。 - save_projection (
bool
) — 是否在狀態字典中儲存全域性 basis_A / basis_B 隨機基,以及每層的 lambda / gamma 對角矩陣。這會增加檢查點的大小,但能保證我們可以在所有系統配置上重新載入檢查點。預設為 `True`。 - sparse (
bool
) — 是否使用 RandLora 論文中描述的稀疏隨機基。這些基是三元稀疏基(僅包含-1、0和1),其中-1和1的分配機率為1/6,0的分配機率為2/3。這些稀疏矩陣旨在未來用於免矩陣乘法計算,請參閱 https://huggingface.co/papers/2406.02528v1。然而,目前的實現是一個概念驗證,其中稀疏性並未用於提高速度或減少記憶體使用。使用稀疏矩陣通常不會降低效能,甚至可能有助於減少過擬合。預設為 `False`。 - very_sparse (
bool
) — 是否使用 RandLora 論文中描述的高度稀疏的隨機基。極稀疏基是三元稀疏基(僅包含-1、0和1),對於一個最小維度為D的矩陣,-1和1的分配機率為1/√D,0的分配機率為1-2/√D。使用這些稀疏矩陣可以比 `sparse` 選項進一步減少過擬合,但很可能會因此降低效能。請謹慎使用。預設為 `False`。 - randlora_dropout (
float
) — RandLora 層的 dropout 機率。 - randlora_alpha (
float
) — RandLora 層的縮放係數,通常是秩的 20 倍。由於 `randlora_alpha` 係數預設較大,可能導致數值不穩定,尤其是在學習率較高時。如果訓練不穩定,請考慮降低學習率或 `randlora_alpha` 係數。 - fan_in_fan_out (
bool
) — 如果要替換的層儲存權重的方式是 (fan_in, fan_out),則設定為 True。例如,gpt-2 使用 `Conv1D`,其權重儲存方式為 (fan_in, fan_out),因此應設定為 `True`。 - bias (
str
) — 偏置型別。可以是 'none'、'all' 或 'randlora_only'。如果為 'all' 或 'randlora_only',則相應的偏置將在訓練期間更新。請注意,這意味著即使停用介面卡,模型的輸出也不會與未進行適配的基礎模型相同。 - modules_to_save (
list[str]
) — 除了 RandLora 層之外,需要設定為可訓練並在最終檢查點中儲存的模組列表。 - init_weights (
bool
) — 是否使用預設初始化來初始化 RandLora 層的權重。除非你確切知道自己在做什麼,否則不要更改此設定。 - layers_to_transform (
Union[list[int],int]
) — 要轉換的層索引,如果指定此引數,它將在指定列表中的層索引上應用 RandLora 轉換。如果傳遞單個整數,它將在此索引的層上應用 RandLora 轉換。 - layers_pattern (
str
) — 層模式名稱,僅在 `layers_to_transform` 不為 `None` 且層模式不在常見層模式中時使用。
這是用於儲存 RandLoraModel 配置的配置類。
RandLoraModel
class peft.RandLoraModel
< 原始碼 >( model peft_config: Union[PeftConfig, dict[str, PeftConfig]] adapter_name: str low_cpu_mem_usage: bool = False state_dict: Optional[dict[str, torch.Tensor]] = None ) → torch.nn.Module
引數
- model (
PreTrainedModel
) — 要適配的模型。 - config (RandLoraConfig) — RandLora 模型的配置。
- adapter_name (
str
) — 介面卡的名稱,預設為 `"default"`。 - low_cpu_mem_usage (
bool
,可選
, 預設為 `False`) — 在元裝置上建立空的介面卡權重。有助於加快載入過程。
返回
torch.nn.Module
RandLora 模型。
從預訓練的 transformers 模型建立 RandLoRA 模型。
示例
>>> from transformers import AutoModelForCausalLM
>>> from peft import RandLoraConfig, get_peft_model
>>> base_model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m")
>>> config = RandLoraConfig(r=32)
>>> model = get_peft_model(base_model, config)
屬性:
- model (
PreTrainedModel
) — 需要被適配的模型。 - peft_config (RandLoraConfig):RandLora 模型的配置。
刪除一個現有的介面卡。
merge_and_unload
< 原始碼 >( progressbar: bool = False safe_merge: bool = False adapter_names: Optional[list[str]] = None )
此方法將 RandLora 層合併到基礎模型中。如果有人想將基礎模型用作獨立模型,則需要此方法。
示例
>>> from transformers import AutoModelForCausalLM
>>> from peft import PeftModel
>>> base_model = AutoModelForCausalLM.from_pretrained("tiiuae/falcon-40b")
>>> peft_model_id = "smangrul/falcon-40B-int4-peft-lora-sfttrainer-sample"
>>> model = PeftModel.from_pretrained(base_model, peft_model_id)
>>> merged_model = model.merge_and_unload()
透過移除所有 RandLora 模組而不進行合併,恢復基礎模型。這將返回原始的基礎模型。