适配器注入
使用 PEFT,您可以在任何torch
模块中注入可训练的适配器,这使您能够使用适配器方法,而无需依赖 PEFT 中的建模类。目前,PEFT 支持将 LoRA、AdaLoRA 和 IA3 注入模型,因为对于这些适配器来说,模型的原地修改足以对其进行微调。
请查看下表以了解何时应注入适配器。
优点 | 缺点 |
---|---|
模型原地修改,保留所有原始属性和方法 | 手动编写 Hugging Face 的from_pretrained 和save_pretrained 实用程序函数以保存和加载适配器 |
适用于任何torch 模块和模态 | 不适用于PeftModel 提供的任何实用程序方法,例如禁用和合并适配器 |
创建新的 PEFT 模型
要执行适配器注入,请使用 inject_adapter_in_model() 方法。此方法接受三个参数:PEFT 配置、模型和可选的适配器名称。您还可以通过多次调用 inject_adapter_in_model()(使用不同的适配器名称)将多个适配器附加到模型。
例如,要将 LoRA 适配器注入 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)
打印模型以查看适配器是否已正确注入。
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) )
保存模型
要只保存适配器,请使用 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)
如果注入适配器速度很慢或您需要加载大量适配器,则可以使用一项优化,它允许在元设备上创建“空”适配器,并且只有在调用 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