LoRA详解

一、背景与贡献

背景:通过微调预训练模型适应下游任务,但随着模型增大,全量微调(finetuning)成本高。

主要贡献:
1.LoRA方法的提出:文章提出了一种新的低秩适应(Low-Rank Adaptation, LoRA)方法,用于在不重新训练所有参数的情况下,对大型预训练语言模型进行有效适应。这种方法通过在Transformer架构的每一层注入可训练的低秩矩阵来实现,从而大幅减少了下游任务的可训练参数数量

2.显著降低参数数量和内存需求:在GPT-3175B上,将训练期间的VRAM消耗从1.2TB减少到350GB。当r=4并且仅调整查询和值投影矩阵时,检查点大小大约减少了10000×(从350GB减少到35MB)。这使得可以使用更少的GPU进行训练,并避免I/O瓶颈。

3.保持或提升模型性能:尽管LoRA减少了可训练参数的数量,但它在多个NLP任务上的性能与完全微调相当或更好,这表明LoRA是一种高效的模型适应方法。

4.无额外推理延迟:LoRA的设计允许在部署时将训练矩阵与冻结权重合并,这意味着在推理时不会引入额外的计算延迟。

5.提高训练效率:与完全微调相比,GPT-3175B LoRA训练期间的速度提高了25%,因为不需要计算绝大多数参数的梯度。

6.易于部署:可以在部署时以更低的成本切换任务,只需交换LoRA权重,而不是所有参数。

总的来说,文章的主要贡献在于提出了一种新的、高效的大型语言模型适应方法,这种方法在减少资源消耗的同时,保持了模型的性能,并且易于与现有技术结合使用。

二、方法原理

当finetune LLM时,我们会在预训练的基础上修改模型参数,简化成如下形式:
在这里插入图片描述
LoRA的核心思想是通过低秩矩阵分解对模型参数的更新进行建模,如下图所示:
在这里插入图片描述
左边预训练模型权重不动,只训练右边的A和B

秩分解矩阵

W 0 W_0 W0被冻结并且不接收梯度更新,而A和B包含可训练参数。
在这里插入图片描述
在这里插入图片描述
r < < m i n ( d , k ) r <<min(d,k) r<<min(d,k)
对A使用随机高斯初始化,对B使用零初始化,因此 △ W = B A \bigtriangleup W=BA W=BA在训练开始时为零(可以确保用模型的原始预训练权重开始微调过程)。
α / r \alpha/r α/r缩放 △ W x \bigtriangleup Wx Wx。当使用Adam进行优化时,如果适当缩放初始化,则调整α与调整学习率大致相同。当改变r时,这种缩放有助于减少重新调整其他超参数的需要(Yang&Hu,2021)。

举个例子:假设W0为512512,就单单只看这部分的话,全参数微调需要调整512512 = 262144个参数,使用LoRA后,这262144个参数就冻结了,此时增加两个低秩矩阵 例如5122和2512,那么此时需要调整的参数大小就为5122+2512 = 2048个参数,2048 / 262144 = 0.0078125,此时要训练的参数就减少了许多。

而且,当我们面对不同的下游任务时,因为原本的预训练模型是冻结的,所以预训练模型用一个就行,只需要保存的参数就是加入的低秩矩阵,这样的话,也能节省大量的存储空间。另一个好处是,可以在部署时以更低的成本切换任务,只需交换LoRA权重,而不是所有参数。这允许创建许多定制模型,这些模型可以在将预训练的权重存储机器上进行动态交换。
伪代码如下:

class LowRankMatrix(nn.Module):
    def __init__(self, weight_matrix, rank, alpha=1.0):
        super(LowRankMatrix, self).__init__()
        self.weight_matrix = weight_matrix
        self.rank = rank
        self.alpha = alpha / rank  # 将缩放因子与秩相关联
        # 初始化低秩矩阵A和B
        self.A = nn.Parameter(torch.randn(weight_matrix.size(0), rank), requires_grad=True)
        self.B = nn.Parameter(torch.randn(rank, weight_matrix.size(1)), requires_grad=True)

    def forward(self, x):
        # 计算低秩矩阵的乘积并添加到原始权重上
        # 应用缩放因子
        updated_weight = self.weight_matrix + self.alpha * torch.mm(self.B.t(), self.A)
        return updated_weight

三、实验结果

  • LoRA可以达到和FineTune相当的精度,参数大幅降低
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

四、LoRA理解

应该将LoRA应用于Transformer中的哪些权重矩阵?

在这里插入图片描述
给定有限的参数预算,应该使用LoRA调整哪些类型的权重,以获得下游任务的最佳性能?

  • 论文在GPT-3175B上设置了18M的参数预算(如果存储在FP16中,大约为35MB),如果调整一种类型的注意力权重,则对应于r=8,如果对所有96层调整两种类型,则对应r=4。

