使用 🤗 PEFT 加载 adapters¶
PEFT(Parameter-Efficient Fine-Tuning)是一种高效微调预训练模型的方法。具体来说,在微调过程中,预训练模型的大部分参数都被冻结,通过添加少量可训练的参数(如 adapters、low-rank matrices 等),调整它们以适应特定任务,而无需对整个预训练模型进行微调。
Adapters 是一组轻量级的、可训练的参数,通常被添加到预训练模型的特定层中。由于 adapters 是独立的参数模块,通常比完整的模型小一个数量级,所以使其具有方便共享、存储和加载的特点。
如图所示,与完整尺寸的模型权重(约为700MB)相比,存储在 Hub 上的 OPTForCausalLM 模型的 adapter 权重仅约为 6MB:
通过使用 PEFT 和 adapters,可以在保持预训练模型大部分参数不变的情况下,高效地微调模型以适应特定任务,从而节省资源并提高性能。如果你对学习更多关于 🤗 PEFT库 感兴趣,请查看文档。
设置¶
peft 库是一个实现了参数高效微调(PEFT)方法的库,支持 LoRA(Low-Rank Adaptation)、Adapter Tuning、Prefix Tuning 等多种方法。
peft 库的核心组件:
- 配置类:如
LoraConfig、AdapterConfig等配置类,用于定义和配置特定的 PEFT adapter,它将所有 Adapter 相关的配置参数都封装在一个独立的对象中,使得可以轻松地调整 Adapter 的配置,而不需要修改模型的其他部分。 - 模型接口:提供了
add_adapter、freeze_model等方法,用于在模型中添加和配置 adapter。 - 训练工具:提供了训练和评估工具,帮助开发者高效地进行模型微调和评估。
首先安装 🤗 peft:
pip install peft
如果你想尝试全新的特性,需要源代码安装这个库:
pip install git+https://github.com/huggingface/peft.git
加载 PEFT adapter 模型¶
想从 huggingface 的 Transformers 库中加载并使用 PEFT adapter 模型,请确保 Hub 仓库或本地目录包含一个 adapter_config.json 文件和 adapter 权重。
确认存在后,可以使用 AutoModelFor 类加载 PEFT adapter 模型。例如,想要给一个因果语言建模加载一个 PEFT adapter 模型:
- 指定 PEFT 模型的 id
- 将其传递给 AutoModelForCausalLM 类
from transformers import AutoModelForCausalLM, AutoTokenizer
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id)
你可以使用 AutoModelFor 类或基础模型类(如 OPTForCausalLM 或 LlamaForCausalLM )来加载一个PEFT adapter。
你也可以通过 load_adapter 方法来加载 PEFT adapter。
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "facebook/opt-350m"
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(model_id)
model.load_adapter(peft_model_id)
基于8bit或4bit进行加载¶
bitsandbytes 集成支持8bit和4bit精度数据类型,这对于加载大模型非常有用,因为它可以节省内存(请参阅bitsandbytes指南以了解更多信息)。
想要有效地将模型分配到你的硬件,请在 from_pretrained() 中添加参数load_in_8bit或load_in_4bit,并设置device_map="auto":
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id, quantization_config=BitsAndBytesConfig(load_in_8bit=True))
添加新的 adapter¶
你可以使用peft.PeftModel.add_adapter方法为一个已有 adapter 的模型添加一个新的 adapter,只要新的 adapter 的类型与当前 adapter 相同即可。
例如,如果你想添加一个 LoRA adapter 到模型上:
from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import LoraConfig
model_id = "facebook/opt-350m"
model = AutoModelForCausalLM.from_pretrained(model_id)
lora_config = LoraConfig(
target_modules=["q_proj", "k_proj"],
init_lora_weights=False
)
model.add_adapter(lora_config, adapter_name="adapter_1")
添加一个新的 adapter:
# 使用相同配置连接新的 adapter,并取别名为 adapter_2
model.add_adapter(lora_config, adapter_name="adapter_2")
现在你可以使用 peft.PeftModel.set_adapter 来设置要使用的 adapter。
# 使用 adapter_1
model.set_adapter("adapter_1")
output = model.generate(**inputs)
print(tokenizer.decode(output_disabled[0], skip_special_tokens=True))
# 使用 adapter_2
model.set_adapter("adapter_2")
output_enabled = model.generate(**inputs)
print(tokenizer.decode(output_enabled[0], skip_special_tokens=True))
from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import PeftConfig
model_id = "facebook/opt-350m"
adapter_model_id = "ybelkada/opt-350m-lora"
tokenizer = AutoTokenizer.from_pretrained(model_id)
text = "Hello"
inputs = tokenizer(text, return_tensors="pt")
model = AutoModelForCausalLM.from_pretrained(model_id)
peft_config = PeftConfig.from_pretrained(adapter_model_id)
# to initiate with random weights
peft_config.init_lora_weights = False
model.add_adapter(peft_config)
model.enable_adapters()
output = model.generate(**inputs)
若想要禁用 adapter 模块:
model.disable_adapters()
output = model.generate(**inputs)
- 创建一个 LoraConfig 或其他适配器配置类的实例,并设置所需的超参数。
这里使用 PEFT 库中的 LoraConfig 类来配置 LoRA adapter,其中需要配置的超参数如下:
- lora_alpha:控制低秩矩阵的大小,通常称为 "rank" 或 "r"。在这个例子中,lora_alpha=16 指定了低秩矩阵的大小。
- lora_dropout:用于指定 dropout 的概率,lora_dropout=0.1 表示 dropout 的概率为 10%。
- r:表示低秩矩阵的秩。在这个例子中,r=64 指定了低秩矩阵的秩为 64。
- bias:用于指定是否添加偏差项。在这个例子中,bias="none" 表示不添加偏差项。
- task_type:用于指定任务的类型。在这个例子中,task_type="CAUSAL_LM" 表示任务是因果语言模型。
from peft import LoraConfig
peft_config = LoraConfig(
lora_alpha=16,
lora_dropout=0.1,
r=64,
bias="none",
task_type="CAUSAL_LM",
)
- 将 adapter 添加到模型中。
model.add_adapter(peft_config)
- 现在可以将添加了 adapter 的模型传递给 Trainer 进行训练了!
trainer = Trainer(..., model=model)
trainer.train()
保存训练好的 adapter 并重新加载它:
model.save_pretrained(save_dir)
model = AutoModelForCausalLM.from_pretrained(save_dir)