PEFT LoRA 介绍(LoRA微调使用的参数及方法)

news2024/11/24 2:01:26

一 PEFT LoRA 介绍

官网简介如下图:

翻译过来是:低秩自适应(LoRA)是一种PEFT方法,它将一个大矩阵在注意层分解成两个较小的低秩矩阵。这大大减少了需要微调的参数数量。

说的只是针对注意力层,其实我自己平时微调操作注意力层+多层感知机层,感觉所有层都可以微调。在阿里的千问开源的模型文档上也看到微调的并不只有注意力层,不知道微调加入其它层效果会不会更好?

二  PEFT LoRA 参数

 1 PEFT LoRA 参数

    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)
# 运行时配置(不保存或恢复)。

2 参数使用示例

    在一个基础模型上创建一个低秩的模型(要微调的模型):

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提供了我们的实现和模型检查点。

3 model低秩模型的方法

  1 add_weighted_adapter 

  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`] 一起使用。
    """

2 delete_adapter

  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.
        """
3 disable_adapter_layers

 disable_adapter_layers 禁用所有适配器。

  • 功能描述:当启用此功能时,模型中的所有适配器层将被禁用,模型将不再使用这些适配器进行推理或训练。此操作通常用于将模型恢复到没有适配器的状态,允许用户仅使用基础模型的功能。

  • 用途场景

    • 模型评估:在评估模型性能时,希望验证基础模型的原始性能,而不受适配器的影响。
    • 调试:在调试过程中,禁用适配器可以帮助识别适配器对模型输出的具体影响。
    • 资源管理:禁用适配器可以减少计算资源的消耗,尤其是在内存受限的环境中。
  • 实现机制:禁用适配器通常涉及调整模型的前向传播逻辑,确保适配器层的输出不被计算或直接返回基础模型的输出。

4 enable_adapter_layers

 enable_adapter_layers  与调用disable_adapter_layers方法相反,启用所有适配器,通常这两个方法配套使用。

5 merge_and_unload(常用)

  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()
6 unload

  unload 与 merge_and_unload 相反,把合并后的模型还原到基本模型

LoRA官网-> https://huggingface.co/docs/peft/package_reference/lora

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1953432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一款功能强大的视频编辑软件会声会影2023

会声会影2023是一款功能强大的视频编辑软件,由加拿大Corel公司制作,正版英文名称为‌Corel VideoStudio。它具备图像抓取和编修功能,可以处理和转换多种视频格式,如‌MV、‌DV、‌V8、‌TV和实时记录抓取画面文件。会声会影提供了…

微服务上(黑马)

文章目录 微服务011 认识微服务1.1 单体架构1.2 微服务1.3 SpringCloud 2 微服务拆分2.1 熟悉黑马商城2.2 服务拆分原则2.2.1.什么时候拆2.2.2.怎么拆 2.3 拆分服务2.3.1 拆分商品管理功能模块2.3.2 拆分购物车功能模块 2.4 远程调用2.4.1 RestTemplate2.4.2.远程调用 2.5 总结…

SpringBoot-21 SpringBoot微服务的发布与部署(3种方式)

基于 SpringBoot 的微服务开发完成之后,现在到了把它们发布并部署到相应的环境去运行的时候了。 SpringBoot 框架只提供了一套基于可执行 jar 包(executable jar)格式的标准发布形式,但并没有对部署做过多的界定,而且为…

25届最近5年广东工业大学自动化考研院校分析

广东工业大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教…

【在排序数组中查找元素的第一个和最后一个位置】python刷题记录

R2-分治 有点easy的感觉,感觉能用哈希表 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:nlen(nums)dictdefaultdict(list)#初始赋值哈希表,记录出现次数for num in nums:if not dict[num]:dict[num]1else:dict[…

(深层与双向)循环神经网络

一、深层循环神经网络 1、对于循环神经网络 2、对于深层,要得到更多的非线性,就像多层感知机(MLP)。 (1)浅层与深层对比 这是具有𝐿个隐藏层的深度循环神经网络, 每个隐状态都连续…

【QT】QT 系统相关(事件、文件、多线程、网络、音视频)

一、Qt 事件 1、事件介绍 事件是应用程序内部或者外部产生的事情或者动作的统称。在 Qt 中使用一个对象来表示一个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制…

《python程序语言设计》第6章14题 估算派值 类似莱布尼茨函数。但是我看不明白

这个题提供的公式我没看明白,后来在网上找到了莱布尼茨函数 c 0 for i in range(1, 902, 100):a (-1) ** (i 1)b 2 * i - 1c a / bprint(i, round(4 / c, 3))结果 #按题里的信息,但是结果不对,莱布尼茨函数到底怎么算呀。

【计算机网络】TCP协议详解

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 1、引言2、udp和tcp协议的异同3、tcp服务器3.1、接口认识3.2、服务器设计 4、tcp客户端4.1、客户端设计4.2、说明 5、再研Tcp服务端5.1、多进程版5.2、多线程版 5、守护进程化5.1、什么是守护进程5.2…

Javascript面试基础6(下)

获取页面所有checkbox 怎样添加、移除、移动、复制、创建和查找节点 在JavaScript中,操作DOM(文档对象模型)是常见的任务,包括添加、移除、移动、复制、创建和查找节点。以下是一些基本的示例,说明如何执行这些操作&a…

【网络世界】HTTP协议

目录 🌈前言🌈 📁 概念 📁 URL 📂 urlencode 和 urldecode 📁 协议格式 📁 方法 📂 GET/get 📂 POST/post 📁 常见的报头 📁 状态码 &…

Web3 职场新手指南:从技能到素养,求职者如何脱颖而出?

随着 2024 年步入下半年,Web3 行业正在经历一系列技术革新。通过改进的跨链交互机制和兼容性,逐步消除市场碎片化的问题。技术的进步为开发者和用户都打开了新的前景。然而,复杂的技术和快速变化的市场环境也让许多新人望而却步。求职者如何找…

编译固件 -- 自用

编译环境 先安装编译环境 git clone <编译仓库路径> git checkout <编译主分支> 更新/下载 然后就是一样的更新下载 ./scripts/feeds update -a ./scripts/feeds install -a 然后直接编译 feeds/puppies/rom/scripts/make.sh 对应型号 make Vs 这里的对应型号可…

gitee的fork

通过fork操作&#xff0c;可以复制小组队长的库。通过复制出一模一样的库&#xff0c;先在自己的库修改&#xff0c;最后提交给队长&#xff0c;队长审核通过就可以把你做的那一份也添加入库 在这fork复制一份到你自己的仓库&#xff0c;一般和这个项目同名 现在你有了自己的库…

Footprint Analytics 助力 Core 区块链实现数据效率突破

Core 是一个基于比特币并兼容 EVM 的 Layer 1 区块链&#xff0c;正通过其创新解决方案引革新特币金融。作为首个引入非托管 BTC 质押协议及全球首个发行收益型 BTC ETP 产品的区块链&#xff0c;Core 站在了区块链技术的最前沿。通过利用超过 50% 的比特币挖矿哈希算力&#x…

24暑假算法刷题 | Day22 | LeetCode 77. 组合,216. 组合总和 III,17. 电话号码的字母组合

目录 77. 组合题目描述题解 216. 组合总和 III题目描述题解 17. 电话号码的字母组合题目描述题解 77. 组合 点此跳转题目链接 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输…

python爬虫入门小案例

python爬虫 以下内容仅供学习交流,请勿用作其他用途,若涉及隐私和版权问题,请及时联系我删除 闲来无事,学了学爬虫小知识,适合入门,文笔拙劣,还望见谅 爬虫是什么: 爬取网页上的文字,图片,视频,音频 自动化操作浏览器,比如填写表单,打卡,提高工作效率爬虫的注意事项: 爬虫…

lua 游戏架构 之 游戏 AI (九)ai_mgr Ai管理

定义ai_mgr的类&#xff0c;用于管理游戏中实体的AI组件。 先定义 AI行为枚举和优先级&#xff1a; lua 游戏架构 之 游戏 AI &#xff08;八&#xff09;ai_tbl 行为和优先级-CSDN博客https://blog.csdn.net/heyuchang666/article/details/140712839?spm1001.2014.3001.55…

MySQL环境的配置文件json

突然了解到&#xff0c;使用json文件去进行环境的配置&#xff0c;这样修改参数的时候就只需要去改json文件中的内容&#xff0c;不需要去修改代码中的内容&#xff0c;其他人的MySQL和我的MySQL也不同&#xff0c;这时其他人只需要修改json文件中的内容&#xff0c;清晰明了&a…

基于微信小程序+SpringBoot+Vue的核酸检测服务系统(带1w+文档)

基于微信小程序SpringBootVue的核酸检测服务系统(带1w文档) 基于微信小程序SpringBootVue的核酸检测服务系统(带1w文档) 在目前的情况下&#xff0c;可以引进一款医院核酸检测服务系统这样的现代化管理工具&#xff0c;这个工具就是解决上述问题的最好的解决方案。它不仅可以实…