面试官:“什么是低秩适配 LoRA?” 我:“省显存。” 面试官:“那 A 和 B 到底怎么训?”
面试鸭
2026年05月27日 13:53

LoRA 不是省显存这么简单

很多人说自己会 LoRA,其实只是会写一段配置。

比如简历上写:

熟悉 LoRA / QLoRA 微调,使用 PEFT 完成大模型适配。

面试官一般不会停在这。

他会继续问:

“LoRA 为什么叫低秩?”

“A 和 B 两个矩阵分别干什么?”

“为什么常见配置只挂 q_proj、v_proj?”

“推理时合并权重和不合并权重,差别是什么?”

这时候,只答一句“LoRA 省显存”,就不够了。

省显存只是结果。

面试官想听的是你知不知道它怎么省、牺牲了什么、上线时怎么用。

LoRA 这道题,表面考原理,实际考的是你有没有把微调当成一个工程方案来理解。

鸭鸭觉得,很多候选人会在三个地方露馅。

第一,只会说“冻结原模型,只训练小参数”,但说不清这个“小参数”为什么能代表权重更新。

这就像你说“我给模型打了补丁”,但讲不清补丁贴在哪、为什么贴这么小还能起作用。

第二,只会背 r、alpha、dropout,但不知道这些参数会怎么影响训练。

r 不是越大越好。

alpha 也不是随便填。

dropout 更不是看到示例里有就照抄。

面试官问这些,不是想听你报默认值,而是想看你有没有调过、踩过、对比过。

第三,只会训练,不会部署。

LoRA 很适合训练阶段省资源,但项目最后总要上线。

单任务服务,合并权重更简单。

多任务服务,保留多个 LoRA 模块更灵活。

如果这个区别说不清,面试官会默认你只跑过 demo,没有真正想过部署。

所以今天这题别写成“LoRA 是什么”的百科介绍。

更好的回答方式是:

先说清楚低秩适配的核心思想。

再说清楚怎么结合 LoRA 做微调。

最后补上几个面试官最爱追的细节:为什么只加 Q/V、A/B 怎么初始化、推理要不要合并权重。

下面这道题就是标准答案,适合直接收藏。

……

【什么是低秩适配(LoRA)技术?如何结合 LoRA 技术进行微调?】

回答重点

LoRA(Low-Rank Adaptation) 的核心思想是:模型在微调时的权重变化矩阵 ΔW 通常是低秩的,可以分解成两个小矩阵 A 和 B 的乘积。原始权重冻住不动,只训练 A 和 B,推理时把 A×B 加回原权重就行。

原始前向计算是 y = Wx,加了 LoRA 之后变成 y = Wx + BAx。其中 W 是 d×d 的原始权重矩阵(假设是 4096×4096),A 是 r×d 的降维矩阵,B 是 d×r 的升维矩阵,r 一般取 8、16、32 这种小数字。这样可训练参数从 d² 降到 2dr,参数量直接砍掉两个数量级。

比如一个 7B 参数的模型,全量微调要训 7B 个参数;用 LoRA 只训注意力层的 Q 和 V 投影,r=8 的话可训练参数只有几百万,存储开销从几十 GB 缩到几十 MB。

image.png

如何结合 LoRA 进行微调

1)选择适配层。一般加在注意力机制的 Query 和 Value 投影矩阵上,这两层对任务适配最敏感。也可以加在 Key 投影或 FFN 层,效果因任务而异。

2)设置超参数。最关键的是秩 r,决定了低秩矩阵的表达能力;还有缩放因子 alpha,控制 LoRA 输出对原权重的影响程度;以及 dropout 防止过拟合。

3)注入 LoRA 模块。用 Hugging Face PEFT 库几行代码搞定:

代码块
PlainText
自动换行
复制代码
from peft import get_peft_model, LoraConfig
​
config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05
)
model = get_peft_model(base_model, config)
复制成功

4)训练。在下游任务数据上训练,只有 A 和 B 矩阵会更新梯度,原模型参数完全冻结。训练速度比全量微调快很多,显存占用也小得多。

5)推理。两种方式:一是把 A×B 的结果加到原权重上合并成一个模型,推理时没有任何额外开销;二是保持分离,动态加载不同任务的 LoRA 模块,方便多任务切换。

扩展知识

为什么低秩假设成立

这个假设来自一个观察:预训练模型已经学到了很强的通用表示,微调时需要调整的只是让这些表示适配特定任务的那部分"方向"。这种调整往往集中在少数几个主成分上,本质上就是低秩的。

