首页 > 其他分享 >peft中使用多个adapter

peft中使用多个adapter

时间:2024-07-12 12:19:27浏览次数:6  
标签:多个 adapter print output model peft adapters

总览

比起从零训练或是全量微调,使用 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

相关文章