LoRA在论文"LoRA: Low-Rank Adaptation of Large Language Models"(Hu等,微软研究院,2021年)中被提出。主要动机是解决完整微调的低效率问题,同时不牺牲性能。作者观察到,在微调过程中,模型权重并不会任意变化,而是倾向于沿着参数空间中的低秩方向移动。
换句话说:模型的权重更新可以近似为低秩矩阵。
在Transformer模型中,关键操作(如注意力层中的投影)是通过矩阵乘法执行的。例如,查询投影计算为:
Q = X * W_Q
其中:
X是输入(前一层的激活值)W_Q是查询投影的可训练权重矩阵在完整微调中,W_Q被直接更新,意味着修改其所有元素。
在LoRA中,W_Q被保持冻结,并引入低秩更新:
Q = X * (W_Q + B * A)
其中:
A是大小为(d_model, r)的矩阵B是大小为(r, d_head)的矩阵r是秩(一个小的超参数,通常在4到64之间)d_model和d_head是W_Q的原始维度矩阵B * A的秩为r,远低于W_Q的完整秩。这意味着不是更新数百万个参数,而只训练A和B的参数,总计:
LoRA参数数量 = r * (d_model + d_head)
例如,如果d_model = 4096,d_head = 128,且r = 8,那么:
LoRA参数 = 8 * (4096 + 128) = 8 * 4224 = 33,792
而原始矩阵W_Q可能有4096 * 128 = 524,288个参数。也就是说,只有原始参数的6.4%被训练。
r(秩): 控制可训练参数的数量。低值(4-8)足以应对简单任务;高值(32-64)用于复杂任务。r值过高会消除效率增益。lora_alpha: 缩放因子,控制更新B * A的幅度。通常设置为r的倍数(例如,如果r = 8,则alpha = 16)。作为LoRA更新的"隐式学习率"。lora_dropout: 应用于LoRA层输出的dropout,用于正则化。典型值:0.0到0.1。target_modules: 应用LoRA的模型模块列表。在Transformers中,通常应用于注意力层中的查询和值投影(q_proj,v_proj)。有时也应用于k_proj,o_proj,或密集MLP层(fc1,fc2)。Hugging Face的peft库允许在几行代码中将LoRA应用于任何与transformers接口兼容的模型:
from peft import LoraConfig, get_peft_model
# LoRA配置
lora_config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 将LoRA应用于模型
model = get_peft_model(model, lora_config)
# 模型现在只训练LoRA参数
model.print_trainable_parameters() # 显示可训练参数的数量
这会转换原始模型,使得在训练期间只更新指定层中的A和B矩阵。其余部分保持冻结。