实验也验证了这一点:即使把全量微调的 ΔW 做 SVD 分解,前几个奇异值就能解释绝大部分方差。LoRA 直接跳过全量训练,用低秩矩阵去逼近这个 ΔW,效果接近但成本低得多。

超参数怎么调

秩 r 是最关键的参数。r 太小,低秩矩阵表达能力不够,复杂任务上欠拟合;r 太大,参数量上去了省资源的优势就没了。实践中一般从 r=8 或 r=16 开始,简单任务 r=4 可能就够,复杂任务可能要到 r=64。

缩放因子 alpha 控制 LoRA 输出的放大倍数,实际用的是 alpha/r 这个比例。常见做法是把 alpha 设成 r 的 2-4 倍,比如 r=8 时 alpha=32。

dropout 防止过拟合,一般设 0.05-0.1。数据量大可以不用或设更小。

target_modules 决定给哪些层加 LoRA。只加 Q 和 V 是最常见的配置,效果不够好可以试试加上 K、O 投影甚至 FFN 层的 up/down projection。

与其他 PEFT 方法对比

方法参数量推理延迟实现复杂度效果LoRA极少(~0.1%)无增加(可合并)简单接近全量Adapter少(1%-5%)略增加简单接近全量Prefix Tuning极少无增加中等(调参多)中等Prompt Tuning极少无增加简单中等

LoRA 最大的优势是推理时可以把 A×B 合并回原权重,完全没有额外延迟。Adapter 推理时要多过一层计算,延迟会涨 3%-5%。

QLoRA:进一步压缩

QLoRA 在 LoRA 基础上加了 4-bit 量化:基座模型用 4-bit NF4 格式存储,只有 LoRA 的 A、B 矩阵用 16-bit 训练。配合双量化和分页优化器,一张 48GB 显存的 GPU 就能微调 65B 参数的模型,效果跟 16-bit 全精度几乎一样。

代码块
PlainText
自动换行
复制代码
from transformers import BitsAndBytesConfig
​
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)
model = AutoModelForCausalLM.from_pretrained(
    model_name, quantization_config=bnb_config
)
复制成功

应用场景

1)资源受限的环境。一张消费级显卡就能微调 7B 甚至 13B 的模型,不用再租 8 卡集群。

2)多任务切换。基座模型只存一份,不同任务加载不同的 LoRA 模块,存储和切换成本都很低。同一个服务可以用 LoRA 热切换的方式支撑几十个不同任务。

3)快速迭代。LoRA 训练快、部署快,适合在模型开发早期快速验证想法。

相关论文与扩展阅读链接

1)LoRA: Low-Rank Adaptation of Large Language Models

2)LoRA项目实现​

面试官追问

提问:LoRA 为什么通常只加在 Q 和 V 层,不加在 K 层?

回答:实验发现 Q 和 V 对任务适配最敏感,只加这两层就能拿到绝大部分收益。K 层加上去收益很小但参数量翻倍,性价比不高。原论文做过消融实验,Q+V 的效果跟 Q+K+V+O 全加几乎一样。当然这不是绝对的,某些特定任务加上 K 或者 FFN 层效果会更好,需要根据实际情况调。

提问:LoRA 的 A 和 B 矩阵怎么初始化?

回答:B 矩阵初始化为全零,A 矩阵用高斯随机初始化。这样初始状态下 BA=0,LoRA 输出为零,模型行为跟原始预训练模型完全一致。训练过程中 A 和 B 逐渐学到有意义的值。这种初始化策略保证了训练的稳定性,不会因为随机初始化破坏预训练学到的知识。

提问:推理时把 LoRA 合并到原权重有什么好处和坏处?

回答:好处是推理延迟为零,跟原模型一模一样,部署也简单。坏处是每个任务都要存一份完整的合并后权重,存储成本高;切换任务要重新加载整个模型,不够灵活。不合并的话,基座模型只存一份,不同任务只需加载几 MB 的 LoRA 权重,切换也快,但推理时多一次矩阵乘法。根据实际场景选择:单任务部署建议合并,多任务服务建议保持分离。

提问:LoRA 微调后的模型能继续做全量微调吗?

回答:可以。把 LoRA 的 A×B 合并到原权重后,就变成了一个普通的模型,可以继续做全量微调或者再加一层新的 LoRA。实际操作中也有人用多轮 LoRA 迭代的方式,第一轮微调完合并,再加新的 LoRA 做第二轮,每轮专注不同的能力提升。

篇幅有限,更多 AI 大模型 相关面试题可以进入面试鸭进行查阅。