PEFT 文件

Adapter 注入

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Adapter 注入

使用 PEFT,您可以將可訓練的 Adapter 注入到任何 torch 模組中,這使您無需依賴 PEFT 中的模型類即可使用 Adapter 方法。這適用於除基於提示學習(例如字首調優或 p-tuning)之外的所有 Adapter。

查看下錶,瞭解何時應注入 Adapter。

優點 缺點
模型被原地修改,保留所有原始屬性和方法 從 Hugging Face 手動編寫 from_pretrainedsave_pretrained 實用程式函式來儲存和載入 Adapter
適用於任何 torch 模組和模態 不適用於 PeftModel 提供的任何實用程式方法,例如停用和合並 Adapter

建立一個新的 PEFT 模型

要執行 Adapter 注入,請使用 inject_adapter_in_model() 方法。此方法接受 3 個引數:PEFT 配置、模型和一個可選的 Adapter 名稱。如果使用不同的 Adapter 名稱多次呼叫 inject_adapter_in_model(),還可以將多個 Adapter 附加到模型中。

例如,要將 LoRA Adapter 注入到 DummyModel 模組的 linear 子模組中:

import torch
from peft import inject_adapter_in_model, LoraConfig

class DummyModel(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.embedding = torch.nn.Embedding(10, 10)
        self.linear = torch.nn.Linear(10, 10)
        self.lm_head = torch.nn.Linear(10, 10)

    def forward(self, input_ids):
        x = self.embedding(input_ids)
        x = self.linear(x)
        x = self.lm_head(x)
        return x


lora_config = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.1,
    r=64,
    bias="none",
    target_modules=["linear"],
)

model = DummyModel()
model = inject_adapter_in_model(lora_config, model)

dummy_inputs = torch.LongTensor([[0, 1, 2, 3, 4, 5, 6, 7]])
dummy_outputs = model(dummy_inputs)

列印模型以檢視 Adapter 是否已正確注入。

DummyModel(
  (embedding): Embedding(10, 10)
  (linear): Linear(
    in_features=10, out_features=10, bias=True
    (lora_dropout): ModuleDict(
      (default): Dropout(p=0.1, inplace=False)
    )
    (lora_A): ModuleDict(
      (default): Linear(in_features=10, out_features=64, bias=False)
    )
    (lora_B): ModuleDict(
      (default): Linear(in_features=64, out_features=10, bias=False)
    )
    (lora_embedding_A): ParameterDict()
    (lora_embedding_B): ParameterDict()
  )
  (lm_head): Linear(in_features=10, out_features=10, bias=True)
)

基於 state_dict 的注入

有時,可能會有一個 PEFT Adapter 檢查點,但由於某種原因不知道相應的 PEFT 配置。要為此檢查點注入 PEFT 層,通常需要基於檢查點的 state_dict 對相應的 PEFT 配置進行逆向工程,最主要的是 target_modules 引數。這可能很繁瑣且容易出錯。為避免這種情況,也可以呼叫 inject_adapter_in_model() 並將載入的 state_dict 作為引數傳遞:

from safetensors.torch import load_file

model = ...
state_dict = load_file(<path-to-safetensors-file>)
lora_config = LoraConfig(...)
model = inject_adapter_in_model(lora_config, model, state_dict=state_dict)

在這種情況下,PEFT 將使用 state_dict 作為目標層的參考,而不是使用 PEFT 配置。作為使用者,您不必為 PEFT 配置設定確切的 target_modules 也能使其工作。但是,您仍應傳遞正確型別的 PEFT 配置,在此示例中為 LoraConfig,您可以將 target_modules 設定為 None

請注意,這仍然只建立未初始化的 PEFT 層,state_dict 中的值不會用於填充模型權重。要填充權重,請繼續呼叫如下所述的 set_peft_model_state_dict()

⚠️ 請注意,如果 PEFT 配置中的配置與 state_dict 中發現的內容不匹配,PEFT 會警告您。如果您知道 PEFT 配置沒有正確指定,可以忽略該警告。

如果原始 PEFT Adapter 使用的是 target_parameters 而不是 target_modules,那麼從 state_dict 注入將無法正常工作。在這種情況下,必須使用正確的 PEFT 配置進行注入。

儲存模型

要僅儲存 Adapter,請使用 get_peft_model_state_dict() 函式:

from peft import get_peft_model_state_dict

peft_state_dict = get_peft_model_state_dict(model)
print(peft_state_dict)

否則,model.state_dict() 返回模型的完整狀態字典。

載入模型

載入已儲存的 state_dict 後,可以使用 set_peft_model_state_dict() 函式應用它:

from peft import set_peft_model_state_dict

model = DummyModel()
model = inject_adapter_in_model(lora_config, model)
outcome = set_peft_model_state_dict(model, peft_state_dict)
# check that there were no wrong keys
print(outcome.unexpected_keys)

如果注入 Adapter 的速度很慢,或者您需要載入大量的 Adapter,您可以使用一種最佳化方法,該方法允許在元裝置上建立一個“空” Adapter,並且僅在呼叫 set_peft_model_state_dict() 時才用真實權重填充權重。為此,請將 low_cpu_mem_usage=True 傳遞給 inject_adapter_in_model()set_peft_model_state_dict()

model = DummyModel()
model = inject_adapter_in_model(lora_config, model, low_cpu_mem_usage=True)

print(model.linear.lora_A["default"].weight.device.type == "meta")  # should be True
set_peft_model_state_dict(model, peft_state_dict, low_cpu_mem_usage=True)
print(model.linear.lora_A["default"].weight.device.type == "cpu")  # should be True
< > 在 GitHub 上更新

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