当前位置: 首页 > article >正文

[论文精读]LoRA: Low-Rank Adaptation of Large Language Models

LoRA: Low-Rank Adaptation of Large Language Models

http://arxiv.org/abs/2106.09685

低秩矩阵训练大模型,有效减小开销、即插即用、对内部参数的变化不大,不得不学。

lora框架冻结预训练模型的权重并插入可训练的秩分解矩阵到Transformer架构的每一层中,这样可以有效减小下游任务所需训练参数

lora的优势:

  1. 通过置换图一中的矩阵A和B,可以高效的切换下游任务类型,且任务切换所需开销更小
  2. lora使得训练更加高效且降低了硬件准入门槛约三倍,原因在于并不需要计算梯度或者维持优化器数据,只用优化插入的更小型的低秩矩阵
  3. 简单的线性设计允许在部署时将可训练矩阵与冻结权重合并,与完全微调的模型相比,通过构建不会引入推理延迟。
  4. LoRA 与许多以前的方法正交,可以与其中许多方法结合使用,例如前缀调整。

将 Transformer 层的输入和输出维度大小称为d_{model} 。我们使用 Wq 、 Wk、Wv 和 Wo 来引用 自注意力模块中的 query/key/value/output (查询、键、值、输出)投影矩阵。 W 或者 W0 是指预先训练的权重矩阵及其 Δ​W 是在适应过程中的累积梯度更新。用 r 表示 LoRA 模块的 秩。使用Adam 进行模型优化,并使用 Transformer MLP 前馈维度 d_{ffn} = 4 \times d_{model}

 问题陈述

全参微调的时候,模型参数是加载的预训练参数,然后通过任务积累的梯度来逐渐调整参数值,目标是最大化条件语言建模目标:

 全参微调的缺点是对于每一个不同的下游任务,学到的参数是不同的,且其维度大小和初始参数的维度一致,不管是存储还是开发都会是极具挑战性的。

文章则针对全参微调在LLM条件下不现实且不高效的问题,采用了一种参数效率更高的方法,其中特定于任务的参数增量 Δ​Φ=Δ​Φ​(Θ) 由更小的参数 Θ 集进一步编码。 |Θ|≪|Φ0| 因此,查找 Δ​Φ 的任务变成了优化 : Θ

以GPT3 175B参数模型为例,使用LORA框架进行微调,需要训练的参数量是原始参数量的0.01%

现有解决方案存在一定的问题

以语言模型为例,在高效调整方面有两个主要的策略:添加适应层或者优化某些形式的输入层激活

适配层增添了推理延迟

适配器有很多变体。 我们专注于 Houlsby 等 人(2019 年)的原始设计,每个 Transformer 模块有两个适配器层,而 Lin 等 人(2020 年)最近的设计每个模块只有一个,但有一个额外的 LayerNorm(Ba 等 人,2016 年)。虽然可以通过修剪层或利用多任务设置来减少整体延迟(Rücklé et al., 2020;Pfeiffer et al., 2021)中,没有直接的方法可以绕过适配器层中的额外计算。这似乎不是问题,因为适配器层被设计为具有很少的参数(有时 < 是原始模型的 1%),因为具有较小的瓶颈维度,这限制了它们可以添加的 FLOPs。但是,大型神经网络依靠硬件并行性来保持低延迟,并且必须按顺序处理适配器层。这在在线推理设置中有所不同,其中批量大小通常小到 1。在没有模型并行性的通用场景中,例如在单个 GPU 上的 GPT-2 (Radford 等 人,b)介质上运行推理,我们看到在使用适配器时延迟明显增加,即使瓶颈维度非常小(表 1 )

当我们需要像 Shoeybi et al. (2020) 那样对模型进行分片时,这个问题会变得更糟;Lepikhin et al. (2020) ,因为额外的深度需要更多的同步 GPU 操作,例如 AllReduce 和 Broadcast,除非我们将适配器参数冗余地多次存储。

直接优化提示词是很困难的

 另一个方向,如前缀调整(Li & Liang,2021)所代表的,面临着不同的挑战。我们观察到前缀调整很难优化,并且其性能在可训练参数中非单调变化,证实了原始论文中的类似观察结果。更根本的是,保留一部分序列长度进行适配必然会减少可用于处理下游任务的序列长度,我们怀疑与其他方法相比,这会使调优提示的性能降低。

