微信扫码
与创始人交个朋友
我要投稿
? 引言
Fine-tuning (微调),是指在新数据集上调整预训练模型的权重,从而提高模型在特定领域,或特定任务上的性能。下图演示了这一过程:
LoRA 是近年来对大模型最重要的贡献之一,它通过只修改模型一小部分的参数,重新定义了对大模型微调的方法。
LoRA 提出后,出现了许多 LoRA 的变体,每种变体都针对特定的挑战进行了改进与优化。下图展示的是 LoRA 之后引入的一些最流行的微调技术:
本篇文章将从 LoRA 开始,介绍每个 LoRA 变体的设计理念、技术创新及其旨在解决的特定问题。
LoRA 的核心理念是相对于全量微调而言,只训练极少的参数,同时保持全量微调所能达到的性能。
更具体地说,在某些特定层中添加了两个低秩矩阵 A 和 B,这些低秩矩阵包含了可训练的参数:
数学上,这种方法是通过修改线性层中的权重矩阵 ΔW 来实现的:
其中,W 是原始的权重矩阵,ΔW 是权重的更新或调整。在LoRA中,这个 ΔW 被分解为两个低秩矩阵 A 和 B 的乘积。由于矩阵 A 和 B 的维度与 ΔW 相比要小得多,从而显著减少了可训练参数的数量。
这种低秩更新不仅简洁,而且能在保留预训练后 LLM 能力的同时,放大了其针对新任务或新数据集所需的特定适应性。
举个例子,若 OpenAI 的用户希望在 GPT-3.5 上微调一个模型,OpenAI 只需存储上述两个矩阵 A 和 B。对于引入了 A、B 两个矩阵的原始线性层,A、B 两个矩阵的参数非常小。
原始的权重矩阵 W 作为所有微调版本的”通用“部分,可以有一个central version(中心版本),即可以在所有用户间共享。
根据 LoRA 论文,作者将模型的 Checkpoint size 大小减少了大约 1 万倍:从 350GB 减少到仅 35MB。
此外,作者还观察到,在对 GPT-3 175B 模型训练时,相较于全量微调,使用 LoRA 微调时训练速度提高了 25%,这是因为在 LoRA 的训练过程中,绝大部分参数都未计算梯度。
另外,使用 LoRA 微调后的模型不会引入推理延迟。这是由于其简单的线性设计,使其部署时可以将新添加的矩阵( A 和 B )与冻结权重( W )合并,因此可以完全按照常规方式推理。
LoRA 另一个非常有趣的特点是超参数 r 比相应权重矩阵的维度小几个数量级。在下表,我们可以将 r=1 的微调结果与 r 为其他值时的结果进行比较:
在大多数情况下,我们注意到 r=1 的表现几乎与任何其他更高的阶数一样好。
这即表明,低秩矩阵 A 和 B 可以是简单的行矩阵或和列矩阵。
以上是对 LoRA 的一个简要概述,接下来介绍 LoRA 的各类变体。
基于 LoRA 技术,LoRA-FA(FA 是 Frozen-A 的缩写)方法引入了一些微小变化,减少了微调时的内存开销。
LoRA 层中需要消耗昂贵的激活内存。因为 LoRA 在前向传播传播过程中需要存储 X 的大量输入激活,用于在反向传播过程中构建 A 的梯度,故 LoRA 无法降低与全量微调相比的激活内存。举个例子,对输入序列长度为 2048 、批量大小为 4 的 LLaMA-65B 进行微调时,所有 LoRA 层需要超过 50GB 的激活内存(以 16 位精度计算)。
LoRA-FA 通过优化内存使用来解决这一挑战,不牺牲微调性能,也无需使用诸如激活重计算之类的高成本计算。其关键修改在于选择性更新机制,在LoRA-FA中,矩阵 A 在初始化后被冻结,作为随机投影;矩阵 B 在用零初始化之后进行训练(就像在原始LoRA中一样)。这将参数数量减半,但具有与普通LoRA 相当的性能:
如上图所示:
LoRA 中,矩阵 A 和 B 都会进行训练。
LoRA-FA 中,仅矩阵 B 会进行训练。这就是 "FA" 在 "LoRA-FA" 中的含义——Frozen-A。
这种方法确保模型权重的调整保持在一个低秩空间内,从而最大限度地减少存储全秩输入激活所需的内存。
在 LoRA-FA 的论文中,针对不同模型架构(如 RoBERTa、T5 和 LLaMA)进行了实验,涵盖了多个规模和任务。结果表明,LoRA-FA 可以接近全量微调及标准 LoRA 方法所达到的微调精度。
例如,从 RoBERTa 模型的实验结果中可以看出,在大多数情况下,LoRA-FA 的表现比 LoRA 要好或几乎持平。使用 LoRA-FA 而不是 LoRA 时,并未出现模型性能显著下降的情况:
此外,在开源 LLaMA-7b 模型的情况下,作者发现到 LoRA-FA 技术的表现始终优于 LoRA:
括号中的数字表示相对于未经过任何微调的 LLaMA-7B 基础模型的性能提升。
在这两种情况下,LoRA-FA 几乎将可训练参数的数量减少了一半。
VeRA(Vector-based Random Matrix Adaptation,基于向量的随机矩阵适应)技术可以进一步减少 LoRA 中可训练参数数量,同时能够匹配或接近 LoRA 的精度。
如前所述,在 LoRA 中,每一层都有一对不同的低秩矩阵 A 和 B,并且这两个矩阵都需要进行训练。
在 VeRA 中,矩阵 A 和 B 被冻结和随机化,并在所有模型层之间共享。这消除了在不同层之间训练和更新大量参数的需求,简化了模型架构:
VeRA 不更新这些矩阵 A 和 B ,而是专注于学习小型的、层特定的缩放向量(layer-specific scaling vectors),记作 b 和 d ,它们是此设置中唯一的可训练参数。这些向量不跨层共享。
在 VeRA 中,我们不更新矩阵 A 和 B,而是专注于学习小型的、层特定的缩放向量 b 和 d,这些向量是层中唯一的可训练参数,不跨层共享。
矩阵 A 从正态分布中随机初始化,并且在微调过程中不进行训练。这一步的初始化类似于 LoRA 中的做法。与 LoRA 的不同在于,VeRA 的这个权重矩阵在所有层之间共享:
矩阵 B 也从正态分布中随机初始化。在 LoRA 中,B 的初始化值是零,但在 VeRA 中不能这样做,因为矩阵 B 不训练,初始化为零将导致输出全为零。这个权重矩阵也在所有层之间共享。
向量 d 的初始值为全 1,并在微调过程中进行训练:
向量 b 的初始值为全 0,同样微调过程中进行训练。以零初始化确保在微调开始时不对模型进行任何更新。
综上所述,最终的适应过程执行如下:
作者在多个方面比较了 VeRA 和 LoRA,例如内存需求、可训练参数数量和准确率,涵盖了 RoBERTa-base、RoBERTa-large、LLaMA 和 GPT-3 等模型。
存储 VeRA 和 LoRA 权重所需的内存对比如下:
对比 VeRA 和 LoRA 在“Trainable Parameters Required Bytes”列中的差异,可以看到 VeRA 的内存需求明显更低。此外,VeRA 的可训练参数数量比 LoRA 小几个数量级。
关于准确率的表现,下图展示了 RoBERTa-base 和 RoBERTa-large 的结果:
大多数情况下,VeRA 与 LoRA 的性能指标差异不大。
在 LLaMA 模型的 MT-bench 上的结果如下:
虽然 VeRA 与 LoRA 之间的性能差异并不显著,但可训练参数总量的下降非常明显,相比 LoRA, VeRA 的训练参数仅为前者的 1/100。
个人认为 Delta-LoRA 微调的方法并不适合大模型厂商,尤其是基于基础的 LLM 向用户提供微调模型的情况。
为详细解释,先了解下 Delta-LoRA 的工作原理。
在 LoRA 中,我们从不更新大型权重矩阵 W,所有更新都重定向到低秩矩阵 A 和 B。
作者指出,这种微调方式并非最优,与全量微调相比,性能差距依然很大。这一差距的原因是,LoRA 仅更新了模型参数的一小部分,I 因此不足以捕捉新数据中的细节。
为解决这个问题,Delta-LoRA 中同时也更新矩阵 W,但并非采用传统微调方式(依然是成本问题)。
Delta-LoRA 不直接使用 A⋅B 作为每一步训练的结果,而是关注在连续的训练步骤之间,低秩矩阵乘积的变化量(delta)。具体来说,Delta-LoRA 会计算两个连续训练步骤之间 A⋅B 的差异。
为简化起见,考虑以下步骤 t+1 和 t 所示的低秩矩阵乘积:
作者假设这两步间产生的缩放差异将反映出大矩阵 W 的梯度更新,如下所示:
因此,大权重矩阵 W 的更新可以写成:
以上公式中,c 是一个常量,作者将其设定为:
在 Delta-LoRA 中,对矩阵 A 和 B 的更新方式与我们处理 LoRA 时相同,未作任何改动。
这就是如何在不通过反向传播显式微调的情况下更新完整的权重矩阵 W,即通过对 A⋅B 矩阵差值的缩放更新 W 矩阵,而未直接求原矩阵的梯度。
下图汇总了 Delta-LoRA 论文中的一些结果。很明显,与其他所有微调方法相比,Delta-LoRA 始终表现最佳:
因其核心知识存在于权重矩阵 W 中,微调可以产生更好的结果。
以 OpenAI 为例, 其提供了一个微调 API,用于根据用户的需求定制模型,目前支持的模型包括 gpt-4o-2024-08-06、gpt-4o-mini-2024-07-18、babbage-002、davinci-002 和 gpt-4-0613 等。
百度智能云也提供 22 个可微调的模型:
如果按照传统微调方式,每个希望拥有定制版本的用户,模型厂商都必须为其专门分配一台 GPU 服务器来加载模型,并确保有足够的计算能力来处理微调请求。
但部署这些具有 1750 亿参数的独立微调模型实例,成本高到令人望而却步:
一个 GPT-3 模型检查点估计会占用约 350GB 的存储空间。而这仅仅是模型的静态内存,仅包含模型权重,甚至还未考虑训练过程中所需的内存、计算激活值、运行反向传播等。
而这仅是针对一个用户的情况,但实际上 OpenAI 已经有很大体量的客户群体根据其数据集微调的定制版 OpenAI 模型。
还有许多其他用户只是想探索或尝试微调功能,这些用户也并不打算使用该模型来服务任何终端用户。但对 OpenAI 来说,仍需承担维护和服务完整微调模型的成本,因为其采用了“按 token 付费”的定价策略。若模型在微调后没有被使用,OpenAI 就无法获得收入。
LoRA 在添加低秩矩阵 A 和 B 后,训练时只训练权重矩阵 A 和 B;推理期间矩阵 A 和 B 的乘积可以加到相应的权重矩阵 W 以生成预测:
因此对于每个微调模型,OpenAI 只需存储上述两个矩阵 A 和 B(引入 AB 的所有线性层),原始权重矩阵 W 可以在所有用户之间共享:
但 Delta-LoRA 引入了对矩阵 W 的更新。因此,我们无法再维持单独的集中式大型模型副本,和用户特定的低秩矩阵。
这会导致巨大的存储成本,因此对于 OpenAI 这类的大模型商,实际上并不可行。
LoRA+ 与 LoRA 略有不同。
在 LoRA 中,我们以相同的学习率更新低秩矩阵 A 和 B:
LoRA 的作者指出,当处理大嵌入维度 (d) 时,LoRA 的当前设置会导致模型微调效果不理想。
在嵌入维度 ddd 很大的情况下,LoRA 的当前设置可能会导致次优(suboptimal)的微调效果:
低秩近似的限制:LoRA 使用的低秩矩阵 A 和 B 来近似原始的权重更新 ΔW 。在嵌入维度 d 很大的情况下,模型可能需要捕捉更多的细节信息,而低秩矩阵的表达能力有限,无法很好地表示嵌入向量之间复杂的交互关系,导致信息丢失,从而影响模型的性能。
信息瓶颈:当嵌入维度很大时,输入特征可能非常复杂且具有高度多样性。低秩矩阵的秩 rrr 决定了它能表示的特征维度数。对于非常大的 d,如果 r 太小,低秩矩阵可能不足以捕捉输入特征的多样性,导致模型在微调时难以有效学习。
优化的难度增加:随着嵌入维度增大,参数空间的复杂度也会增加。在这种情况下,LoRA 的低秩矩阵可能不足以有效优化所有参数,特别是当输入数据的维度增加时,可能会导致微调效果的降低。
LoRA+ 是通过为低秩矩阵 A 和 B 设置不同的学习率解决这个问题。更具体地说,通过为矩阵 B 设置更高的学习率解决此问题:
其有效性可从下图所示的损失曲线中得以体现:
蓝线显示了当矩阵 B 的学习率较高时的损失曲线随训练轮数的变化。
浅橙色线表示当矩阵 A 和矩阵 B 的学习率相同时,损失曲线随训练轮数的变化情况(即使用 LoRA 微调的情况 )。
作者进行了多种实验,发现 LoRA+ 在性能上比标准 LoRA 提高了 1% - 2%。同时,在相同的计算成本下,微调速度提高了最多 2 倍。
作者提供了数学证据,证明了为何此方法有效。其核心直觉在于初始化步骤:
在LoRA 中,低秩矩阵 B 的初始值为零,这意味着 B 对模型输出没有初始贡献,因此需要设置较大的学习率进行梯度更新;比之下,矩阵 A 是随机初始化的,这意味着它从一开始就对模型的行为有所贡献;对于 A 来说,较小、更精细的调整足以使其在网络中微调其角色。
激活剪枝(Activation Pruning)是一种剪枝技术,通过分析神经网络中某些神经元的激活值来确定哪些神经元对模型输出的重要性较低,从而将其删除。这种方法的核心目标是减少模型复杂性、加速推理并降低模型参数量,尤其在推理部署阶段非常有用。
这里面的核心思想是,若一个神经元很少有较高的激活值,那么它对模型输出的贡献就很小。
对应到 LoRA ,需要重新判断在每一层中添加低秩矩阵是否真的有必要。是否可以只在一些层中添加 LoRA 矩阵,而可以实现其性能与在所有层中都添加相同的效果呢?
LoRA-drop 正是基于以上想法构建。换句话说,LoRA-drop 首先判断在哪些层中添加 LoRA 矩阵是必要的。
从整个网络来看,LoRA 层始终相对较小,因此表面上看多添加一些矩阵似乎不是什么问题;但随着添加的 LoRA 矩阵越多,微调的成本实际也就越高。
添加低秩矩阵层的选择方法如下:
首先,将低秩矩阵添加到所有层中。
对数据集进行采样,并对低秩矩阵进行几个回合的训练。
类似于激活剪枝步骤,计算低秩矩阵 A⋅B⋅X 生成的激活并进行分析。
如果激活(整体考虑)趋于较大,意味着它们对相应权重矩阵 W 的输出有显著贡献,因此建议在这一层中保留 LoRA 矩阵。若激活(整体考虑)趋于较小,意味着它们对相应权重矩阵 W 的输出没有显著贡献,因此建议在这一层中保持原权重矩阵不变,不再放置任何额外的 LoRA 矩阵。
一旦确定了包含 LoRA 矩阵的层,使用整个数据集对它们进行训练。
LoRA-drop 的最大优势不在于准确性的提升,而在于模型训练速度的加快。
本篇文章介绍了自 LoRA 以来提出的各种大型语言模型微调方法,并未对其中涉及到的数学做过多解释。如果你对其中的数学原理,尤其是矩阵分解的思路感兴趣,可以阅读原论文。
由于 AdaLoRA 和 DoRA 也需要补充一些数学细节,本文中也未介绍,后续若有必要可以再详细阐述。
参考文献:
LoRA:https://arxiv.org/abs/2106.09685;
LoRA-FA:https://arxiv.org/abs/2308.03303
VeRA:https://arxiv.org/abs/2310.11454
Delta-LoRA:https://arxiv.org/abs/2309.02411
LoRA+:https://arxiv.org/abs/2402.12354
LoRA-drop:https://arxiv.org/abs/2402.07721
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-12-27
全是细节|大模型SFT的100个关键点
2024-12-26
新型LLM优化技术削减内存成本高达75%
2024-12-26
AI模型训练到底在训练什么?
2024-12-25
Cursor小白必看:听说你还在安装配置环境?学会这个让你告别环境烦恼!
2024-12-25
微软变脸OpenAI,模型价值之争压不住了?
2024-12-25
GPT-5 研发一年半进度堪忧!每轮 5 亿美金训练成本打水漂,还得雇人从头“造数据”
2024-12-25
基于昇腾910B,使用XTuner微调一个InternLM个人小助手丨玩转书生大模型
2024-12-25
BERT新版本:ModernBERT -- Smarter, Better, Faster, Longer
2024-09-18
2024-07-11
2024-07-11
2024-07-09
2024-06-11
2024-10-20
2024-07-26
2024-07-23
2024-07-20
2024-07-12