大模型参数高效微调(PEFT)技术解析及微调加速实践

2023年,大模型如雨后春笋般爆发,58同城TEG-AI Lab作为AI平台部门,紧跟大语言模型技术发展步伐,打造了大语言模型平台,支持大语言模型训练和推理部署,并基于大语言模型平台构建了58同城生活服务领域(房产、招聘、汽车、黄页)垂类大模型灵犀大语言模型(ChatLing) ,支撑了业务方大模型应用的探索落地。灵犀大语言模型在公开评测集和实际应用场景下,效果均优于开源通用大语言模型以及商用通用大语言模型。

图片

在研发灵犀大模型过程中,我们在大模型参数高效微调PEFT(Parameter-Efficient-FineTuning)上进行了广泛实践。本文系统性地解析了几种常用的大模型参数高效微调(PEFT)方法,并对每种方法的算法原理和应用效果进行了详细介绍。首先本文将阐述参数高效微调的重要性和基本概念,随后简要介绍LoRA微调之前的两种PEFT方法Adapter Tuning和Prefix Tuning,然后本文会详细介绍LoRA(Low-Rank Adaptation)、QLoRA(Quantized LoRA)和AdaLoRA(Adaptive Low-Rank Adaptor)以及SoRA(Sparse low rank adaptation)四种参数高效方法。这些方法旨在减少训练参数量、降低微调成本,同时保持模型性能。此外,本文还将分享基于Unsloth的微调加速实践经验,并且展示了在不同模型和数据集上的训练加速效果和显存占用降低效果。综上,本文将从微调方法和训练加速两个角度分享相关的技术解析和实践经验。

参数高效微调(PEFT)

自ChatGPT走红以来,众多厂商纷纷投身于人工智能大型语言模型的研发与应用。然而,高昂的计算成本使得从零开始训练一个大型语言模型对许多人而言是难以企及的。因此,自Transformer和BERT时代起,微调(fine-tuning)技术因其亲民性而受到青睐。对于业务应用而言,基于开源模型在大量语料上训练的语言模型,再针对特定业务领域数据进行微调,这种成本效益更高的方法在当前阶段似乎更符合大多数公司的需求。微调技术指的是在一个已经训练好的模型(预训练模型)的基础上,通过特定的下游任务数据对其进行进一步训练,从而使模型能够更好地适应特定任务的需求。预训练模型如同一个高效的特征提取器,基于先前训练数据中积累的经验,能够提取出有效的特征,从而显著提升下游任务的训练效果和收敛速度。全参数微调是指在下游任务的训练过程中,对预训练模型的所有参数进行更新。如下图所示在微调过程中,权重矩阵中的每个参数(d*d个参数)都要参与更新。然而对于大规模语言模型而言,传统的全参数微调方法所需的计算资源和时间成本极其高昂。例如,最近发布的开源模型如LLaMA 3-70B、Qwen 1.5-110B和DeepSeek-V2等,这些模型的参数规模之大使得即使是进行微调普通用户也难以承受。

图片

但是,由于模型在预训练阶段已经见过足够多的数据,收获了足够的经验,因此我只要想办法给模型增加一个额外知识模块,让这个小模块去适配我的下游任务,模型主体保持不变(freeze)即可。这就称之为参数高效微调,这种方式显然可以大大降低训练参数量,也就降低了微调成本,而且大幅提高了微调效率。下面,本文将介绍几种广泛使用的高效微调方法。

Adapter Tuning与Prefix Tuning

Adapter Tuning

2019 年,Adapter Tuning将 Adapter 引入 NLP 领域,作为全模型微调的一种替代方案。Adapter 主体架构如下图所示。图例中的左边是一层Transformer Layer结构,其中的Adapter是前文描述的“额外知识模块”;右边是Adatper的具体结构。在微调时,除了Adapter的部分,其余的参数都是被冻住的(freeze),这样能有效降低训练参数量。Adapter的内部架构不是本文所述的重点,这里就不再介绍了。但这样的结构设计存在一个显著劣势:添加了Adapter后,模型结构整体变的更深了,会增加推理时长。

图片

Prefix Tuning