文中方法

低秩参数化更新矩阵

神经网络通常包含很多需要进行矩阵乘法的稠密层,这些层中的权重矩阵通常情况下是满秩的。当在特定任务下进行微调,Aghajanyan et al. (2020)表明,预训练语言模型具有较低的 “内在维度”,并且即使随机投影到较小的子空间,仍然可以有效地学习。

受此启发,假设权重的更新在适应过程中也具有较低的 “内在秩”。对于预训练的权重矩阵 W_0\in \mathbb{R}^{d \times k} ,我们通过用低秩分解 W0+Δ​W=W0+B​A 来表示后者来限制其更新,其中 B∈ℝd×r,A∈ℝr×k 且 秩 r≪min⁡(d,k) 。在训练期间, W0 被冻结并且不接收梯度更新,而A 和 B 包含可训练参数。请注意,W0 和 Δ​W=B​A 都乘以相同的输入(记输入为x,x是embedding),并且它们各自的输出向量在类似坐标系上求和。对于 h = W_0 x ,我们修改后的正向传递得到:

使用随机高斯分布初始化矩阵A,使用全0初始化矩阵B,这样就能保证在最开始的时候Δ​W=0.然后我们按\frac{\alpha }{r}进行缩放 Δ​W​x ,  其中 α 是 中的 r 常数。使用 Adam 进行优化时,如果我们适当地缩放初始化,则修改 α 与调整学习率大致相同。因此,我们只需设置 α 为第一个尝试的 r ,而不调整它。这种缩放有助于减少当我们变化 r 时重新调整超参数的需要。

全面微调的一般化。  更通用的微调形式允许训练预训练参数的子集。LoRA 更进一步,不需要对权重矩阵的累积梯度更新在适应期间具有满秩。这意味着,当将 LoRA 应用于所有权重矩阵并训练所有偏差,我们通过将 LoRA 的秩 r 设置为预先训练的权重矩阵的秩来大致恢复完全微调的表现力。换句话说,随着我们增加可训练参数的数量,训练 LoRA 大致收敛到训练原始模型,而基于适配器的方法收敛到 MLP,基于前缀的方法收敛到不能采用长输入序列的模型。

没有额外的推理延迟。当部署到实际中,我们可以直接计算和存储W= W0 + BA 然后正常进行推理,W0和BA都是d×k矩阵。当需要切换到其他下游任务的时候,只需要让W减去BA就得到了初始的W0,然后再加上另一个任务的B'A'即可,这样使得任务切换的开销很小。如果是全参微调的模型,切换下游任务需要卸载模型,重装另一个任务对应的模型,这样开销会很大,时间消耗也更多。

把LORA应用到Transformer

原则上,我们可以将 LoRA 应用于神经网络中权重矩阵的任何子集,以减少可训练参数的数量。 在 Transformer 架构中,自注意力模块 ( Wq,Wk,Wv,Wo ) 中有四个权重矩阵,MLP 模块中有两个权重矩阵。我们将 Wq (或 Wk , Wv ) 视为维度dm​o​d​e​l×dm​o​d​e​l 的单个矩阵,即使输出维度通常被切成注意力首部。我们将研究限制在仅为下游任务调整注意力权重,并冻结 MLP 模块(因此它们没有在下游任务中接受训练),以实现简单性和参数效率。我们在 7.1 节 中进一步研究了在 Transformer 中适应不同类型的注意力权重矩阵的影响。我们将调整 MLP 层、LayerNorm 层和偏差的实证研究留给未来的工作。

