Lora没有真正地“调”预训练的参数,而是增加了一个低秩矩阵。
思路:
LLM的预训练模型的权重很可能是满秩的,这代表几乎全部的权重都是有意义的。
Lora的目的就是用更少的权重(低秩的表达),来近似的代替原始的预训练满秩参数。(类似于PCA)
实现方案;
代码实现:
input_dim = 768 # 例如,预训练模型的隐藏大小
output_dim = 768 # 例如,层的输出大小
rank = 8 # 低秩适应的等级'r'
W = ... # 来自预训练网络的权重,形状为 input_dim x output_dim
W_A = nn.Parameter(torch.empty(input_dim, rank)) # LoRA权重A
W_B = nn.Parameter(torch.empty(rank, output_dim)) # LoRA权重B初始化LoRA权重
nn.init.kaiming_uniform_(W_A, a=math.sqrt(5))
nn.init.zeros_(W_B)
def regular_forward_matmul(x, W):
h = x @ W
return h
def lora_forward_matmul(x, W, W_A, W_B):
h = x @ W # 常规矩阵乘法
h += x @ (W_A @ W_B) * alpha # 使用缩放的LoRA权重
return h
Reference: