PEFT 文档

Adapter 注入

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Adapter 注入

通过 PEFT,你可以将可训练的 adapters 注入到任何 torch 模块中,这允许你使用 adapter 方法,而无需依赖 PEFT 中的建模类。目前,PEFT 支持将 LoRAAdaLoRAIA3 注入到模型中,因为对于这些 adapters,模型的原地修改足以对其进行微调。

查看下表,了解何时应注入 adapters。

优点 缺点
模型被原地修改,保留所有原始属性和方法 手动编写 Hugging Face 的 from_pretrainedsave_pretrained 实用函数来保存和加载 adapters
适用于任何 torch 模块和模态 不适用于 PeftModel 提供的任何实用方法,例如禁用和合并 adapters

创建新的 PEFT 模型

要执行 adapter 注入,请使用 inject_adapter_in_model() 方法。此方法接受 3 个参数:PEFT 配置、模型和可选的 adapter 名称。如果使用不同的 adapter 名称多次调用 inject_adapter_in_model(),你也可以将多个 adapters 附加到模型。

例如,要将 LoRA adapters 注入到 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)

打印模型以查看 adapters 是否已正确注入。

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)
)

保存模型

要仅保存 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 的速度很慢,或者你需要加载大量 adapters,你可以使用一种优化方法,该方法允许在 meta 设备上创建“空” 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 上更新