实际优点和局限性。  最显著的好处是减少了内存和存储使用量。对于使用 Adam 训练的大型 Transformer,我们将 VRAM 使用量减少多达 2/3 如果 r≪dm​o​d​e​l ,因为我们不需要存储冻结参数的优化器状态。在 GPT-3 175B 上,我们将训练期间的 VRAM 消耗从 1.2TB 减少到 350GB。在调整查询和值投影矩阵后 r=4 ,检查点大小减少了大约 10,000 × 个(从 350GB 减少到 35MB)。这使我们能够使用明显更少的 GPU 进行训练,并避免 I/O 瓶颈。另一个好处是,我们可以在部署时以更低的成本在任务之间切换,只需交换 LoRA 权重,而不是所有参数。这允许创建许多自定义模型,这些模型可以在将预训练权重存储在 VRAM 中的机器上动态换入和换出。我们还观察到,与完全微调相比,在 GPT-3 175B 上训练期间,速度提高了 25%因为我们不需要计算绝大多数参数的梯度。

LoRA 也有其局限性。 例如,如果选择把 A 和 B 并入 W 以消除额外的推理延迟,那么在一次前向传播中批量输入具有不同A和B的不同任务并不简单。不过,在延迟不重要的情况下,可以不合并权重并动态选择用于批处理样本的 LoRA 模块。

实验

任务类型:

  1. 微调FT:一种常见的适应方法。在微调期间,模型被初始化为预先训练的权重和偏差,并且所有模型参数都会进行梯度更新。一个简单的变体是仅更新某些层,同时冻结其他层。
  2. 仅偏置Bias-ony 或者 BitFit:只训练偏置向量,同时冻结其他所有内容。
  3. 前缀嵌入优化 (PreEmbed) 在输入标记中插入特殊标记。这些特殊标记具有可训练的单词嵌入,通常不在模型的词汇表中。放置此类令牌的位置可能会影响性能。我们专注于 “prefixing”,它将此类标记附加到提示符前面,以及 “infixing”,它附加到提示符中;两者都在Li & Liang (2021)中进行了讨论。我们使用 lp (resp. li ) 表示前缀 (resp. infix) 标记的数量。可训练参数的数量为 |Θ|=dm​o​d​e​l×(lp+li) 。
  4. 前缀层优化 (PreLayer) 是前缀嵌入优化的扩展。我们不是仅仅学习一些特殊标记的词 embeddings(或者等效地,嵌入层之后的 activations),而是学习每个 Transformer 层之后的 activations。从前面的层计算的激活值被可训练的激活值简单地替换。生成的可训练参数数量为 |Θ|=L×dm​o​d​e​l×(lp+li) ,其中 L 是 Transformer 层的数量。
  5. 适配器调整:在自注意力模块(和 MLP 模块)和随后的残差连接之间插入适配器层。在适配器层中有两个全连接层,它们具有偏置,中间有非线性。我们称之为原创设计 AdapterH 。一种更高效的设计:适配器层仅在 MLP 模块和 LayerNorm 之后应用。我们称之为 AdapterL 。另一个设计: AdapterP 。我们还包括另一个名为 AdapterDrop 的基线,它删除了一些适配器层以提高效率 ( AdapterD )。我们尽可能引用先前工作中的数字,以最大限度地增加我们比较的基线数量;它们位于第一列中带有星号 (*) 的行中。在所有情况下,我们都有其中 L^A​d​p​t 是适配器层的数量和 L^L​N 可训练的 LayerNorm 的数量(例如,在 AdapterL 中)。
  6. LoRA :添加了与现有权重矩阵并行的可训练秩分解矩阵对。如上文所述,为了简单起见,我们大多数实验只将 LoRA 应用于 Wq Wv 。可训练参数的数量由原始权重的秩 r 和形状决定:  ,其中 L^L​o​R​A 是我们应用 LoRA 的权重矩阵的数量

 

理解低秩更新

 1、LORA应该应用于Transformer架构中的哪个权重矩阵?

在参数预算有限的情况下,我们应该使用 LoRA 调整哪些类型的权重才能在下游任务上获得最佳性能? 如 4.2 节 所述,我们只考虑 self-attention 模块中的权重矩阵。我们在 GPT-3 175B 上设置了 18M 的参数预算(如果存储在 FP16 中,大约是 35MB),这对应于我们 r=8 是否为所有 96 层调整一种类型的注意力权重或 r=4 调整两种类型的注意力权重。结果如表 5 所示。