注意, putting all the parameters in ∆Wq或∆Wk会显著降低性能,而调整Wq和Wv会产生最佳结果。这表明,即使是rank=4也能捕获∆W中的足够信息,因此,相同可调整参数约束下, it is preferable to adapt more weight matrices than adapting a single type of weights with a larger rank.

结论:

  • 参数量固定情况下,应用于Wq和Wv可以得到较好的结果
  • 参数固定情况下,Lora以低r适配于更多的矩阵效果好于以高r适配少的矩阵

LoRA的最佳rank是多少?

在这里插入图片描述
This suggests the update matrix ∆W could have a very small “intrinsic rank”. To further support this finding, we check the overlap of the subspaces learned by different choices of r and by different random seeds. We argue that increasing r does not cover a more meaningful subspace, which suggests that a low-rank adaptation matrix is sufficient.
增加r并不能覆盖更有意义的子空间,这表明低秩自适应矩阵就足够了。

那么r如何设置呢?怎么理解r的大小?

  • r越大,获取新知识的可能性就越大
  • r主要看学习领域的垂直性,如果学习领域和原生模型相差大,r需要大一些。r越大,能学习的东西越多,但容易导致灾难性遗忘。
  • 举个例子,如下游任务使用的语言和预训练语言不同时,较大的秩效果当然好于较小的秩

不同r的子空间相似性

给定 Ar=8 and Ar=64,它们是使用相同的预训练模型的秩r=8和64的学习自适应矩阵,进行奇异值分解,得到right-singular unitary matrices UAr=8 and UAr=64 .
在这里插入图片描述
1表示完全重叠,0表示完全分开,Grassman距离表明

  • 最top的奇异向量在A(r=8)和A(r=64)之间显著重叠,而其他方向则不重叠。这就可以解释为何r=1就可以在GPT3很多下游任务中表现良好。

  • top奇异向量方向是最有用的,而其他方向可能包含训练期间积累的大部分随机噪声。因此,自适应矩阵确实可以具有非常低的秩。

  • 类似实验现象,如下图,不同种子随机初始化的delta wq,delta wv,可以发现delta wq的秩高于wv。
    在这里插入图片描述

∆W与W的关系

主要探讨下面两个问题:

  • does ∆W highly correlate with W? (Or mathematically, is ∆W mostly contained in the top singular directions of W?)
  • how “large” is ∆W comparing to its corresponding directions in W?
    实验方法:
    在这里插入图片描述
    结论:
  • 与随机矩阵相比,∆W与W的确有更强的相关性,说明∆W的加入放大了W中已经存在的一些特征。
  • ∆W只放大W中未强调的方向,而不是重复W的top奇异方向
  • 放大系数相当大:当r=4时,放大系数为21.5≈6.91/0.32
  • Lora潜在地放大了在一般预训练模型中学习但未强调的特定下游任务的重要特征。

五、Lora的变体

LoRA的各种变体 LoRA的提出促进了整个大模型微调领域的发展,进而涌现出了很多变体。

  1. QLora:QLoRA可以说是最流行的LoRA变体。QLoRA在微调期间使用模型量化来减少内存使用,同时保持(大致)相等的性能水平。更具体地说,QLoRA对预训练的模型权重使用4位量化,并在此基础上训练LoRA模块。此外,还有多种新的量化技术,以进一步减少内存使用: 4位NormalFloat(NF4)格式:一种新的(量化的)数据类型,适用于遵循正态分布的权重。 双重量化:通过量化模型权重及其相应的量化常数来减少内存占用。 Paged Optimizers:防止在处理长序列或训练大型模型时,由于梯度检查点导致内存不足错误而导致的内存峰值。 在实践中,QLoRA以略微降低训练速度为代价来节省内存。例如,用QLoRA代替LoRA来微调LLaMA-2-7B可以减少33%的内存使用,但增加了39%的训练时间。
  2. QA-LoRA:https://arxiv.org/pdf/2309.14717
  3. LongLoRA:LongLoRA只是一种有效的微调技术,可以使用它来调整预训练的LLM,以支持更长的上下文长度。也就是说,LongLoRA试图使用基于LoRA的微调方案将LLM廉价地调整为更长的上下文长度。

六、使用感受

  • 不同任务r参数可能不同,需要做适配
  • 可以使用较少的gpu资源进行训练或者调试
  • a通常设置为2* r

[1] https://zhuanlan.zhihu.com/p/611557340
[2] http://www.360doc.com/content/23/1217/20/62738899_1107901534.shtml#google_vignette
[3] https://www.douban.com/note/851292112/?_i=1933911ScfdGwq
[4] https://arxiv.org/pdf/2106.09685
[5] https://blog.csdn.net/qq_52785473/article/details/136938053
[6] https://github.com/huggingface/peft

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值