Transformers 文档

使用 🤗 PEFT 加载适配器

使用 🤗 PEFT 加载适配器

Parameter-Efficient Fine Tuning (PEFT) 方法在微调期间冻结预训练模型参数,并在其基础上添加少量可训练参数(适配器)。适配器被训练以学习任务特定的信息。这种方法已被证明在计算使用较低的情况下非常节省内存,同时产生的结果与完全微调的模型相当。

使用PEFT训练的适配器通常也比完整模型小一个数量级,这使得它们便于共享、存储和加载。

The adapter weights for a OPTForCausalLM model stored on the Hub are only ~6MB compared to the full size of the model weights, which can be ~700MB.

如果您有兴趣了解更多关于🤗 PEFT库的信息,请查看文档

设置

通过安装🤗 PEFT开始:

pip install peft

如果你想尝试全新的功能,你可能会对从源代码安装库感兴趣:

pip install git+https://github.com/huggingface/peft.git

支持的PEFT模型

🤗 Transformers 原生支持一些 PEFT 方法,这意味着您可以加载存储在本地或 Hub 上的适配器权重,并通过几行代码轻松运行或训练它们。支持以下方法:

如果你想使用其他PEFT方法,例如提示学习或提示调优,或者想了解🤗 PEFT库的更多信息,请参考文档

加载一个PEFT适配器

要从🤗 Transformers加载并使用PEFT适配器模型,请确保Hub存储库或本地目录包含adapter_config.json文件和适配器权重,如上图示例所示。然后,您可以使用AutoModelFor类加载PEFT适配器模型。例如,要加载用于因果语言建模的PEFT适配器模型:

  1. 指定PEFT模型ID
  2. 将其传递给AutoModelForCausalLM
from transformers import AutoModelForCausalLM, AutoTokenizer

peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id)

你可以使用AutoModelFor类或基础模型类如OPTForCausalLMLlamaForCausalLM来加载PEFT适配器。

你也可以通过调用load_adapter方法来加载一个PEFT适配器:

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)

查看下面的API文档部分以获取更多详细信息。

以8位或4位加载

bitsandbytes 集成支持8位和4位精度的数据类型,这对于加载大型模型非常有用,因为它可以节省内存(请参阅 bitsandbytes 集成 指南 以了解更多信息)。将 load_in_8bitload_in_4bit 参数添加到 from_pretrained() 并设置 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))

添加一个新的适配器

你可以使用~peft.PeftModel.add_adapter向已经存在适配器的模型添加一个新的适配器,只要新适配器与当前适配器类型相同。例如,如果你已经有一个LoRA适配器附加到模型上:

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

添加一个新的适配器:

# attach new adapter with same config
model.add_adapter(lora_config, adapter_name="adapter_2")

现在你可以使用 ~peft.PeftModel.set_adapter 来设置使用哪个适配器:

# use adapter_1
model.set_adapter("adapter_1")
output_disabled = model.generate(**inputs)
print(tokenizer.decode(output_disabled[0], skip_special_tokens=True))

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

要禁用适配器模块:

model.disable_adapters()
output = model.generate(**inputs)

训练一个PEFT适配器

PEFT适配器由Trainer类支持,因此您可以为您的特定用例训练一个适配器。只需要添加几行代码即可。例如,要训练一个LoRA适配器:

如果你不熟悉使用Trainer微调模型,请查看微调预训练模型教程。

  1. 使用任务类型和超参数定义您的适配器配置(有关超参数作用的更多详细信息,请参见~peft.LoraConfig)。
from peft import LoraConfig

peft_config = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.1,
    r=64,
    bias="none",
    task_type="CAUSAL_LM",
)
  1. 将适配器添加到模型中。
model.add_adapter(peft_config)
  1. 现在你可以将模型传递给Trainer
trainer = Trainer(model=model, ...)
trainer.train()

保存您训练好的适配器并重新加载它:

model.save_pretrained(save_dir)
model = AutoModelForCausalLM.from_pretrained(save_dir)

向PEFT适配器添加额外的可训练层

你也可以通过在PEFT配置中传递modules_to_save来微调附加的可训练适配器,这些适配器附加在已经带有适配器的模型上。例如,如果你想在带有LoRA适配器的模型上微调lm_head:

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"],
    modules_to_save=["lm_head"],
)

model.add_adapter(lora_config)

API 文档

transformers.integrations.PeftAdapterMixin

< >

( )

一个包含所有用于加载和使用PEFT库支持的适配器权重的函数的类。有关适配器及其在基于变压器的模型上注入的更多详细信息,请查看PEFT库的文档:https://huggingface.co/docs/peft/index

目前支持的PEFT方法都是非前缀调优方法。以下是支持的PEFT方法列表,任何人都可以使用这个mixin类加载、训练和运行:

其他PEFT模型,如提示调优、提示学习不在范围内,因为这些适配器不能“注入”到torch模块中。要使用这些方法,请参考PEFT库的使用指南。

使用这个mixin,如果安装了正确的PEFT版本,可以实现以下功能:

  • 加载存储在本地路径或远程Hub仓库中的适配器,并将其注入到模型中
  • 在模型中附加新的适配器,并使用Trainer或自行训练它们。
  • 附加多个适配器并迭代地激活/停用它们
  • 激活/停用模型中的所有适配器。
  • 获取活动适配器的state_dict

load_adapter

