LoRA
Published:
LoRA
原理
LoRA 的全称是 Low-Rank Adaptation, 中文可译为“低秩适配”, 是 PEFT 的一种. 所谓 PEFT 是 Parameter-Efficient Fine-Tuning, 即参数高效微调. 它最早被系统地用于大语言模型的参数高效微调, 但其作用对象本质上是神经网络中的线性层, 因此同样适用于 Transformer 和扩散模型等.
一句话概括 LoRA: 保留预训练模型的原始权重不动, 在部分线性层旁边增加一个规模很小、可以训练的低秩分支, 用这个分支学习新任务需要的权重变化.

我们找一个全连接层, 设其输入为 $x\in \mathbb{R}^{d\times 1}$, 输出为 $h\in \mathbb{R}^{k\times 1}$, 其原始权重矩阵为 $W_0\in\mathbb{R}^{k\times d}$, 在原始模型中有
\[h=W_0 x\]LoRA 的做法是插入一个并行的新的权重矩阵 $\Delta W\in \mathbb{R}^{d\times k}$, 训练时冻结原始权重矩阵 $W_0$, 只训练 $\Delta W$. 也就是说
\[h = (W_0+\Delta W)x\]我们将 $\Delta W$ 分解为降维矩阵 $A\in \mathbb{R}^{r\times d}$ 和升维矩阵 $B\in \mathbb{R}^{k\times r}$, 其中 $r\ll \min{d,k}$.从而
\[h = (W_0+\Delta W)x = W_0x + BAx\]这样一来, 我们新增的参数量为 $r(k+d)$, 我们需要训练的参数也是这些. 这远小于 $W_0$ 的参数量 $d\cdot k$, 并且这完全保留了原始模型的先验.
LoRA 能 work 的原因是大模型往往是过参数化的, 大部分有效信息会分布在一个低维空间.
调参
初始化
$A$ 使用标准正态分布初始化, $B$ 使用 零矩阵初始化, 这样当数据第一次通过网络时,它和预训练的结果是一致的,这样便保证了模型在初始阶段便有一个不错的效果.
使用的地方
[4] 的实验建议在 Transformer 中, 对 $W_q, W_k, W_v, W_o$ 都运用 LoRA, 并且在所有 MLP 和 MoE 层也用上 LoRA. [4] 的实验结果是后者更加重要.
缩放系数
原始论文 [5] 提到 We then scale ∆W x by α r , where α is a constant in r.
\[h = W_0x+ \frac{\alpha}{r}\Delta Wx\]社区实践往往取 $\alpha/r$ 为固定值.
这里感觉不太对, 我查了一下, 依据 [1], [2], [3], 的分析, 更好的做法应该是取
\[h = W_0x+ \frac{\alpha}{\sqrt{r}}\Delta Wx\]并且 $\alpha$ 没有道理跟着 $r$ 缩放. 我感觉可能是因为原始论文将分母取得更大了(从理论的 $\sqrt{r}$ 变成了 $r$), 实践中用 $\alpha$ 的同步缩放做了一些抵消. 此外, [1] 提到 $\alpha$ 应该取比较大的值(大语言模型中采用 256).
学习率
[4] 建议使用十倍于全量微调的学习率
参考
[1] A Rank Stabilization Scaling Factor for Fine-Tuning with LoRA
[2] The Hidden Power of Scaling Factor in LoRA Optimization
[3] https://zhuanlan.zhihu.com/p/685589734
[4] https://thinkingmachines.ai/blog/lora/#introduction
[5] LoRA: Low-Rank Adaptation of Large Language Models