PEFT 文档

VB-LoRA:使用向量库的极限参数高效微调

Hugging Face's logo
加入 Hugging Face 社区

并获取增强的文档体验

开始使用

VB-LoRA:使用向量库的极限参数高效微调

概述

VB-LoRA 是一种参数高效的微调技术,它通过在子向量级别学习细粒度的参数共享方案来扩展 LoRA,从而实现显著更高的参数效率。这使得 VB-LoRA 在存储和传输成本至关重要的场景中尤其有用。它的工作原理是将低秩矩阵(来自不同层和模块,如 K、Q、V 和 FFN)分解为子向量,然后通过向量库全局共享这些子向量。

论文摘要如下:

随着大型语言模型的采用率不断提高,以及对每个用户或每个任务的模型定制需求不断增长,参数高效微调 (PEFT) 方法(如低秩自适应 (LoRA) 及其变体)会产生大量的存储和传输成本。为了进一步减少存储参数,我们引入了一种“分而治之”的范式,通过向量库全局共享参数,打破了跨矩阵维度、模块和层的低秩分解壁垒。作为该范式在 LoRA 上的实例化,我们提出的 VB-LoRA 通过可微分的 top-k 混合模块,从共享向量库中组合了 LoRA 的所有低秩矩阵。VB-LoRA 实现了极致的参数效率,同时保持了与最先进的 PEFT 方法相当甚至更好的性能。广泛的实验证明了 VB-LoRA 在自然语言理解、自然语言生成和指令调优任务上的有效性。在微调 Llama2-13B 模型时,VB-LoRA 仅使用了 LoRA 存储参数的 0.4%,但取得了更优越的结果。

使用技巧

  • VB-LoRA 利用稀疏 top-k 模块来学习共享机制。在保存适配器参数时,您可以设置 VBLoRAConfig 中的 save_only_topk_weights = True 来仅保存 top-k 权重及其索引,或者将其设置为 False 来保存所有可训练的 logits。启用 save_only_topk_weights = True 可以显著减少存储空间;例如,在 Llama2-7B 中,存储文件大小从 308MB 减少到 2.5MB。请注意,使用 save_only_topk_weights = True 保存的模型仅用于合并或推理,不能用于恢复训练。

  • VB-LoRA 有两组训练参数:向量库参数和 logit 参数。在实践中,我们发现 logit 参数需要更高的学习率,而向量库参数需要更低的学习率。当使用 AdamW 优化器时,logits 的典型学习率为 0.01,向量库参数的典型学习率为 0.001。

VBLoRAConfig

class peft.VBLoRAConfig

< >

( task_type: typing.Union[str, peft.utils.peft_types.TaskType, NoneType] = None peft_type: typing.Union[str, peft.utils.peft_types.PeftType, NoneType] = None auto_mapping: typing.Optional[dict] = None base_model_name_or_path: typing.Optional[str] = None revision: typing.Optional[str] = None inference_mode: bool = False r: int = 4 num_vectors: int = 256 vector_length: int = 256 topk: int = 2 target_modules: Optional[Union[list[str], str]] = None exclude_modules: Optional[Union[list[str], str]] = None save_only_topk_weights: bool = False vblora_dropout: float = 0.0 fan_in_fan_out: bool = False bias: str = 'none' modules_to_save: Optional[list[str]] = None init_vector_bank_bound: float = 0.02 init_logits_std: float = 0.1 layers_to_transform: Optional[Union[list[int], int]] = None layers_pattern: Optional[Union[list[str], str]] = None )

参数

  • r (int) — 增量矩阵的秩。
  • num_vectors (int) — 向量库中向量的数量。当模型尺寸增加时,使用更高的值。
  • vector_length (int) — 向量库中向量的长度。向量的长度应能被模型的隐藏维度整除。
  • topk (int) — Top-K 选择的 K 值。K 值越大,保存的模型尺寸越大。在实践中,设置 K=2 通常可提供最佳性能和参数效率。有关更多详细信息,请参阅论文中的讨论。
  • target_modules (Union[List[str], str]) — 要应用适配器的模块名称。如果指定此项,则仅替换具有指定名称的模块。当传递字符串时,将执行正则表达式匹配。当传递字符串列表时,将执行精确匹配,或者检查模块的名称是否以任何传递的字符串结尾。如果将其指定为“all-linear”,则将选择所有 linear/Conv1D 模块,但不包括输出层。如果未指定此项,则将根据模型架构选择模块。如果架构未知,则会引发错误 — 在这种情况下,您应手动指定目标模块。
  • exclude_modules (Optional[Union[List[str], str]]) — 不应用适配器的模块名称。当传递字符串时,将执行正则表达式匹配。当传递字符串列表时,将执行精确匹配,或者检查模块的名称是否以任何传递的字符串结尾。
  • save_only_topk_weights (bool) — 是否仅保存 topk 权重。设置 save_only_topk_weights = True 可以显著减少存储空间。但是,在此模式下保存的模型仅可用于合并或推理,而不能用于恢复训练。
  • vblora_dropout (float) — VBLoRA 层的 dropout 概率。
  • fan_in_fan_out (bool) — 如果要替换的层存储的权重类似于 (fan_in, fan_out),则设置为 True。例如,gpt-2 使用 Conv1D,它存储的权重类似于 (fan_in, fan_out),因此应将其设置为 True
  • bias (str) — VBLoRA 的偏置类型。可以是 ‘none’、‘all’ 或 ‘vblora_only’。如果为 ‘all’ 或 ‘vblora_only’,则在训练期间将更新相应的偏置。请注意,这意味着即使禁用适配器,模型也不会产生与未进行适配的基础模型相同的输出。
  • modules_to_save (List[str]) — 除 VBLoRA 层之外,要设置为可训练并在最终检查点中保存的模块列表。
  • init_vector_bank_bound (float) — 向量库使用 -init_vector_bank_bound 和 init_vector_bank_bound 之间的均匀分布进行初始化。避免使用全零初始化向量库,以防止零梯度。通常,像 0.02 这样的小值是有效的。使用较大的值初始化可能会导致训练不稳定。
  • init_logits_std (float) — logits 使用标准差为 init_logits_std 的正态分布进行初始化。默认为 0.1。
  • layers_to_transform (Union[List[int],int]) — 要转换的层索引。如果传递整数列表,它将适配器应用于此列表中指定的层索引。如果传递单个整数,它将在此索引处的层上应用转换。
  • layers_pattern (Optional[Union[List[str], str]]) — 层模式名称,仅当 layers_to_transformNone 不同时使用。这应针对模型的 nn.ModuleList,通常称为 'layers''h'