< >

( peft_model_id: typing.Optional[str] = None adapter_name: typing.Optional[str] = None revision: typing.Optional[str] = None token: typing.Optional[str] = None device_map: typing.Optional[str] = 'auto' max_memory: typing.Optional[str] = None offload_folder: typing.Optional[str] = None offload_index: typing.Optional[int] = None peft_config: typing.Dict[str, typing.Any] = None adapter_state_dict: typing.Optional[typing.Dict[str, ForwardRef('torch.Tensor')]] = None low_cpu_mem_usage: bool = False is_trainable: bool = False adapter_kwargs: typing.Optional[typing.Dict[str, typing.Any]] = None )

参数

  • peft_model_id (str, optional) — 在Hub上查找的模型标识符,或保存的适配器配置文件和适配器权重的本地路径。
  • adapter_name (str, optional) — 使用的适配器名称。如果未设置,将使用默认适配器。
  • revision (str, optional, defaults to "main") — The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a git-based system for storing models and other artifacts on huggingface.co, so revision can be any identifier allowed by git.

    要测试你在Hub上提交的拉取请求,你可以传递revision="refs/pr/"

  • token (str, optional) — 是否使用认证令牌来加载远程文件夹。对于加载HuggingFace Hub上的私有仓库非常有用。您可能需要调用huggingface-cli login并粘贴您的令牌以缓存它。
  • device_map (str or Dict[str, Union[int, str, torch.device]] or int or torch.device, optional) — A map that specifies where each submodule should go. It doesn’t need to be refined to each parameter/buffer name, once a given module name is inside, every submodule of it will be sent to the same device. If we only pass the device (e.g., "cpu", "cuda:1", "mps", or a GPU ordinal rank like 1) on which the model will be allocated, the device map will map the entire model to this device. Passing device_map = 0 means put the whole model on GPU 0.

    要让 Accelerate 自动计算最优化的 device_map,请设置 device_map="auto"。有关每个选项的更多信息,请参阅 设计设备映射.

  • max_memory (Dict, 可选) — 一个字典设备标识符到最大内存。如果未设置,将默认为每个GPU的最大可用内存和可用的CPU RAM。
  • offload_folder (str or os.PathLike, optional) — 如果 device_map 包含任何值为 "disk",我们将卸载权重的文件夹。
  • offload_index (int, optional) — offload_index 参数将传递给 accelerate.dispatch_model 方法.
  • peft_config (Dict[str, Any], 可选) — 要添加的适配器的配置,支持的适配器是非前缀调优和适配提示方法。此参数用于用户直接传递PEFT状态字典的情况
  • adapter_state_dict (Dict[str, torch.Tensor], optional) — 要加载的适配器的状态字典。此参数用于用户直接传递PEFT状态字典的情况
  • low_cpu_mem_usage (bool, 可选, 默认为 False) — 在加载PEFT适配器时减少内存使用。这也应该会加快加载过程。 需要PEFT版本0.13.0或更高。
  • is_trainable (bool, 可选, 默认为 False) — 适配器是否应该可训练。如果为 False,适配器将被冻结,只能用于推理。
  • adapter_kwargs (Dict[str, Any], 可选) — 传递给适配器配置的from_pretrained方法和find_adapter_config_file方法的额外关键字参数。

从文件或远程Hub文件夹加载适配器权重。如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档中的更多信息:https://huggingface.co/docs/peft

需要peft作为后端来加载适配器权重。

add_adapter

< >

( adapter_config adapter_name: typing.Optional[str] = None )

参数

  • adapter_config (~peft.PeftConfig) — 要添加的适配器的配置,支持的适配器是非前缀调谐和适应提示方法
  • adapter_name (str, 可选, 默认为 "default") — 要添加的适配器的名称。如果没有传递名称,则会为适配器分配一个默认名称。

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

为当前模型添加一个新的适配器用于训练目的。如果没有传递适配器名称,则会为适配器分配一个默认名称,以遵循PEFT库的约定(在PEFT中,我们使用“default”作为默认适配器名称)。

set_adapter

< >

( adapter_name: typing.Union[typing.List[str], str] )

参数

  • adapter_name (Union[List[str], str]) — 要设置的适配器名称。也可以是一个字符串列表来设置多个适配器。

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

通过强制模型使用特定适配器并禁用其他适配器来设置特定适配器。

disable_adapters

< >

( )

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

禁用所有附加到模型的适配器。这将导致仅使用基础模型进行推断。

enable_adapters

< >

( )

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

启用附加到模型的适配器。

active_adapters

< >

( )

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

获取模型的当前活动适配器。在多适配器推理(组合多个适配器进行推理)的情况下,返回所有活动适配器的列表,以便用户可以相应地处理它们。

对于之前的PEFT版本(不支持多适配器推理),module.active_adapter 将返回一个单一的字符串。

get_adapter_state_dict

< >

( adapter_name: typing.Optional[str] = None )

参数

  • adapter_name (str, 可选) — 获取状态字典的适配器名称。如果未传递名称,则使用当前活动的适配器。

如果您不熟悉适配器和PEFT方法,我们邀请您阅读PEFT官方文档以了解更多信息:https://huggingface.co/docs/peft

获取应仅包含指定adapter_name适配器的权重张量的适配器状态字典。 如果未传递adapter_name,则使用当前活动的适配器。

< > Update on GitHub