将所有参数放入 Δ​Wq 或 Δ​Wk 会导致性能显著降低,同时调 Wq 和 Wv 产生最佳结果。这表明,即使秩为 4 也能捕获足够的信息, Δ​W 因此最好采用更多的权重矩阵,而不是采用具有较大秩的单一类型的权重。 

2.LORA中最佳秩r是多少?

 从实验结果来看,似乎一昧增加矩阵的秩提升不大,这表明低秩矩阵已经够用了

探究不同r之间的子空间相似性

 从图中来看,相似性大多集中在低秩上

探究不同种子下子空间的相似性

 从图中可以看出,在相同的秩下,不同的种子表现出相似性最高的地方还是集中在低秩部分。

Δ​Wq 似乎具有比 Δ​Wv 更高的“内在秩”,因为 的 Δ​Wq 两次运行都学习了更常见的奇异值方向

3.适应矩阵 Δ​W 与 W 相比如何? 

进一步研究了Δ​W和W之间的关系 。特别是,是否 Δ​W 与 W 高度相关?(或者从数学角度看,∆W 是否主要包含在 W 的顶部奇异方向中?)另外,与Δ​W在W中的相应方向相比,“大”有多大?这可以阐明适应预训练语言模型的底层机制。

计算 U⊤​W​V⊤ 投影 W 到 r 的 Δ​W 的维子空间上,其中 U / V 是 的 Δ​W 左/右奇异向量矩阵。然后,我们比较 和 之间的 ‖U⊤​W​V⊤‖F ‖W‖F Frobenius 范数。作为比较,我们还通过替换为 W U,V 或随机矩阵的顶部 r 奇异向量来计算 ‖U⊤​W​V⊤‖F 。

 由表7:相较于随机矩阵,Δ​W和W具有更强的相关性,这就表明了Δ​W放大了W中已有的一些特征;其次,不是重复 W 的顶部奇异方向, Δ​W 而是只放大 W 中未强调的方向;第三,当秩为4的时候,放大的倍数是相当巨大的(放大因子很大):21.5=6.91/0.32

测量子空间之间的相似性

总结

LoRA的思想:

  • 在原始 PLM (Pre-trained Language Model) 旁边增加一个旁路,做一个降维再升维的操作,来模拟所谓的intrinsic rank
  • 训练的时候固定 PLM 的参数,只训练降维矩阵A与升维矩阵B。而模型的输入输出维度不变,输出时将BA与 PLM 的参数叠加。
  • A用随机高斯分布初始化,B用 0 矩阵初始化 ,保证训练的开始此旁路矩阵依然是 0 矩阵。

http://www.kler.cn/a/374040.html

相关文章:

  • Spring 框架中常见的注解(Spring、SpringMVC、SpringBoot)
  • Vue 3:解析
  • 深度学习(八) TensorFlow、PyTorch、Keras框架大比拼(8/10)
  • 基于SSM学生竞赛模拟系统的设计
  • CodeS:构建用于文本到 SQL 的开源语言模型
  • MATLAB——矩阵操作
  • 【初阶数据结构与算法】新的旅程之时间复杂度和空间复杂度
  • 学Linux的第五天
  • 如何在被 DDoS 攻击时更换 IP 地址
  • Vue项目中动态路由与权限控制:router.beforeEach的使用及无token重定向登录页
  • Linux上python离线安装教程
  • 常见问题 | 数字签名如何保障电子商务交易安全?
  • 【代码随想录Day60】图论Part11
  • Linux 文件系统权限
  • Spring Boot 中的过滤器 (Filter) 使用方案
  • 关于自动驾驶等级相关知识
  • ubuntu20.04 加固方案-设置SSH是否使用业界认可的加密算法
  • Kubernetes(K8s)相关漏洞介绍
  • SpringMVC实战(3):拓展
  • 【C/C++】字符/字符串函数(1)——由string.h提供
  • QT报错,QObject::setParent: Cannot set parent, new parent is in a different Thread
  • 虚拟滚动 - 从基本实现到 Angular CDK
  • 在阿里云快速启动Umami玩转网页分析
  • RabbitMQ怎么保障消息的可靠性
  • 预约小程序多选修改——思路分享
  • Android OkHttp与HttpsURLConnection如何修改支持的TLS版本