大模型微调LoRA原理:冻结主干参数与低秩矩阵注入
全参微调大模型在工程上并不划算。以7B参数模型为例,Adam优化器需要额外保存一阶二阶动量,显存占用往往是模型权重的3倍以上,一张80G的A100也仅能容纳很小的batch。大模型微调的主流做法是参数高效微调,LoRA(Low-Rank Adaptation)是其中应用最广的一种。
LoRA的核心假设是:预训练模型在适配下游任务时,权重更新的本质秩较低。因此不直接更新权重矩阵W,而是学习一个低秩分解增量。设原始权重为W0,前向计算变为W0·x + BA·x,其中B为r×k矩阵、A为d×r矩阵,r远小于d和k,可训练参数量只占全量的0.1%到1%。训练时冻结W0,只优化BA;推理时可以将BA合并回W0,不引入任何额外延迟。
LoRA微调代码实现:PEFT库与训练配置
Hugging Face PEFT库封装了LoRA的完整流程,配合transformers与datasets,十几行代码即可完成配置。以下是一个把Llama类模型适配到中文指令数据的微调脚本核心片段:
from peft import LoraConfig, get_peft_model, TaskType
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B", torch_dtype="bfloat16")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B")
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
lora_dropout=0.05,
bias="none",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
训练超参上,batch size按显存浮动设1到8,学习率常用1e-4到2e-4(远高于全参微调的1e-5量级),warmup steps设为总步数的3%-5%。目标模块的选择直接影响效果:仅微调注意力投影(q/k/v/o)适合通用能力增强,把MLP的gate与up投影加入后领域知识注入效果更明显。
LoRA微调后的权重合并与推理部署
训练产物是adapter权重(safetensors),体积只有几十MB,便于分发。线上推理可以把LoRA合并回基座,避免推理框架对adapter的额外支持要求:
merged = model.merge_and_unload()
merged.save_pretrained("merged_model", safe_serialization=True)
tokenizer.save_pretrained("merged_model")
合并后的模型与普通基座模型结构一致,可直接用vLLM、TGI等推理框架加载。不想合并时,vLLM自0.4.2版本起支持–lora-modules参数动态加载多个adapter,同一基座模型上按请求路由不同微调版本,单卡服务多个垂直场景。
显存占用与训练效果实测对比
同一条7B指令数据上,全参微调峰值显存约78GB,LoRA(r=16)约18GB,差距来自优化器状态和可训练梯度回传。若叠加bfloat16与梯度检查点,LoRA单卡可跑更大batch。效果上,LoRA在指令跟随任务上能达到全参微调95%以上的分数,在代码与数学这类强逻辑任务上差距略大,可提升r到32并加入更多层投影缓解。数据质量仍是效果上限的决定因素,低秩适配解决的是训练资源约束,不改变数据分布的固有短板。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/da-mo-xing-wei-tiao-lora-shi-zhan-di-zhi-shi-pei-xun-lian/