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 的所有低秩矩阵。与最先进的 PEFT 方法相比,VB-LoRA 实现了极高的参数效率,同时保持了相当或更好的性能。大量的实验证明了 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”,则选择所有线性/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_transform` 不为 `None` 时使用。这应该针对模型的 `nn.ModuleList`,通常称为 `'layers'` 或 `'h'`。

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

论文:https://huggingface.co/papers/2405.15179

VBLoRAModel

class peft.VBLoRAModel

< >

( model peft_config: Union[PeftConfig, dict[str, PeftConfig]] adapter_name: str low_cpu_mem_usage: bool = False state_dict: Optional[dict[str, torch.Tensor]] = None ) torch.nn.Module

参数

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

返回

torch.nn.Module

VBLoRA 模型。

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

该方法在 https://huggingface.co/papers/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)

属性:

  • model (PreTrainedModel) — 需要被适配的模型。
  • peft_config (VBLoRAConfig):VBLoRAConfig 模型的配置。

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 模块来恢复基础模型,而不进行合并。这会返回原始的基础模型。

< > 在 GitHub 上更新