【笔记】Lora微调原理
大语言模型微调算法
基本原理:低秩矩阵相乘升维,与预训练权重矩阵叠加,实现模型微调
原理简述:冻结预训练的模型参数,然后在Transfomer的每一层中加入一个可训练的旁路矩阵(低秩可分离矩阵),接着将旁路输出与初始路径输出相加输入到网络当中。在训练的时候,只训练这些新增的低秩矩阵的参数。其中低秩矩阵由两个矩阵组成,第一个矩阵负责降维,第二个矩阵负责升维,中间层维度为r,两个低秩矩阵能够大幅度减小参数量。
原理解释:
输入为x
,输出为h
,预训练模型:
$h=W_{0}x$
在全参数量上微调(regular finetuning):
$h=W_{0}x+△Wx$
如果采用低秩可分离矩阵(LoRA),则:
$$h=W_{0}x+△Wx=W_{0}x+BAx $$
在这个过程中,最核心的步骤便是将 $△W$ 进行分解,将其分解为两个低秩矩阵。如果只使用单独的一个矩阵,那么参数量为 $$dd$$,如果使用低秩可分离矩阵,此时原来的大矩阵可分解为两个秩为 $r$ 的大小为 $$dr$$ 的小矩阵,参数量大小为 ,由于 $$r<d$$ 所以可以大幅度减少参数量。
即:*A矩阵采用一个 $$dr$$ 矩阵,B矩阵采用一个 $$rd$$ 矩阵,总参数量 $$2rd$$ **
公式推导:
LoRA 作用形式:$W=W_{plm}+aW_{lora}=W_{plm}+aB_{lora_{zeros}}*A_{lora_{gaussian}}$
论文中,将 LoRA 作用在 Query 与 Value 权重矩阵上效果最好:
attention query
映射矩阵:$W_{q}=W_{q_{plm}}+aW_{q_{lora}}$
attention value
映射矩阵:$W_{v}=W_{v_{plm}}+aW_{v_{lora}}$
Attention
计算结果:
$head=softmax(Q,K)XW=softmax(Q,K)X(W_{v_{plm}}+aXW_{v_{lora}})=softmax(Q,K)XW_{v_{plm}}+asoftmax(Q,K)XW_{v_{lora}}$
低秩分解:
· 如何实现低秩分解?
低秩分解是一种将矩阵分解为低秩近似的技术。在LORA中,我们使用低秩矩阵来编码参数增量。假设我们有一个预训练的权重矩阵,它的维度是高的。我们可以将这个矩阵分解为两个低秩矩阵的乘积,例如:$$W= UV^T$$其中U 和V是低秩矩阵。
##矩阵中,row2 = row1 * 2,row3 = row1*3,也就是说,矩阵中的每一行,都可以通过第一行线性表示。
A = [[1, 2, 3],[2, 4, 6],[3, 6, 9]]
#任意一行,总可以用其他两行的线性组合来表示。
B = [[1, 2, 3], [7, 11, 5],[8, 13, 8]]
#任意一行,都不能从其余行的线性组合中推导而来。
C = [[1, 0, 0],[0, 1, 0],[0, 0, 1]]
#求解秩:
A = np.array(A)
B = np.array(B)
C = np.array(C)
print("Rank of A:", np.linalg.matrix_rank(A)) # 1
print("Rank of B:", np.linalg.matrix_rank(B)) # 2
print("Rank of C:", np.linalg.matrix_rank(C)) # 3
# 对矩阵A来说,由于只要掌握其中的任意一行,其余行都可以由这一行线性推导而来,因此A的秩是1。
# 对矩阵B来说,由于只要掌握其中的任意两行,其余行都可以由这两行线性组合推导而来,因此B的秩是2。
# 对矩阵C来说,由于必须完全掌握三行,才能得到完整的C,因此C的秩是3。
# 简单理解一下,秩表示的是矩阵的信息量。
#如果矩阵中的某一维,总可以通过其余维度线性推导而来,那么对模型来说,
#这一维的信息是冗余的,是重复表达的。
#对A和B的情况,我们称为秩亏(rank deficient),
#对C的情况,我们称为满秩(full rank)。
· 对A矩阵,采用随机高斯初始化;对B矩阵,采用zero初始化。这样做的原因是要保证梯度更新有效。
$ℎ_{𝑖}^{(2)}$ 是输出向量 $h$ 的第 $i$ 个元素,$B_{i,k}$ 是矩阵 $B$ 的元素,$A_{i,k}$ 是矩阵 $A$ 的元素,而 $x_{j}$ 是输入向量 $x$ 的第 $j$ 个元素。
计算权重 $B$ 中元素 $B_{i,k}$ 的偏导数来进行梯度下降。固定 $i$ 和 $k$,对所有的 $j$ 进行求和,将 $A$ 的对应元素与输入向量的元素相乘并累加。
$B_{i,k}$ 的每个更新都是由 $x$ 和 $A$ 的对应元素的乘积影响的,故而对A矩阵,采用随机高斯初始化;对B矩阵,采用zero初始化。