前缀微调(prefix-tunning),用于生成任务的轻量微调。前缀微调将一个连续的特定于任务的向量序列添加到输入,称之为前缀。与提示(prompt)不同的是,前缀完全由自由参数组成,与真正的 token 不对应。相比于传统的微调,前缀微调只优化了前缀。因此,我们只需要存储一个大型 Transformer 和已知任务特定前缀的副本,对每个额外任务产生非常小的开销。Prefix Tuning通过在输入数据前增加prefix前缀来给模型提供一些先验知识的方式来提升微调效果,提供prefix的长度在训练中是一个可调整的超参,在微调中,同样需要冻结住模型其余模块,只训练prefix相关的超参即可。

图片

如上论文图给出的是gpt2模型 ,prefix的作用是引导模型提取x相关的信息,进而更好地生成y。例如,我们要做一个summarization的任务,那么经过微调后,我们希望prefix能引导模型去提取输入x中的核心信息做总结。但是这样也会导致模型输入的增加,增加计算量和推理时间,并且增加prefix难以保证训练效果。

LoRA(Low-Rank Adaptation)

原理

由于上面两种方法的劣势,我们希望找到一种方法既能像全参微调一样不增加额外输入或改变模型结构,又能大幅度减少训练参数量降低微调成本的方法。基于此LoRA(Low-Rank Adaptation,低秩适配器)第一个解决了这个问题。如下图是LoRA的整体架构,Lora通过在原始权重矩阵W的旁边新增一个旁路,这个旁路由低秩的两个矩阵 A 和 B 组成,这两个低秩矩阵组合用来近似模拟全参更新中的 ΔW 增量矩阵。在训练过程中,我们冻结住原始预训练模型的权重 W ,只更新LoRA的两个低秩参数矩阵 A 和 B 。为了在训练的初始时刻能保证加了LoRA Adapter之后不影响原始模型的能力,我们分别使用高斯初始化和零初始化来初始化 A 和 B 。

图片

假设原始权重矩阵的维度是 d×d,LoRA低秩矩阵A的维度设置为 r×d,矩阵B的维度为 d×r,这里我们冻结原始权重,相当于只更新增量权重。可以理解为我们先通过A矩阵进行一个降维操作,然后再使用B矩阵进行升维操作。这样微调的参数就从原来的 d×d 降低到了 2×d×r。因为一般设置的参数 r 会远小于 d,所以这里能大大降低训练参数量。在训练过程中,由于预训练权重 W 被冻结,仅对低秩矩阵 A 和 B 进行训练。因此,在保存LoRA训练的权重时,仅需保存参数量相对较小的低秩部分即可。训练时,GPU显存通常存储以下内容:输入数据、模型权重、模型的中间结果、梯度以及优化器状态。相比全参数微调方法,LoRA训练中输入数据部分显存占用不变。而因为原始权重也需要参与计算,因此模型权重和中间结果的占用也不变(增加的LoRA部分权重几乎可以忽略不计)。关于梯度的显存占用分析则相对复杂,以反向传播时 B 的梯度计算为例进行具体分析如下:

在这里插入图片描述

考虑 B 梯度的前两项,梯度的维度和预训练权重的梯度相同,均为 d×d。然而,由于LoRA并不作用于模型的所有层,并且由于训练参数的减少,优化器状态的存储显著减少,因为通常像类似adam优化器需要存储一阶梯度和二阶动量,而且通常优化器状态中存储的都是fp32类型的值,所以这部分显存占用相比全参微调大大降低,总体上显著降低了显存的占用。在推理时,将LoRA权重与原始权重合并即 h=(W+BA)x 的方式得到与原始模型一样的结构。这意味着完全不需要改变模型的任何结构,微调后模型的推理参数量与原始模型参数量完全一致。且这种方式让我们可以根据不同的业务场景基于同一个基座模型训练不同的LoRA权重,然后在不同的应用上加载不同的LoRA权重,非常灵活,而且LoRA权重通常非常小,也很易于存储和加载。

LoRA特点总结:

  • • 对 A 采用高斯初始化,对 B 采用零初始化;
  • • 微调的参数就从原来的 d×d 降低到 2×d×r ; r << d。
  • • 推理时不增加任何计算量,与原始模型架构完全一致
  • • 可以基于同一个基座在不同的场景下训练不同的lora模型加载使用

