赞
踩
官网简介如下图:
翻译过来是:低秩自适应(LoRA)是一种PEFT方法,它将一个大矩阵在注意层分解成两个较小的低秩矩阵。这大大减少了需要微调的参数数量。
说的只是针对注意力层,其实我自己平时微调操作注意力层+多层感知机层,感觉所有层都可以微调。在阿里的千问开源的模型文档上也看到微调的并不只有注意力层,不知道微调加入其它层效果会不会更好?
PEFT LoRA 所有的参数说明如下:
- r (int)
- # Lora 注意力维度(“秩”)。
-
- target_modules (Optional[Union[List[str], str]])
- # 要应用适配器的模块名称。
- # 如果指定了此参数,则仅替换具有指定名称的模块。
- # 传递字符串时,将执行正则表达式匹配。
- # 传递字符串列表时,将执行精确匹配或检查模块名称是否以任何传递的字符串结尾。
- # 如果指定为‘all-linear’,则选择所有线性/Conv1D模块,不包括输出层。
- # 如果未指定,则根据模型架构选择模块。
- # 如果架构未知,则会引发错误——在这种情况下,应手动指定目标模块。
-
- lora_alpha (int)
- # Lora 缩放的 alpha 参数。
-
- lora_dropout (float)
- # Lora 层的 dropout 概率。
-
- fan_in_fan_out (bool)
- # 如果要替换的层存储权重格式为 (fan_in, fan_out),则设置为 True。
- # 例如,gpt-2 使用的 Conv1D 存储权重格式为 (fan_in, fan_out),因此应设置为 True。
-
- bias (str)
- # LoRA 的偏置类型。可以是 ‘none’,‘all’ 或 ‘lora_only’。
- # 如果是 ‘all’ 或 ‘lora_only’,则相应的偏置将在训练期间更新。
- # 请注意,这意味着即使禁用适配器,模型也不会生成与未适配的基础模型相同的输出。
-
- use_rslora (bool)
- # 设置为 True 时,使用 Rank-Stabilized LoRA,将适配器缩放因子设置为 lora_alpha/数学.sqrt(r)。
- # 因为这被证明效果更好。否则,将使用 lora_alpha/r 的原始默认值。
-
- modules_to_save (List[str])
- # 除适配器层外要设置为可训练并在最终检查点中保存的模块列表。
-
- init_lora_weights (bool | Literal["gaussian", "olora", "pissa", "pissa_niter_[number of iters]", "loftq"])
- # 如何初始化适配器层的权重。
- # 传递 True(默认值)会使用微软参考实现中的默认初始化。
- # 传递 ‘gaussian’ 会使用按 LoRA 秩缩放的高斯初始化。
- # 设置初始化为 False 会导致完全随机初始化,不推荐使用。
- # 传递 ‘loftq’ 使用 LoftQ 初始化。传递 ‘olora’ 使用 OLoRA 初始化。
- # 传递 ‘pissa’ 使用主奇异值和奇异向量适应(PiSSA)初始化,比 LoRA 收敛更快,最终性能更佳。
- # ‘pissa_niter_[number of iters]’ 使用基于快速 SVD 的 PiSSA 初始化,[number of iters] 表示执行 FSVD 的子空间迭代次数,必须是非负整数。
- # 当设置为 16 时,可以在几秒内完成 7B 模型的初始化,训练效果大致相当于使用 SVD。
-
- layers_to_transform (Union[List[int], int])
- # 要转换的层索引。
- # 如果传递了整数列表,则会对列表中指定的层索引应用适配器。
- # 如果传递单个整数,则会对该索引处的层应用转换。
-
- layers_pattern (str)
- # 层模式名称,仅在 layers_to_transform 不为 None 时使用。
-
- rank_pattern (dict)
- # 层名称或正则表达式到与默认 r 指定的秩不同的秩的映射。
-
- alpha_pattern (dict)
- # 层名称或正则表达式到与 lora_alpha 指定的默认 alpha 不同的 alpha 的映射。
-
- megatron_config (Optional[dict])
- # Megatron 的 TransformerConfig 参数,用于创建 LoRA 的并行线性层。
- # 可以这样获取:core_transformer_config_from_args(get_args()),这两个函数来自 Megatron。
- # 这些参数将用于初始化 Megatron 的 TransformerConfig。
- # 当要将 LoRA 应用于 megatron 的 ColumnParallelLinear 和 RowParallelLinear 层时,需要指定此参数。
-
- megatron_core (Optional[str])
- # 要使用的 Megatron 核心模块,默认为 "megatron.core"。
-
- loftq_config (Optional[LoftQConfig])
- # LoftQ 的配置。
- # 如果不为 None,则使用 LoftQ 量化骨干权重并初始化 Lora 层,同时传递 init_lora_weights='loftq'。
- # 请注意,在这种情况下,不应传递量化模型,因为 LoftQ 会自行量化模型。
-
- use_dora (bool)
- # 启用 “权重分解低秩适应”(DoRA)。
- # 此技术将权重更新分解为两个部分:幅度和方向。
- # 方向由普通 LoRA 处理,幅度由单独的可学习参数处理。
- # 这可以在低秩下提高 LoRA 的性能。
- # 目前,DoRA 仅支持线性和 Conv2D 层。DoRA 比纯 LoRA 引入更大的开销,因此建议在推理时合并权重。
- # 更多信息,请参见 https://arxiv.org/abs/2402.09353。
-
- layer_replication (List[Tuple[int, int]])
- # 通过根据指定的范围堆叠原始模型层来构建新的层堆栈。
- # 这允许在不复制基础模型权重的情况下扩展(或缩小)模型。
- # 新层将全部附有单独的 LoRA 适配器。
-
- runtime_config (LoraRuntimeConfig)
- # 运行时配置(不保存或恢复)。
在一个基础模型上创建一个低秩的模型(要微调的模型):
- from transformers import AutoModelForSeq2SeqLM
- from peft import LoraModel, LoraConfig
-
- # 设置 LoRA 配置
- config = LoraConfig(
- task_type="SEQ_2_SEQ_LM", # 任务类型为序列到序列语言模型
- r=8, # LoRA 的秩
- lora_alpha=32, # LoRA 的缩放因子
- target_modules=["q", "v"], # 目标模块列表
- lora_dropout=0.01, # LoRA 层的 dropout 概率
- )
-
- # 加载预训练的 T5 基础模型
- model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")
-
- # 创建 LoRA 模型
- lora_model = LoraModel(model, config, "default")
配置低秩模型参数
- import torch
- import transformers
- from peft import LoraConfig, PeftModel, get_peft_model, prepare_model_for_kbit_training
-
- # 设置 LoRA 参数
- rank = ...
- target_modules = ["q_proj", "k_proj", "v_proj", "out_proj", "fc_in", "fc_out", "wte"]
- config = LoraConfig(
- r=4, # LoRA 的秩
- lora_alpha=16, # LoRA 的缩放因子
- target_modules=target_modules, # 目标模块列表
- lora_dropout=0.1, # LoRA 层的 dropout 概率
- bias="none", # 无偏置
- task_type="CAUSAL_LM" # 任务类型为因果语言模型
- )
-
- # 设置量化配置
- quantization_config = transformers.BitsAndBytesConfig(load_in_8bit=True)
-
- # 加载分词器
- tokenizer = transformers.AutoTokenizer.from_pretrained(
- "kakaobrain/kogpt",
- revision="KoGPT6B-ryan1.5b-float16", # 或者使用 float32 版本:revision=KoGPT6B-ryan1.5b
- bos_token="[BOS]", # 句子开头标记
- eos_token="[EOS]", # 句子结束标记
- unk_token="[UNK]", # 未知标记
- pad_token="[PAD]", # 填充标记
- mask_token="[MASK]" # 掩码标记
- )
-
- # 加载预训练的 GPT-J 模型
- model = transformers.GPTJForCausalLM.from_pretrained(
- "kakaobrain/kogpt",
- revision="KoGPT6B-ryan1.5b-float16", # 或者使用 float32 版本:revision=KoGPT6B-ryan1.5b
- pad_token_id=tokenizer.eos_token_id, # 填充标记的 ID
- use_cache=False, # 不使用缓存
- device_map={"": rank}, # 设备映射
- torch_dtype=torch.float16, # 使用 float16 类型
- quantization_config=quantization_config # 量化配置
- )
-
- # 准备模型进行 k-bit 训练
- model = prepare_model_for_kbit_training(model)
-
- # 获取 LoRA 模型
- lora_model = get_peft_model(model, config)
为什么要创建低秩模型,不解释直接引用论文的一部分说明如下:
自然语言处理的一个重要范例是对一般领域数据进行大规模预训练,并适应特定的任务或领域。当我们预训练更大的模型时,重新训练所有模型参数的完全微调变得不太可行。以GPT-3 175B为例,部署独立的微调模型实例,每个实例都有175B参数,成本非常高。我们提出了低秩自适应(Low-Rank Adaptation, LoRA),它冻结了预训练的模型权重,并将可训练的秩分解矩阵注入到Transformer体系结构的每一层,从而大大减少了下游任务的可训练参数的数量。与经过Adam微调的GPT-3 175B相比,LoRA可以将可训练参数的数量减少10,000倍,GPU内存需求减少3倍。在RoBERTa、DeBERTa、GPT-2和GPT-3上,LoRA在模型质量方面的表现与微调相当或更好,尽管具有更少的可训练参数、更高的训练吞吐量,并且与适配器不同,没有额外的推理延迟。我们还对语言模型适应中的等级缺陷进行了实证研究,从而揭示了LoRA的有效性。我们发布了一个促进LoRA与PyTorch模型集成的包,并在此https URL上为RoBERTa、DeBERTa和GPT-2提供了我们的实现和模型检查点。
add_weighted_adapter 增加适配器
该方法的代码原形及参数说明 如下:
- def add_weighted_adapter(
- self,
- adapters: list[str],
- weights: list[float],
- adapter_name: str,
- combination_type: str = "svd",
- svd_rank: int | None = None,
- svd_clamp: int | None = None,
- svd_full_matrices: bool = True,
- svd_driver: str | None = None,
- density: float | None = None,
- majority_sign_method: Literal["total", "frequency"] = "total",
- ) -> None:
- """
- 该方法通过合并给定的适配器及其权重来添加新的适配器。
- 使用 `cat` 合并类型时,应注意生成适配器的秩将等于所有适配器秩的总和。因此,混合适配器可能会变得过大,从而导致 OOM 错误。
- 参数:
- adapters (`list`):
- 要合并的适配器名称列表。
- weights (`list`):
- 每个适配器的权重列表。
- adapter_name (`str`):
- 新适配器的名称。
- combination_type (`str`):
- 合并类型,可以是 [`svd`, `linear`, `cat`, `ties`, `ties_svd`, `dare_ties`, `dare_linear`,
- `dare_ties_svd`, `dare_linear_svd`, `magnitude_prune`, `magnitude_prune_svd`] 中的一个。
- 使用 `cat` 合并类型时,生成适配器的秩等于所有适配器秩的总和(混合适配器可能会变得过大,导致 OOM 错误)。
- svd_rank (`int`, *可选*):
- SVD 输出适配器的秩。如果未提供,将使用合并适配器的最大秩。
- svd_clamp (`float`, *可选*):
- 用于限制 SVD 分解输出的量化阈值。如果未提供,则不执行限制。默认为 None。
- svd_full_matrices (`bool`, *可选*):
- 控制是计算完整 SVD 还是简化 SVD,从而影响返回的张量 U 和 Vh 的形状。默认为 True。
- svd_driver (`str`, *可选*):
- 要使用的 cuSOLVER 方法名称。此关键字参数仅在 CUDA 上合并时有效。
- 可以是 [None, `gesvd`, `gesvdj`, `gesvda`] 中的一个。更多信息请参阅 `torch.linalg.svd` 文档。默认为 None。
- density (`float`, *可选*):
- 取值范围在 0 到 1 之间。0 表示所有值都被剪除,1 表示没有值被剪除。
- 应与 [`ties`, `ties_svd`, `dare_ties`, `dare_linear`, `dare_ties_svd`, `dare_linear_svd`,
- `magnitude_prune`, `magnitude_prune_svd`] 一起使用。
- majority_sign_method (`str`):
- 获取符号值幅度的方法,应为 ["total", "frequency"] 中的一个。
- 应与 [`ties`, `ties_svd`, `dare_ties`, `dare_ties_svd`] 一起使用。
- """
delete_adapter 删除适配器
访方法代码原形如下:
- def delete_adapter(self, adapter_name: str) -> None:
- """
- Deletes an existing adapter.
- Args:
- adapter_name (str): Name of the adapter to be deleted.
- """
disable_adapter_layers 禁用所有适配器。
功能描述:当启用此功能时,模型中的所有适配器层将被禁用,模型将不再使用这些适配器进行推理或训练。此操作通常用于将模型恢复到没有适配器的状态,允许用户仅使用基础模型的功能。
用途场景:
实现机制:禁用适配器通常涉及调整模型的前向传播逻辑,确保适配器层的输出不被计算或直接返回基础模型的输出。
enable_adapter_layers 与调用disable_adapter_layers方法相反,启用所有适配器,通常这两个方法配套使用。
merge_and_unload 合并模型,最常用。
参数解释如下:
- progressbar (bool)
- # 是否显示指示卸载和合并过程的进度条。
-
- safe_merge (bool)
- # 是否启用安全合并检查,以检查适配器权重中是否存在潜在的 NaN 值。
-
- adapter_names (List[str], optional)
- # 要合并的适配器名称列表。如果为 None,则合并所有活动适配器。默认为 None。
merge_and_unload 方法原型:
- def merge_and_unload(
- self, progressbar: bool = False, safe_merge: bool = False, adapter_names: Optional[list[str]] = None
- ) -> torch.nn.Module:
- r"""
- This method merges the LoRa layers into the base model. This is needed if someone wants to use the base model
- as a standalone model.
- Args:
- progressbar (`bool`):
- whether to show a progressbar indicating the unload and merge process
- safe_merge (`bool`):
- whether to activate the safe merging check to check if there is any potential Nan in the adapter
- weights
- adapter_names (`List[str]`, *optional*):
- The list of adapter names that should be merged. If None, all active adapters will be merged. Defaults
- to `None`.
-
- """
使用示例:
- from transformers import AutoModelForCausalLM
- from peft import PeftModel
-
- # 从预训练模型中加载基础模型
- base_model = AutoModelForCausalLM.from_pretrained("tiiuae/falcon-40b")
-
- # PEFT 模型的 ID
- peft_model_id = "smangrul/falcon-40B-int4-peft-lora-sfttrainer-sample"
-
- # 从预训练模型和 PEFT 模型 ID 中加载 PEFT 模型
- model = PeftModel.from_pretrained(base_model, peft_model_id)
-
- # 合并 PEFT 模型并卸载不需要的部分
- merged_model = model.merge_and_unload()
unload 与 merge_and_unload 相反,把合并后的模型还原到基本模型
LoRA官网-> https://huggingface.co/docs/peft/package_reference/lora
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。