考察点
这道题出自快手大模型岗位面试,是 LoRA 原理题里的经典细节题,专门筛掉只会调 PEFT 库默认参数的候选人。面试官想确认你真的理解初始化的设计动机:为什么训练开始时模型行为必须和原模型一致,以及从梯度流的角度分析两个矩阵能不能互换初始化方式。追问常往 LoRA 的其他变体(PiSSA、LoRA-GA)、rank 和 alpha 的作用走。
参考答案
LoRA 的结构先交代清楚
LoRA 冻结预训练权重 W,给每层加一个低秩旁路:前向变成 y = Wx + BAx,其中 A 是 r×d 的降维矩阵,B 是 d×r 的升维矩阵,r 远小于 d(常见 8、16、64)。训练只更新 A 和 B,参数量从 d² 降到 2·d·r,通常只占原模型的千分之几。
标准初始化:A 高斯、B 全零
LoRA 论文和主流实现(PEFT 库默认)的做法是:
- A 矩阵:随机初始化,通常用高斯分布 N(0, σ²),有的实现用 Kaiming uniform;
- B 矩阵:全部初始化为 0。
这样设计的第一动机很直接:训练起点时 ΔW = BA = 0,模型行为和未微调的预训练模型完全一致。微调是在预训练能力上做增量调整,如果一开始就加一个随机扰动(A、B 都随机初始化,BA 是个随机矩阵),等于先给模型来一刀随机破坏再开始学习,既浪费训练步数去修复,也可能损伤预训练能力。B 置零保证了「从零增量开始」,这是迁移学习里很基本的直觉——新模块初始时不该改变原函数。
B 为 0 梯度会不会断?不会,反过来才会
这题真正的分水岭在这里:很多人第一反应是「B 全是 0,梯度不是也没了吗」,这是错的,算一下就清楚。
设损失 L,ΔW = BA。两个矩阵的梯度分别是:
- ∂L/∂B = (∂L/∂ΔW) · Aᵀ
- ∂L/∂A = Bᵀ · (∂L/∂ΔW)
初始时 B = 0、A 是随机非零:
- ∂L/∂B = 梯度 · Aᵀ ≠ 0,B 第一步就能学到东西;
- ∂L/∂A = Bᵀ · 梯度 = 0,A 第一步不动。
但 B 更新一步之后就不再是 0 了,第二步起 ∂L/∂A 也非零,两个矩阵进入联合训练。所以 B 置零只让 A 滞后一步,训练完全正常。这在训练动力学上还有个好处:B 置零相当于打破了 A、B 之间的对称性,让两个矩阵学到不同的角色。
反过来行不行:A 置零、B 随机?不行
如果把两者调换——A = 0、B 随机:
- ∂L/∂A = Bᵀ · 梯度 ≠ 0,A 能动;
- ∂L/∂B = 梯度 · Aᵀ = 0,B 永远不动。
而 B 不动意味着 ΔW = BA 永远是 0(A 怎么更新都被零矩阵 B 乘没),模型学不到任何东西,训练彻底死锁。所以答案明确:B 可以置零(且应该置零),A 不行。两个都置零同样死锁——所有梯度全为零。
本质原因是链式法则里梯度要穿过另一个矩阵:置零的那个矩阵会把传给对方的梯度掐断,所以必须保证「非零初始化矩阵的梯度路径」先被激活,而激活它的条件恰恰是对方置零时自己的梯度不依赖对方。不对称初始化就是这么来的。
补充:初始化不是只有这一种选择
标准做法不是金科玉律,可以提一嘴变体显示视野:PiSSA 用原权重 W 的 SVD 分解的主奇异分量初始化 A 和 B(都不为零),让 LoRA 一开始就去拟合原权重里最重要的方向,收敛更快;LoRA-GA 用全量微调第一步的梯度方向初始化。这些变体牺牲「起点等价原模型」换取更快的收敛,说明初始化本质是个 trade-off,但默认的 A 随机 + B 置零依然是大多数场景的稳妥选择。
可能的追问
- rank 和 alpha 怎么选? 答:rank 决定容量,8-16 对多数任务够用,复杂任务上 64;alpha 是缩放系数(实际缩放是 alpha/r),一般设 alpha = 2r 起步,调 alpha 相当于调 LoRA 支路的学习率。
- LoRA 加在哪些层? 答:至少加在注意力的 Q、V 上(论文原始做法);实践上加满 Q、K、V、O 和 FFN 效果更稳,代价是参数量上升,但仍远小于全量微调。
- B 置零会不会让训练前期浪费? 答:只滞后一步梯度,影响可忽略;相比随机初始化破坏预训练能力的代价,这个设计是净收益,PiSSA 类方法的存在只是说明还有更优解而非默认解有错。