实验

LoRA现已在业界广泛应用于各个场景的微调任务,在诸多任务中都被验证是有效且可行的。我们也基于两个业务场景做了单一任务的微调实践。LoRA的原理在于增量矩阵 ΔW 满足低秩假设, h=(WWx 中的 ΔW 确实是一个低秩矩阵。如果不满足该假设,那么LoRA的分解就一定会有精度损失,而达不到最好的微调效果。因此需要在任务中需要选择合适的 r,理论上说,针对复杂的任务可能需要更大的 r,但是 r 的值越大,可训练的参数量就越大,训练时长和显存占用就会同时变得更大。一般来说增大 r 的值会取得更好的微调效果,但是也不是一定如此,对于简单任务的微调太大的训练参数反而会使模型训练容易过拟合而导致效果变差。因此在实验阶段我们在两

<think>好的,用户现在需要关于大模型微调的实例和代码示例。首先,我需要回忆一下之前用户提供的引用内容。根据引用[1],提到了Torchtune的教程和代码示例,以及第七阶段涉及使用星火大模型和文心大模型构建行业应用。用户可能希望得到具体的步骤和代码,而不仅仅是理论。 接下来,我需要确定用户的具体需求。他们可能对如何实际操作微调大模型感兴趣,特别是使用像PyTorch这样的框架。用户提到的示例代码可能括数据准备、模型配置、训练循环等部分。同时,用户可能希望了解不同的微调方法,比如LoRA,因为这在微调大型模型时可以减少计算资源的需求。 然后,我应该考虑用户可能的背景。他们可能是开发者或研究人员,有一定机器学习基础,但需要具体的指导来实施微调。因此,回答需要结构清晰,分步骤解释,并提供代码示例。同时,需要确保代码的正确性和适用性,比如使用流行的库如Hugging Face Transformers和PyTorch。 还要注意引用用户提供的资料,特别是在引用Torchtune的部分,以增强可信度。此外,用户可能对优化方法(如LoRA)和应用场景感兴趣,所以在相关问题上可以进一步扩展。 最后,确保回答符合格式要求,使用中文,行内公式用$...$,独立公式用$$...$$,正确使用LaTeX语法,并在适当的位置添加引用标识。同时,生成的相关问题要贴近用户可能的后续疑问,帮助他们进一步学习。</think># 大模型微调实例与代码解析 ## 一、微调核心步骤说明 大模型微调主要含以下技术环节: 1. **数据准备**:需构建与目标领域匹配的标注数据集,推荐格式为JSON或CSV 2. **模型加载**:使用`transformers`库加载预训练模型与分词器 3. **参数配置**:设置学习率(推荐$lr=1e-5$到$1e-3$)、训练轮次(通常2-5个epoch) 4. **训练优化**:采用LoRA等参数高效微调方法,显存消耗可降低70%[^1] ## 二、PyTorch代码示例 ```python from transformers import AutoModelForCausalLM, AutoTokenizer import torch # 加载预训练模型 model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf") tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf") # 配置LoRA参数 from peft import LoraConfig, get_peft_model lora_config = LoraConfig( r=8, # 低秩矩阵维度 lora_alpha=32, target_modules=["q_proj", "v_proj"], # 修改注意力层的投影矩阵 lora_dropout=0.05 ) model = get_peft_model(model, lora_config) # 训练循环示例 optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4) for epoch in range(3): for batch in train_loader: inputs = tokenizer(batch["text"], return_tensors="pt", padding=True) outputs = model(**inputs, labels=inputs["input_ids"]) loss = outputs.loss loss.backward() optimizer.step() optimizer.zero_grad() ``` ## 三、关键参数解析 $$ \text{LoRA更新公式:} W' = W + \alpha \cdot \Delta W $$ 其中$W \in \mathbb{R}^{d \times k}$为原始参数矩阵,$\Delta W$为低秩更新矩阵,$\alpha$为缩放系数。该技术通过低秩分解($r=8$)大幅减少可训练参数量[^1] ## 四、行业应用案例 1. **金融领域**:使用星火大模型微调财务报表分析模型 2. **医疗领域**:基于文心大模型构建病历自动生成系统 3. **客服场景**:微调Llama-2实现多轮对话管理
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值