总览
比起从零训练或是全量微调,使用 peft 库对预训练模型进行微调是更经济的做法。adapter 是 peft 独有的概念,可向预训练模型添加的额外的少量可学习参数。
peft 库是支持对同一基础模型附上多个 adapters 的,但文档写得不是很明了。本文针对需要对多个 adapters 的情况进行说明。
所使用的 peft 库版本为 0.11.1。
添加与启用 adapter
可以对已经封装为 PeftModel
的模型调用 .add_adapter()
方法添加更多 adapters。
···
# 使用 get_peft_model 封装 model(顺便添加一个 adapter 名为 "memory_encoder")
model = get_peft_model(model, peft_config, adapter_name="memory_encoder")
# 然后再添加两个 adapters "get_memory_slot_num" 和 "memory_merge"
model.add_adapter(peft_config=peft_config, adapter_name="get_memory_slot_num")
model.add_adapter(peft_config=peft_config, adapter_name="memory_merge")
使用 .set_adapter("xxxx")
激活某一个 adapter,同时关闭其他所有 adapters。
model.set_adapter("memory_encoder")
# 用这行代码查看哪个 adapters 被激活
print(model.active_adapters)
关闭所有 adapter
peft 文档中提到,使用 model.disable_adapters()
来关闭所有 adapter。实测会出现错误:
ValueError: No adapter loaded. Please load an adapter first.
使用 model.get_base_model()
仍然获取不了关闭所有 adapter 的模型。几次实验下来,必须用 .disable_adapter()
上下文才能关闭:
with model.disable_adapter():
output_base = model(input).logits
实验代码
以下代码可以直观感受到如何正确使用多 adapter。
代码改编自这个 issue。注意,代码中对 LoraConfig 设置了 init_lora_weights=False
,这是为了让不同 adapter 的输出产生差异,方便观察。
import torch
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer
torch.manual_seed(0)
# model
model_id = "facebook/opt-125m"
model = AutoModelForCausalLM.from_pretrained(model_id)
# input
input = torch.tensor([[1, 2, 3, 4, 5]])
# base output
output_base = model(input).logits
print("Base model output:")
print(output_base[0, :3, :5])
# lora model, with two adapters
config = LoraConfig(
r=8,
init_lora_weights=False,
)
model_new = get_peft_model(model, config, adapter_name="adapter1")
model_new.add_adapter("adapter2", config)
# adapter1 output
model_new.set_adapter("adapter1")
output_adapter1 = model_new(input).logits
print("Model output after loading adapter1:")
print(output_adapter1[0, :3, :5])
# adapter2 output
model_new.set_adapter("adapter2")
output_adapter2 = model_new(input).logits
print("Model output after setting adapter2:")
print(output_adapter2[0, :3, :5])
# base output, using `.disable_adapter()`
with model_new.disable_adapter():
output_base = model_new.get_base_model()(input).logits
print("Model output after disabling adapters:")
print(output_base[0, :3, :5])
输出如下,
Base model output:
tensor([[-3.9463, -3.9443, 3.2428, -3.9522, 5.4978],
[-3.7805, -3.7759, 5.7177, -3.7743, 4.9581],
[ 2.1029, 2.1002, 1.9693, 2.0843, 3.4022]],
grad_fn=<SliceBackward0>)
Model output after loading adapter1:
tensor([[-4.3453, -4.3408, 3.1605, -4.3554, 5.1735],
[-6.6361, -6.6226, 5.1298, -6.6439, 4.8503],
[-5.7428, -5.7319, 1.3401, -5.7514, 3.2514]],
grad_fn=<SliceBackward0>)
Model output after setting adapter2:
tensor([[-2.7773, -2.7804, 3.6311, -2.7796, 4.8852],
[-4.9475, -4.9557, 6.4802, -4.9422, 3.2613],
[-3.2183, -3.2340, 1.6089, -3.2155, 2.9233]],
grad_fn=<SliceBackward0>)
Model output after disabling adapters:
tensor([[-3.9463, -3.9443, 3.2428, -3.9522, 5.4978],
[-3.7805, -3.7759, 5.7177, -3.7743, 4.9581],
[ 2.1029, 2.1002, 1.9693, 2.0843, 3.4022]])
可以发现 adapter 切换有效,关闭 adapter 的输出与原模型输出相同。
标签:多个,adapter,print,output,model,peft,adapters From: https://www.cnblogs.com/chirp/p/18298086