- 文献阅读:Sparse Low-rank Adaptation of Pre-trained Language Models
- 1. 文章简介
- 2. 具体方法介绍
- 1. SoRA具体结构
- 2. 阈值选取考察
- 3. 实验 & 结论
- 1. 基础实验
- 1. 实验设置
- 2. 结果分析
- 2. 细节讨论
- 1. 稀疏度分析
- 2. rank分析
- 3. 参数位置分析
- 4. 效率考察
- 1. 基础实验
- 4. 总结 & 思考
- 文献链接:https://arxiv.org/abs/2311.11696
- GitHub链接:https://github.com/TsinghuaC3I/SoRA
1. 文章简介
这篇文章是清华大学在23年11月发表的一篇针对LLM的高效finetune方面的工作。
众所周知,LLM虽然效果很好,但是由于其极其巨大的参数量,对LLM的finetune一直是一个老大难问题,因此最近针对这方面的研究也是层出不穷,其中最为知名的可能就是微软提出的LoRA算法了,我自己之前也整理了一篇水文来介绍过这篇工作(文献阅读:LoRA: Low-Rank Adaptation of Large Language Models)。
整体上来说,LoRA的核心思路就是用一个额外的Adapter网络来模拟模型finetune之后的参数微扰,使得原始模型的输出加上Adapter模型的输出近似于finetune之后的模型输出。此时,我们只需要train一个很小的adapter就可以来模拟模型的finetune了,既不用改动原始大模型的结构,也不需要增加很多额外的参数。
但是,LoRA有一个比较大的问题就是它默认了微扰对于各个层的影响都是一样的,且都是比较小的,因此LoRA对所有层都共享一个超参,就是adapter中间层的维度。而这个假设事实上是有点强的,因此后续也有一些工作尝试对这个点进行优化,文中提到的一个典型工作就是AdaLoRA,它通过奇异值分解的方式来动态调整不同层所需的Adapter中间层的维度,但是因为他引入了奇异值分解,因此需要挺多的额外计算量,且需要引入一些额外的正交假设。
基于此,文中提出了一个新的他们命名为SoRA的方法,本质上来说,它和AdaLoRA一样,也是希望动态调整不同层中Adapter中间层的维度,但是相较于AdaLoRA,更加简单直接,无需引入额外的假设,且不会增加多少额外的计算量。
下面,我们来具体看一下文中提出的SoRA方法的具体实现和对应的实验以及实验结果。
2. 具体方法介绍
1. SoRA具体结构
下面,我们首先来看一下SoRA的整体结构。
可以看到,本质上来说,SoRA依然走的还是LoRA的降维投影的模式,不过,SoRA的思路是先给一个较大的中间维度,然后通过 L 1 L_1 L1正则来获取参数的稀疏性,然后通过要给阈值来对维度进行剪裁,使得最终使用的中间矩阵 W u W_u Wu与 W d W_d Wd是两个较小维度的矩阵。
具体来说的话,我们先给出一个具有较大中间维度的系数投影矩阵 W u W_u Wu与 W d W_d Wd,这部分的定义是和LoRA完全一样的,然后我们给出一个门向量来对中间维度进行稀疏化剪裁,使得 W u W_u Wu与 W d W_d Wd当中用不到的部分直接置零被抹去。
具体的扰动量输出结果就是:
z = W u ( g ⊙ ( W d ⋅ x ) ) z = W_u(g \odot (W_d \cdot x)) z=Wu(g⊙(Wd⋅x))
然后,关于这个门向量 g g g的训练方式的话,就是通过如下的方式:
g t + 1 = Γ η t ⋅ λ ( g t − η t ∇ L 0 ( △ t ) ) g_{t+1} = \Gamma_{\eta_t \cdot \lambda} (g_t - \eta_t \nabla L_{0}(\triangle_t)) gt+1=Γηt⋅λ(gt−ηt∇L0(△t))
其中,阈值函数的定义为:
Γ ξ ( x ) = { x − ξ , x > ξ 0 , − ξ < x ≤ ξ x + ξ , x ≤ − ξ \Gamma_{\xi}(x) = \left\{ \begin{aligned} &x - \xi, && x > \xi \\ &0, && -\xi < x \leq \xi \\ &x + \xi, && x \leq -\xi \\ \end{aligned} \right. Γξ(x)=⎩ ⎨ ⎧x−ξ,0,x+ξ,x>ξ−ξ<x≤ξx≤−ξ
这个实现的本质事实上就是 L 1 L_1 L1正则,换用另一个等价形式可以写为:
g t + 1 = a r g m i n g η t ⋅ λ ∥ g ∥ 1 + 1 2 ∥ g − ( g t − η t ∇ L 0 ( g t ) ) ∥ 2 2 g_{t+1} = \mathop{argmin}\limits_{g} \eta_t \cdot \lambda \| g \|_1 + \frac{1}{2} \| g - (g_t - \eta_t \nabla L_0(g_t)) \|_2^2 gt+1=gargminηt⋅λ∥g∥1+21∥g−(gt−ηt∇L0(gt))∥22
而这个恰好就是 L 1 L_1 L1正则项:
L ( △ ) = L 0 ( △ ) + λ ∑ k = 1 K ∥ g ( k ) ∥ 1 L(\triangle) = L_0(\triangle) + \lambda \sum\limits_{k=1}^{K} \| g^{(k)} \|_1 L(△)=L0(△)+λk=1∑K∥g(k)∥1
因此,我们可知 g g g会趋向于稀疏,而由此,我们就可以对参数矩阵 W u W_u Wu与 W d W_d Wd进行降维剪裁。
可以看到,上述实现和AdaLoRA基本上是有异曲同工之妙的,本质上都是先设置一个较大的中间维度之后进行剪裁,不过,相较于AdaLoRA,用文中的话来说,SoRA并没有引入额外的正交限制,且只使用 L 1 L_1 L1正则来动态控制每一层中间层的剪裁力度,因此多少显得更加直接以及优雅一些。
2. 阈值选取考察
最后,文中还讨论了一下上述实现中的阈值参数 ξ \xi ξ的选择,通过控制 ξ \xi ξ,我们就可以有效地控制最终的输出向量 g g g的稀疏性,因此,关于 ξ \xi ξ的选择,事实上是需要注意一下的,显然太稀疏的话会影响模型的效果,而太稠密的话那么稀疏化的意义也就没有了,耗费的计算量也大。
因此,文中给出了一个 ξ \xi ξ的schedule算法如下:
通过上述算法,文中得到了一系列不同稀疏度的模型,然后对其进行分析就可以获得一些关于 ξ \xi ξ的直观认知了。
3. 实验 & 结论
下面,我们来看一下文中给出的具体实验内容。
1. 基础实验
1. 实验设置
首先,关于SoRA的具体实验设计方面,文中使用的baseline模型主要包括以下一些:
- Adapter
- BitFit
- LoRA
- AdaLoRA
其次,文中使用的实验数据集为GLUE数据集。
最后,关于文中实验所使用的模型,文中主要是使用DeBERTaV3-base和RoBERTa-large模型进行考察,不过主要还是前者为主。
2. 结果分析
下面,我们给出文中得到的基础实验的结果如下:
可以看到:
- SoRA与AdaLoRA的效果相近,均基本都能够干掉LoRA。
为了更好地比较SoRA与LoRA,文中还控制两者在拥有相同的中间维度进行了一下比较,得到结果如下:
可以看到:
- SoRA的参数量均少于LoRA,但是效果基本都能够优于LoRA模型。
2. 细节讨论
然后,我们来看一下文中关于SoRA的细节讨论分析。
1. 稀疏度分析
首先,我们来看一下稀疏度对SoRA效果的影响,文中给出结果示意图如下:
可以看到:
- 整体来说,只需要很小的参数量,SoRA的效果就能控制和完整的参数量差不多。
2. rank分析
其次,文中还对不同任务下SoRA在各个层当中保留的中间层的维度进行了分析讨论,得到结果如下:
可以看到:
- 不同任务下,SoRA保留的中间层的维度是不相同的,QQP的保留维度明显就要高于QNLI任务;
- 同一任务当中网络的不同部分所需要保留的中间维度也不尽相同,多数情况下FFW层所需的中间维度是要高于其他部分的。
3. 参数位置分析
此外,文中还对attention层当中QKV矩阵进行了更细致的讨论,看看SoRA分别作用于这几部分时的影响,得到结果如下:
可以看到:
- 整体上还是所有部分都使用了SoRA之后能获得最优的效果。
4. 效率考察
最后,文中还对比了SoRA与AdaLoRA的训练效率,得到结果如下:
可以看到:
- 相较于AdaLoRA,SoRA在训练上成本更低,耗时更少。
4. 总结 & 思考
综上,文中提出了一个LoRA的优化算法SoRA,目的是动态调整LoRA的中间维度,使得模型可以在保留tuning效果的前提下进一步压缩extra模型的参数量。
当然,考虑到我们当前的工作事实上来LoRA都用不到,根本不涉及LLM的tuning,因此这部分暂时应该也没有机会去上手实操看看了,不过整体上感觉还是非常有价值的一个工作,后面有机会的话还是想试试……
啊啊啊啊啊,我想train模型啊,天天调prompt,真的是烦死了!!!!!