LoRA面试篇
什么是LoRA?
通过低秩分解来模拟参数的改变量,从而以极小的参数量来实现大模型的简介训练;
其思想就是冻结一个预训练模型的矩阵参数,并选择用A和B矩阵来替代,在下游任务时只更新A和B。
思路:
1.在原模型旁边加一个旁路,通过低秩分解(先降维再升维)来模拟参数的更新量;
2.训练时,原模型固定,只训练降维矩阵A和升维矩阵B;
3.推理时,可将BA加到原参数上,不引入额外的推理延迟;
4.初始化,A采用高斯分布初始化,B初始化为全0,保证训练开始时旁路为0矩阵;
5.可插拔式的切换任务,当前任务W0+B1A1,将lora部分减掉,换成B2A2,即可实现任务切换;
特点:
1.将BA加到W上可以消除推理延迟;
2.可以通过可插拔的形式切换到不同的任务;
3.设计的比较好,简单且效果好;
QLoRA
思路:
- 使用一种新颖的高精度技术将预训练模型量化为4bit;
- 添加一组可以学习的低秩适配器权重,这些权重通过量化权重的反向传播梯度进行微调
特点:
使用QLoRA微调模型,可以显著降低对于显存的要求。同时,训练模型的速度会慢于LoRA。
AdaLoRA
思路:
对LoRA的一种改进,他根据重要性评分动态分配承诺书预算给权重矩阵,将关键的增量矩阵分配给高秩以捕捉更精细和任务特定的信息,而将较不重要的矩阵的秩降低,以防止过拟合并节省计算预算;
LoRA微调的优点是什么?
1.一个中心模型服务多个下游任务,节省参数存储量;
2.推理阶段不引入额外计算量;
3.与其它参数高效微调方法正交,可有效组合;
4.训练任务补角稳定,效果比较好;
5.LoRA几乎不添加任何推理延迟,因为适配器权重可以与基本模型合并;
LoRA的缺点是什么?
参与训练的模型参数数量不多,也就百万到千万级别的参数量,所以效果比全量微调差很多。可能在扩撒模型上的感知没有那么强,但在LLM上,个人感觉表现还是差距很大的。
LoRA微调方法为啥能加速训练?
- 只更新了部分参数:比如LoRA原论文就选择只更新Self Attention的参数,实际使用时我们还可以只选择是更新部分参数;
- 减少了通信时间:由于更新的参数量变少了,所以要传输的数据量也变少了,从而减少了传输的时间;
- 采用了各种低精度加速技术,比如FP16、FP8等
这三部分原因确实能加速训练的速度,然而他们并不是LoRA所独有的,事实上几乎所有的参数高效方案都具有这些特点。LoRA的优点是它的低秩分解很直观,在不少场景下跟全量微调的效果一致,以及在预测阶段不增加推理成本。
如何在已有的LoRA模型上训练数据?
理解此问题的情景是:已有LoRA模型只训练了一部分数据,要训练另一部分数据的话,是在这个LoRA上继续训练,还是跟Base模型合并后再套一层LoRA,或者从头开始训练呢?
我认为把之前的LoRA跟Base model合并后,继续训练可以,未来保留之前的知识和能力,训练新的LoRA时,加入之前一些新的数据时很需要的。另外,每次都重头来成本很高。
Rank如何选取?
Rank的取值简单地说,效果上在4-8之间最好,再高并没有效果提升。不过论文的实验是面向下游单一监督任务的,因此在指令微调上根据指令分布的广度,Rank选择还是需要8以上的取值进行测试。
LoRA高效微调如何避免过拟合?
减小r或增加数据集大小可以帮助减少过拟合。
还可以尝试增加优化器的权重衰减率或者LoRA层的Dropout值。
LoRA权重是否可以合并?
可以将多套LoRA权重合并。训练中保持LoRA权重独立,并在前向传播时添加,训练后可以合并权重以简化操作。
是否可以逐层调整LoRA的最优rank?
理论上,可以为不同层选择不同的LoRA rank,类似于为不同层设定不同的学习率,但由于增加了调优的复杂性,实际中很少执行。
LoRA的矩阵如何初始化?为什么要初始化为全0?
矩阵B被初始化为0,而矩阵A正常高斯初始化;
如果B,A全都被初始化为0,那么缺点与深度网络全0初始化一样,很容易导致梯度消失(因为此时初始化所有神经元的功能都是等价的);
如果B,A全部高斯初始化,那么在网络训练刚开始就会有概率为得到一个过大的偏移值,从而引入了太多噪声,导致难以收敛;
因此,一部分初始为0,一部分正常初始化是为了在训练开始时维持网络的原有输出(初始偏移为0),但同时也保证在真正开始学习后能够更好的收敛。