VB-LoRA:使用向量库的极端参数高效微调
概述
VB-LoRA 是一种参数高效的微调技术,它通过在子向量级别学习精细的参数共享方案来扩展 LoRA,从而实现更高的参数效率。这使得 VB-LoRA 在存储和传输成本至关重要的场景中特别有用。它的工作原理是将来自不同层和模块(如 K、Q、V 和 FFN)的低秩矩阵分解成子向量,然后通过向量库在全局范围内共享这些子向量。
论文摘要如下:
随着大型语言模型的采用不断增加,用户模型或任务模型定制的需求也在不断增长,参数高效微调 (PEFT) 方法(例如低秩自适应 (LoRA) 及其变体)会产生巨大的存储和传输成本。为了进一步减少存储参数,我们引入了一种“分而享之”范例,通过向量库全局共享参数,打破不同矩阵维度、模块及层间的低秩分解障碍。作为面向 LoRA 的范例,我们提出的 VB-LoRA 将 LoRA 的所有低秩矩阵与带有可微分的 top-k 混合模块的共享向量库进行组合。与最先进的 PEFT 方法相比,VB-LoRA 可实现极高的参数效率,同时保持相当或更好的性能表现。详尽的实验表明,VB-LoRA 在自然语言理解、自然语言生成和说明调整任务中具有很高的效率。在微调 Llama2-13B 模型时,VB-LoRA 仅使用了 LoRA 存储参数的 0.4%,却能实现更出色的效果。
使用技巧
VB-LoRA 利用稀疏 top-k 模块来学习共享机制。在保存适配器参数时,你既可以通过在 VBLoRAConfig 中将 save_only_topk_weights 设置为 True 来仅保存顶部 k 权重及其索引,也可以通过将其设置为 False 来保存所有可训练的逻辑。启用 save_only_topk_weights = True 可显著减少存储空间;例如,在 Llama2-7B 中,存储文件大小从 308MB 减小到 2.5MB。请注意,使用 save_only_topk_weights = True 保存的模型仅用于合并或推理,不能用于恢复训练。
VB-LoRA 具有两组训练参数:词向量参数和逻辑参数。在实践中,我们发现逻辑参数需要更高的学习率,而词向量参数需要更低的学习率。在使用 AdamW 优化器时,逻辑参数的典型学习率为 0.01,词向量参数的学习率为 0.001。
VBLoRAConfig
class peft.VBLoRAConfig
< 源代码 >( peft_type:Union = None auto_mapping:Optional = None base_model_name_or_path:Optional = None revision:Optional = None task_type:Union = None inference_mode:bool = False r:int = 4 num_vectors:int = 256 vector_length:int = 256 topk:int = 2 target_modules:Union = 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 = None init_vector_bank_bound:float = 0.02 init_logits_std:float = 0.1 layers_to_transform:Union = None layers_pattern:Union = None )
参数
- r (
int
) — 增量矩阵的秩。 - num_vectors (
int
) — 向量库中的向量数量。当模型大小增加时,使用更高的值。 - target_modules (
Union[List[str], str]
) — 要将适配器应用于的模块的名称。如果指定了此参数,则只会替换具有指定名称的模块。当传递一个字符串时,将执行一个正则表达式匹配。当传递字符串的列表时,将执行确切匹配或检查模块的名称是否以任何传递的字符串结尾。如果将其指定为“all-linear”,则选择所有 linear/Conv1D 模块,排除输出层。如果未指定此参数,则将根据模型架构选择模块。如果不知道架构,则将引发错误 — 在这种情况下,你应手动指定目标模块。 - save_only_topk_weights (
布尔值
) — 仅保存 topk 权重。设置save_only_topk_weights = True
会显著减少存储空间。但是,以这种模式保存的模型只能用于合并或推理,不能用于从头开始训练。 - vblora_dropout (
浮点
) — VBLoRA 层的 dropout 概率。 - modules_to_save (
List[str]
) — 要设置为可训练和保存在最终检查点中的 VBLoRA 层之外的模块的列表。 - init_vector_bank_bound (
float
) — 矢量库使用介于 -init_vector_bank_bound 和 init_vector_bank_bound 之间的均匀分布进行初始化。避免使用全 0 值初始化矢量库,以防止梯度为 0。通常情况下,0.02 等较小值较为有效。使用较大值进行初始化会导致训练不稳定。 - init_logits_std (
float
) — Logit 使用标准差为 init_logits_std 的正态分布进行初始化。默认为 0.1。 - layers_to_transform (
Union[List[int],int]
) — 要变换的层索引。如果传入列表格式的整数,它会将适配器应用于此列表中指定的层索引。如果传入单个整数,它会在该索引的层上应用变换。 - layers_pattern (
str
) — 层模式名称,仅在layers_to_transform
与None
不同时使用。
此为配置类,用于存储 VBLoRAConfig 的配置。
VBLoRAModel
类 peft.VBLoRAModel
< 源代码 >( model config adapter_name low_cpu_mem_usage: bool = False ) → torch.nn.Module
参数
- model (PreTrainedModel) — 将要被适配的模型。
- config (VBLoRAConfig) — VBLoRA 模型的配置。
返回
torch.nn.Module
VBLoRA 模型。
从预训练的 Transformer 模型创建 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)
属性:
- model (PreTrainedModel) — 要适配的模型。
- peft_config (VBLoRAConfig): VBLoRAConfig 模型的配置。
删除现有适配器。
返回可保存的 VB-LoRA 参数和其他可保存参数的数量。
merge_and_unload
< 源 > ( 进度: bool = False 安全合并: bool = False 适配器名称: 可选[str 列表] = 无 )
此方法将 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()
打印可保存 VB-LoRA 参数的数量和可保存参数总数。
set_adapter
< source > ( adapter_name: str | list[str] )
设置激活的适配器。
此外,此函数将指定适配器设置为可训练(即,requires_grad=True)。如果不需要这样做,请使用以下代码。
通过移除所有 VBLoRA 模块(不合并),来获得基础模型。这会返回原始基础模型。