这是用于存储 VBLoRAConfig 配置的配置类。

论文: https://arxiv.org/abs/2405.15179

VBLoRAModel

class peft.VBLoRAModel

< >

( model config adapter_name low_cpu_mem_usage: bool = False ) torch.nn.Module

参数

  • model (PreTrainedModel) — 要适配的模型。
  • config (VBLoRAConfig) — VBLoRA 模型的配置。
  • adapter_name (str) — 适配器的名称,默认为 "default"
  • low_cpu_mem_usage (bool, optional, defaults to False) — 在 meta 设备上创建空适配器权重。有助于加速加载过程。

返回

torch.nn.Module

VBLoRA 模型。

从预训练的 transformers 模型创建 VBLoRA 模型。

该方法的详细描述请见 https://arxiv.org/abs/2405.15179

示例

>>> from transformers import AutoModelForCausalLM
>>> from peft import VBLoRAConfig, get_peft_model

>>> base_model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m")
>>> config = VBLoRAConfig(
...     task_type="SEQ_CLS",
...     r=4,
...     target_modules=["fc1", "fc2", "k_proj", "out_proj", "q_proj", "v_proj"],
...     num_vectors=60,
...     vector_length=256,
...     save_only_topk_weights=True,
... )
>>> model = get_peft_model(base_model, config)

属性:

delete_adapter

< >

( adapter_name: str )

参数

  • adapter_name (str) — 要删除的适配器的名称。

删除现有适配器。

disable_adapter_layers

< >

( )

禁用所有适配器。

当禁用所有适配器时,模型输出对应于基础模型的输出。

enable_adapter_layers

< >

( )

启用所有适配器。

如果您之前禁用了所有适配器并想要重新启用它们,请调用此方法。

get_nb_savable_parameters

< >

( adapter = 'default' )

返回可保存的 VB-LoRA 参数和其他可保存参数的数量。

merge_and_unload

< >

( progressbar: bool = False safe_merge: bool = False adapter_names: Optional[list[str]] = None )

参数

  • progressbar (bool) — 是否显示进度条以指示卸载和合并过程
  • safe_merge (bool) — 是否激活安全合并检查以检查适配器权重中是否存在任何潜在的 Nan
  • adapter_names (list[str], optional) — 应该合并的适配器名称列表。如果为 None,则将合并所有活动的适配器。默认为 None

此方法将 VBLoRA 层合并到基础模型中。如果有人想要将基础模型用作独立模型,则需要这样做。

示例

>>> from transformers import AutoModelForCausalLM
>>> from peft import PeftModel

>>> base_model = AutoModelForCausalLM.from_pretrained("tiiuae/falcon-40b")
>>> peft_model_id = "smangrul/falcon-40B-int4-peft-lora-sfttrainer-sample"
>>> model = PeftModel.from_pretrained(base_model, peft_model_id)
>>> merged_model = model.merge_and_unload()

print_savable_parameters

< >

( )

打印可保存的 VB-LoRA 参数的数量和总可保存参数。

set_adapter

< >

( adapter_name: str | list[str] )

参数

  • adapter_name (str or list[str]) — 要激活的适配器名称。

设置活动的适配器。

此外,此函数会将指定的适配器设置为可训练(即,requires_grad=True)。如果不需要这样做,请使用以下代码。

>>> for name, param in model_peft.named_parameters():
...     if ...:  # some check on name (ex. if 'lora' in name)
...         param.requires_grad = False

unload

< >

( )

通过删除所有 VBLoRA 模块但不合并,返回基础模型。这将返回原始基础模型。

< > Update on GitHub