Part V · 第 21 章 专题 · 21.1

预训练与微调(LoRA)

先在大量、广泛的数据上训练一个模型,再用一小份新数据把它改造成你要的样子:这就是今天几乎所有机器人基础模型的用法。本节在浏览器里先用 32 台机器人的数据预训练一个关节力矩模型,再用几十个测量点把它适配到一台新机器人上,现场比较线性探针、全量微调和 LoRA:谁更省数据,谁会忘掉旧本领,为什么一个只有 2 列的低秩更新就够用,以及 4 位量化(QLoRA)怎样让 650 亿参数的模型在一张显卡上微调。

约 50 分钟 前置:17.3 Transformer 与 Attention · 18.3 对比学习 · 16.2 泛化与正则化 · 1.13 最小二乘 · 1.12 SVD 6 个交互

    1为什么机器人需要它

    机器人数据很贵。一条遥操作演示要一个人花上一两分钟,一台机器人一天也就采几百条;而 17.3 节那样的 Transformer 动辄上亿参数,从零开始训练需要的数据量远远超过一个实验室能采到的。另一方面,互联网上有数十亿张图片和句子,开放数据集里有上百万条来自几十种机器人的轨迹。预训练 + 微调把这两件事接起来:先在“广而杂”的大数据上学到通用的表示和技能(预训练),再用目标任务的“少而精”的数据做一次小幅修改(微调)。

    18.3 节已经见过最简单的一种:冻结预训练好的编码器,只在它的特征上训练一个线性分类器(线性探针)。本节把问题问完整:什么时候冻结就够了?什么时候必须改动网络本身?改动之后,模型原来会的东西还在不在?一个 70 亿参数的视觉-语言-动作模型(VLA),要怎样才能在一张显卡上、用一两百条演示完成微调?答案的核心是 LoRA:不改原始权重,只学一个低秩的增量 \(\Delta W=BA\)。

    2直觉:预训练学到的是一组好的“基函数”

    本节的玩具问题是一个真实的机器人问题:保持力矩。机械臂第 2 个关节要停在角度 \(q\) 不动,电机需要输出多大的力矩 \(\tau(q)\)?它由重力(8.1 节的 \(g(q)\),形如 \(a\cos q+b\sin q\),\(a,b\) 取决于负载和质心)、传感器零偏,以及传动系统里每转重复 4 次的力矩波动组成。同一型号的 32 台机器人负载、零偏、波动的相位都不一样,我们在仿真里为每台采了大量数据。

    预训练的网络是一个“主干 + 多个头”的结构:关节角以 \((\cos q,\sin q)\) 的形式输入(转动关节的常规编码),经过两层 32 个单元的 tanh 隐藏层,再到一个 6 维的表示 \(\hl{phi}{\boldsymbol\phi(q)}\);每台机器人各有一个线性的头,\(\tau_k(q)\approx\mathbf w_k^\top\boldsymbol\phi(q)+b_k\)。为了让 32 个头都满意,主干必须学会这个机器人家族共有的结构。页面打开时这次预训练就在后台跑完了:3000 步,32 台机器人的平均误差降到约 0.014 N·m。

    现在来了第 33 台机器人,我们只测了 12 个角度。最省事的做法是冻结主干,只为它拟合一个新的头 \(\hl{head}{\mathbf w}\):这就是线性探针(linear probe),也就是 1.13 节的最小二乘,基函数换成了 \(\phi_1(q),\dots,\phi_6(q)\)。

    $$ \hat\tau(q)=\hl{head}{\mathbf w}^\top\hl{phi}{\boldsymbol\phi(q)}+b,\qquad \mathbf w,b=\arg\min\sum_{i=1}^{N}\big(\mathbf w^\top\boldsymbol\phi(q_i)+b-\tau_i\big)^2+\lambda\|\mathbf w\|^2 $$
    FIG 1线性探针 = 在冻结的特征上做最小二乘
    左:新机器人的 12 个测量点(琥珀色,可以上下拖动),虚线是它真实的保持力矩曲线(只供你对照,拟合看不到它)。绿线是用预训练特征做的线性探针;切到“预训练之前”,紫线是用同一个网络训练前(随机初始化)的特征做的探针。打开“显示机器人家族”会画出 8 台预训练机器人的曲线(细线)。右上:6 个特征 \(\phi_j(q)\)(青色),线越粗表示探针给它的权重 \(|w_j|\) 越大。读数里的“真实误差”是拟合曲线与虚线在整个关节范围上的均方根误差。
    试一试
    • 切到“预训练之前”的特征:同样 12 个点,探针的真实误差从约 0.04 N·m 涨到 0.2 N·m 以上:随机特征里没有这个家族的形状。
    • 用预训练特征,把 \(1<q<2\) rad 之间的某个点往上拖 0.8 N·m 以上(就像撞上了限位弹簧):探针弯不过去,这个点上的残差超过 0.3 N·m。
    核心洞见

    预训练的价值在于把“这一类问题的答案长什么样”压缩进特征里。新任务如果落在这个家族里,只需要几个数就能确定(这里是 7 个:6 个权重加一个偏置),12 个点绰绰有余,而且误差接近测量噪声。随机特征同样能穿过这些点,却不知道点与点之间该是什么形状。反过来,家族之外的东西(一个预训练时从未出现过的限位弹簧),冻结的特征怎么组合都表达不出来:这时就必须改动主干本身,也就是微调。

    3动手:四种适配方法现场比赛

    给新机器人准备两种情况。同一家族:只是换了负载,曲线仍是重力 + 零偏 + 波动。新的效应:同样的机器人,但装了一个限位弹簧,\(q\) 超过 1 rad 后多出一段约 2 N·m/rad 的线性回弹力矩,这是预训练数据里从没有过的形状。每种情况采 \(N\) 个带噪声的测量(噪声标准差 0.05 N·m),四种方法同时训练:

    • 从零训练:同样结构的网络,随机初始化,所有参数都训练。
    • 线性探针:主干冻结,新头用岭回归一次解出(凸问题,不需要迭代,所以它的曲线一开始就是终点)。
    • 全量微调:从预训练权重出发,所有参数都训练;新头先用线性探针的解初始化(这个做法叫 LP-FT,第 4 节解释原因;LoRA 的新头也这样初始化)。
    • LoRA:所有预训练权重冻结;第二个隐藏层的 32×32 权重矩阵加上一个秩为 \(r\) 的增量 \(\frac{\alpha}{r}BA\),只训练 \(B\)(32×\(r\))、\(A\)(\(r\)×32)和新头。\(B\) 初始化为零,所以训练开始时模型和预训练模型一模一样。

    四种方法用同样的 Adam 优化器、同样的批次(每步最多 32 个样本),训练 1000 步后自动停下。学习率按各自的习惯取:从零训练和 LoRA 用 0.003,全量微调用小一些的 0.001。

    FIG 2从零训练、线性探针、全量微调、LoRA:同一份小数据,四种结果
    左:新机器人的 \(N\) 个测量点(琥珀色)、真实曲线(虚线),以及四个模型此刻的预测:从零训练(紫)、线性探针(蓝)、全量微调(红)、LoRA(绿)。“新的效应”下,竖直虚线标出限位弹簧开始起作用的 \(q=1\) rad。右上:每个模型在整个关节范围上相对真实曲线的均方根误差(测试误差,对数纵轴)随训练步数的变化,颜色同左。表格给出每种方法需要训练的参数个数和当前测试误差。
    • 选“同一家族”、\(N=16\),训练到 1000 步:线性探针的误差(约 0.05 N·m)是四者中最低的,其余三者都在 0.2 N·m 以上:只有 16 个点时,训练上千个参数反而把噪声也学了进去。
    • 选“新的效应”、\(N=128\),训练到 1000 步:全量微调和 LoRA 的误差都不到线性探针的一半(约 0.03 对 0.15 N·m),而 LoRA 训练的参数只有全量微调的十分之一。

    几个值得注意的地方。(1) 线性探针只有 7 个参数,对家族内的任务它几乎不可能过拟合;但在“新的效应”下,无论给多少数据,它都停在约 0.15 N·m:这是偏差,冻结的特征表达不了弹簧的折角(16.2 节的偏差–方差)。(2) 全量微调和 LoRA 在“同一家族”、\(N=16\) 时比它们出发时的探针更差:看右上的红线和绿线:它们从探针的误差出发,随着训练把噪声也拟合进去,误差一路升高(全量微调在第 200 步约 0.11,到 1000 步约 0.21)。这是微调最常见的失败方式,对策是早停、更小的学习率或者干脆只做探针。(3) 在“新的效应”下,默认的 \(N=64\) 里从零训练(约 0.07 N·m)已经比探针好,但仍不如两种微调(约 0.05 N·m):预训练学到的重力和波动形状,从零训练要用更多数据才能自己找到。

    要多少数据?

    一次训练的结果受随机性影响,下面把 \(N\) 从 8 扫到 256,每个 \(N\) 用 3 组不同的数据和初始化各训练 1000 步,画出测试误差的几何平均。对数–对数坐标下,曲线之间的水平距离就是“省了多少倍的数据”。

    FIG 3数据效率:测试误差随演示数 \(N\) 的变化
    横轴:测量点数 \(N\)(对数);纵轴:测试误差(N·m,对数)。实心点和连线是 3 次训练的几何平均,小点是单次结果;颜色同 FIG 2:从零(紫)、线性探针(蓝)、全量微调(红)、LoRA \(r=2\)(绿)。虚线是测量噪声的标准差 0.05 N·m。每个目标的扫描要在浏览器里训练 54 个模型,大约需要 15 到 25 秒;滚出屏幕时会暂停。
    • 分别为“同一家族”和“新的效应”跑完扫描。同一家族:线性探针在 \(N\le128\) 的每个 \(N\) 上都最低,到 \(N=256\) 时才和 LoRA 打平(LoRA 略低一点)。新的效应:\(N\le16\) 时探针最低,\(N\ge64\) 时全量微调和 LoRA 最低,两条曲线在中间交叉。
    核心洞见

    选哪种适配方法,取决于两件事:新任务离预训练分布有多远,以及你有多少数据。离得近、数据少:冻结主干、只训练头。离得远、数据多:改动主干。LoRA 在两者之间:它能改动主干,可改动被限制在一个低维的子空间里。在我们的玩具里(新的效应),从零训练到 256 个点仍停在约 0.06 N·m,比两种微调(约 0.02 N·m)差三倍;在真实的机器人上,输入是图像和语言,“家族”的结构复杂得多,这个差距要大得多。

    4另一个视角:学会新的,会忘掉旧的吗?

    一个基础模型的价值在于它会很多东西。在新机器人上微调之后,那 32 台老机器人它还能用吗?我们保留每台老机器人原来的头不动,把它们接在微调后的主干上,再测一次误差(下文称“旧机器人误差”)。预训练模型本身的旧机器人误差约 0.014 N·m。如果微调把它大幅抬高,就叫灾难性遗忘(catastrophic forgetting,McCloskey 与 Cohen 1989):神经网络的知识分布在所有共享的权重里,为新任务改动这些权重,就会顺带改动旧任务的答案。

    三种常见的对策:(1) 回放(rehearsal / replay):微调时混入一部分旧数据,损失变成 \(L+\hl{replay}{\beta}\,L_0\)(\(L\) 是新任务的损失,\(L_0\) 是旧任务的损失);机器人领域常说的“联合微调”(co-fine-tuning,RT-2 用网络数据和机器人数据一起微调)就是这一类。(2) 把参数拉回预训练值:加正则项 \(\hl{l2sp}{\lambda}\|\boldsymbol\theta-\boldsymbol\theta_0\|^2\)(L2-SP,Li 等 2018);EWC(Kirkpatrick 等 2017)是它的加权版本,对旧任务越重要的参数拉得越紧。(3) 不动原始权重:LoRA 和各种适配器把改动放在额外的参数里,随时可以拿掉。

    FIG 4灾难性遗忘:新机器人误差与旧机器人误差的取舍
    任务固定为“新的效应”、\(N=64\)。左:一台老机器人的真实曲线(虚线)和四个模型用它原来的头给出的预测:全量微调(红)、全量微调 + L2-SP(琥珀)、全量微调 + 回放(青)、LoRA \(r=2\)(绿);“下一台”换一台老机器人看。右上:取舍平面,横轴是新机器人的测试误差,纵轴是 32 台老机器人的平均误差(都取对数);每条线是一个模型在训练中走过的路径,实心点是它现在的位置。用 LP-FT 时,所有路径都从蓝色空心圈出发:线性探针的解(主干未动,所以旧机器人误差就是预训练值)。
    • 按默认设置训练到 1000 步:普通全量微调把旧机器人误差从 0.014 抬到 0.14 N·m 以上(十倍多),LoRA 也差不多:合并进去的低秩改动同样会改变旧机器人的答案。
    • 调大回放权重 \(\beta\)(每次改动会重新开始训练),找一个值,使训练 1000 步后青色模型的旧机器人误差低于 0.04 N·m,同时新机器人误差低于 0.1 N·m(仍明显好于探针的约 0.16)。
    • 把新头的初始化从“线性探针(LP-FT)”切到“随机”,训练到 1000 步:普通全量微调的旧机器人误差超过 0.5 N·m,是 LP-FT 时的四倍左右。

    LP-FT 的道理(Kumar 等 2022):随机初始化的头一开始给出的是错得离谱的预测,它产生的大梯度会一路传回主干,在头学好之前就把预训练特征扭曲了;先用线性探针把头放到合理的位置,再一起微调,主干只需要做小的修正。在 FIG 4 里,这一个开关就让遗忘差了约四倍,而新机器人误差几乎不变(约 0.05 N·m)。

    回放在这个玩具里比 L2-SP 划算:L2-SP 把所有参数一视同仁地往回拉,要压住遗忘就得把新任务也一起压住(\(\lambda=1\) 时旧机器人误差约 0.04,新机器人误差却退到约 0.12);回放直接告诉网络“这些答案不许变”,网络会把改动放到旧任务不在乎的方向上。代价是你得一直保留、并且能用到旧数据。最后,把 LoRA 适配器“关掉”试试:旧机器人误差立刻回到 0.014,因为原始权重一个都没动。一个基础模型加上很多个可插拔的小适配器(每台机器人、每个任务一个),是 LoRA 在部署上最实际的好处。

    5LoRA 近看:微调的改动本来就是低秩的

    LoRA(Hu 等 2021)基于一个经验观察:预训练模型在下游任务上需要的改动,其“内在维度”很低(Aghajanyan 等 2021 在语言模型上测过:在一个随机的低维子空间里优化几百到几千个参数,就能达到全量微调的大部分效果)。那就直接把权重矩阵的改动限制成低秩:

    $$ \mathbf h'=W_0\mathbf h+\hl{dW}{\Delta W}\,\mathbf h,\qquad \hl{dW}{\Delta W}=\frac{\alpha}{r}\,\hl{B}{B}\,\hl{A}{A},\qquad B\in\mathbb R^{d\times r},\;A\in\mathbb R^{r\times k},\;r\ll\min(d,k) $$

    训练的参数从 \(dk\) 个降到 \(r(d+k)\) 个。下面的图先用全量微调在“新的效应”、\(N=128\) 上训练 1000 步,把第二个隐藏层的改动 \(\Delta W=W-W_0\) 拿出来做 1.12 节的 SVD:如果它的奇异值 \(\hl{sigma}{\sigma_i}\) 很快衰减,那么一个低秩矩阵就能代替它。同时训练一个 \(r=2\) 的 LoRA,看它的 \(\Delta W\) 长什么样。

    FIG 5权重改动 \(\Delta W\) 的奇异值:秩为 \(r\) 的截断够不够用
    左:三个 32×32 矩阵的热图,红 = 正,蓝 = 负,颜色越浓绝对值越大:预训练权重 \(W_0\)(单独的色标)、所选来源的改动 \(\Delta W\)、以及它的秩 \(r\) 截断 \(\Delta W_r\)(后两者共用色标)。右上:\(\Delta W\) 的奇异值(对数纵轴),前 \(r\) 个(保留的)为绿色,其余为灰色线框。三种来源:全量微调后的 \(\Delta W\);\(r=2\) 的 LoRA 学到的 \(\frac{\alpha}{r}BA\);以及只用 4 个样本算出的一次梯度 \(\partial L/\partial W\)。读数给出前 \(r\) 个奇异值占 \(\|\Delta W\|_F^2\) 的比例,以及把全量微调模型的这一层改动换成 \(\Delta W_r\)(其他层保持微调后的值)后的测试误差。
    • 点“微调”,来源选“全量微调”,然后找出让前 \(r\) 个奇异值占到 \(\|\Delta W\|_F^2\) 的 90% 以上的最小 \(r\)(32 个奇异值里只要 3 个),再看读数:换成这个 \(\Delta W_r\) 后的测试误差几乎等于完整的微调。
    • 把来源切到“一次梯度(4 个样本)”:恰好只有 4 个奇异值不为零,其余小到 \(10^{-10}\) 以下。

    第二个任务背后是一条简单而重要的事实:对一个样本,线性层 \(\mathbf z=W\mathbf h\) 的梯度是外积 \(\partial L/\partial W=\boldsymbol\delta\,\mathbf h^\top\)(16.3 节),秩为 1;一个批次 \(n\) 个样本的梯度是 \(n\) 个外积之和,秩不超过 \(n\)。微调的数据少、步数少、而且每步的梯度方向高度相关,累积起来的改动自然集中在少数几个方向上。LoRA 的 \(B\) 和 \(A\) 就是让优化器直接去找这几个方向。

    LoRA 还有一个好处:训练完可以合并,\(W=W_0+\frac{\alpha}{r}BA\) 只是一个同样大小的矩阵,推理时的计算量和延迟与原模型完全相同(读数里的“合并误差”是合并前后输出的最大差,只剩浮点舍入)。想换任务时减去 \(\frac{\alpha}{r}BA\)、加上另一个即可。

    6再省一点:把冻结的底座量化(QLoRA)

    LoRA 让需要训练的参数少了几百倍,但冻结的底座仍然要整个放进显存:70 亿参数用 16 位存就是 14 GB。全量微调更贵:混合精度的 Adam 每个参数要存 16 字节(16 位权重和梯度各 2 字节,32 位的权重主副本 4 字节,Adam 的两个矩估计 8 字节,ZeRO 论文的估算),70 亿参数就是 112 GB,还没算激活值。QLoRA(Dettmers 等 2023)把冻结的底座量化成 4 位,LoRA 的参数仍用 16 位训练,梯度穿过反量化后的权重传给 \(B\) 和 \(A\)。

    最简单的量化是分块 absmax:把权重分成小块,每块记下最大绝对值 \(c\),再把 \(w/c\in[-1,1]\) 四舍五入到 \(2^{b}-1\) 个等距的格点之一,只存格点编号(\(b\) 位)和每块一个 \(c\)。下面对我们的预训练网络这样做(每块是权重矩阵的一行,第一层则是一列;大多数块有 32 个数),看量化让老机器人的误差变大了多少,再在量化后的底座上训练 LoRA。

    $$ c=\max_{j\in\mathcal B}|w_j|,\qquad \hl{quant}{\hat w_j=\frac{c}{m}\,\operatorname{round}\!\Big(\frac{m\,w_j}{c}\Big)},\quad m=2^{b-1}-1,\qquad |\hat w_j-w_j|\le\frac{c}{2m} $$
    FIG 6量化底座 + LoRA,以及微调一个大模型要多少显存
    左上:预训练网络所有权重除以各自块的 absmax 之后的直方图(青色),琥珀色竖线是 \(b\) 位的量化格点,每个权重被移到最近的那条线上。左下:一台老机器人的真实曲线(虚线)、全精度模型(蓝)与量化模型(红)的预测。右上:微调一个大模型所需的显存(只算权重、梯度和优化器状态,不算激活值):全量微调、LoRA(16 位底座)、QLoRA(4 位底座);虚线是 24 GB、48 GB 和 80 GB 三种常见显卡的容量。LoRA 的可训练参数按模型的 0.6% 估算(大约是在 7B 级模型的每个线性层上用秩 16),每个可训练参数按 16 字节计;QLoRA 的底座每参数 0.5 字节,另加约 0.016 字节的分块常数(双重量化之后)。
    • 把底座量化到 2 位(每个权重只剩 −c、0、+c 三个值):老机器人的误差涨到 0.6 N·m 以上,几十倍。然后点“在这个底座上训练 LoRA”:新机器人的误差仍能降到 0.04 N·m 以下,和 16 位底座上的 LoRA(约 0.03)相差不多。
    • 把模型大小拖到 65B:全量微调要一千多 GB,16 位底座的 LoRA 也要一百多 GB,只有 QLoRA(约 40 GB)放得进一张 48 GB 的显卡。这正是 QLoRA 论文的标志性结果。

    注意两个现象。第一,在 2 位底座上,LoRA 训练开始时的误差(约 0.20 N·m)比 16 位底座(约 0.15)差,但训练会把量化误差和新任务一起“修”掉:低秩增量加一个新头,足够补偿量化带来的那部分偏差。QLoRA 论文报告,用 4 位底座 + LoRA 微调,能达到 16 位全量微调的效果。第二,我们这个只有 1357 个参数的小网络对量化非常敏感(4 位时老机器人误差约 0.1 N·m,是全精度的 7 倍);大模型的权重多、冗余大,对 4 位量化宽容得多。QLoRA 的 4 位格点也不是等距的,而是按正态分布的分位数放置(NF4),因为预训练权重大致服从零均值正态分布,靠近 0 的地方格点更密;它还把每块 64 个权重的常数 \(c\) 再量化一次(双重量化),并用分页优化器应对显存峰值。

    7再看数学

    四个优化问题

    记预训练得到的主干参数为 \(\boldsymbol\psi_0\),新任务数据为 \(\{(x_i,y_i)\}_{i=1}^N\),新头为 \(\mathbf w\),模型 \(\hat y=\mathbf w^\top\boldsymbol\phi_{\boldsymbol\psi}(x)\)。四种做法只是“哪些变量可以动、从哪里出发”不同:

    $$ \hl{lp}{\mathbf w^\star=\arg\min_{\mathbf w}\;L(\mathbf w,\boldsymbol\psi_0)+\lambda\|\mathbf w\|^2=(\Phi^\top\Phi+\lambda I)^{-1}\Phi^\top\mathbf y} $$ $$ \hl{ft}{\min_{\mathbf w,\boldsymbol\psi}\;L(\mathbf w,\boldsymbol\psi)},\qquad (\mathbf w,\boldsymbol\psi)\big|_{t=0}=(\mathbf w^\star,\boldsymbol\psi_0) $$ $$ L(\mathbf w,\boldsymbol\psi)+\hl{l2sp}{\lambda\|\boldsymbol\psi-\boldsymbol\psi_0\|^2},\qquad L(\mathbf w,\boldsymbol\psi)+\tfrac{\lambda}{2}\textstyle\sum_i F_i(\psi_i-\psi_{0,i})^2,\qquad L(\mathbf w,\boldsymbol\psi)+\hl{replay}{\beta\,L_0(\boldsymbol\psi)} $$ $$ \hl{lora}{\min_{\mathbf w,B,A}\;L\big(\mathbf w,\;W_0+\tfrac{\alpha}{r}BA\big)},\qquad B\big|_{t=0}=0,\quad A_{ij}\big|_{t=0}\sim\mathcal N(0,\sigma^2) $$

    四行依次是:线性探针(LP);全量微调,从探针的解出发(LP-FT);加在全量微调上的三种防遗忘项,L2-SP、EWC 和回放;LoRA。线性探针里 \(\Phi\) 的第 \(i\) 行是 \(\boldsymbol\phi_{\boldsymbol\psi_0}(x_i)^\top\)(末尾补一个 1 作偏置),这就是 1.13 节的正规方程加岭项(FIG 1 和 FIG 2 用 \(\lambda=0.01\),偏置不受惩罚)。第三行的中间一项是 EWC:\(F_i\) 是旧任务上 Fisher 信息矩阵的对角元,粗略地说是“损失对第 \(i\) 个参数有多敏感”,所以 EWC 是“按重要性加权的 L2-SP”。回放项 \(L_0\) 在 FIG 4 里是 32 台老机器人通过各自冻结的头的均方误差,每步随机取 16 个角度。悬停这些公式,FIG 2 和 FIG 4 里对应的曲线会加粗。

    LoRA 的梯度与初始化

    令 \(G=\partial L/\partial W\) 为合并后权重 \(W=W_0+sBA\)(\(s=\alpha/r\))上的普通梯度,也就是全量微调会用到的那个梯度。由链式法则:

    $$ \frac{\partial L}{\partial \hl{B}{B}}=s\,G\,A^\top,\qquad \frac{\partial L}{\partial \hl{A}{A}}=s\,B^\top G,\qquad G=\sum_{n\in\mathcal B}\boldsymbol\delta_n\mathbf h_n^\top\;\;\Rightarrow\;\;\operatorname{rank}G\le|\mathcal B| $$

    页面的代码正是这样做的:用 nn.js 在合并后的网络上反传得到 \(G\),再乘上 \(A^\top\) 或 \(B^\top\)。从这两个式子能读出初始化的讲究:如果 \(A\) 和 \(B\) 都从零开始,两个梯度都是零,永远动不了;如果都随机,训练一开始模型就被一个随机的 \(sBA\) 扰乱了。所以 LoRA 让 \(B=0\)、\(A\) 随机:起点就是预训练模型,而 \(\partial L/\partial B=sGA^\top\neq0\),第一步就能动起来。缩放 \(s=\alpha/r\) 让“改变秩”和“改变学习率”大致解耦:\(r\) 变大时每一列的贡献按 \(1/r\) 缩小,LoRA 论文因此把 \(\alpha\) 固定为第一个尝试的 \(r\),之后不再调它(我们取 \(\alpha=2r\))。

    参数个数。一个 \(d\times k\) 的矩阵:全量 \(dk\),LoRA \(r(d+k)\)。\(d=k=4096\)、\(r=8\) 时是 65,536 对 16,777,216,约 0.39%。我们的玩具:全量微调 1357 个参数(\(2\cdot32+32\) + \(32\cdot32+32\) + \(32\cdot6+6\) + 新头 7),LoRA \(r=2\) 是 \(2\cdot2\cdot32=128\) 加新头 7,共 135 个。

    适配器(adapter,Houlsby 等 2019)是更早的做法:在每个 Transformer 子层后面插入一个小瓶颈 \(\mathbf h\leftarrow\mathbf h+W_{\uparrow}\,\sigma(W_{\downarrow}\mathbf h)\),\(W_{\downarrow}\in\mathbb R^{m\times d}\),\(m\ll d\),只训练这些小矩阵。参数同样很少,但中间有非线性 \(\sigma\),没法并进原权重,推理时多出串行的计算。提示微调 / 前缀微调则只学几个附加在输入序列(或每层键值)前面的向量,参数更少,表达力也更弱。

    低秩截断为什么是最优的

    FIG 5 的 \(\Delta W_r\) 用的是 SVD 截断 \(\Delta W_r=\sum_{i\le r}\sigma_i\mathbf u_i\mathbf v_i^\top\)。Eckart–Young 定理(1.12 节)说它是所有秩不超过 \(r\) 的矩阵里离 \(\Delta W\) 最近的(Frobenius 范数下),误差恰好是 \(\|\Delta W-\Delta W_r\|_F^2=\sum_{i>r}\sigma_i^2\),读数里的能量比例就是 \(\sum_{i\le r}\sigma_i^2/\sum_i\sigma_i^2\)。LoRA 并不先算全量微调再截断,而是直接在秩 \(r\) 的矩阵里优化,学到的 \(\Delta W\) 也不必等于全量微调的截断:FIG 5 里 LoRA 的 \(BA\) 和全量微调的 \(\Delta W\) 长得并不一样,测试误差却差不多,因为能把新任务做好的改动不止一个。

    一句话总结

    预训练给出一个好的起点和一组好的特征;线性探针只在特征上做最小二乘,便宜、稳,但有偏差;全量微调什么都能改,但费数据、费显存、会遗忘;LoRA 把改动限制在 \(W_0+\frac{\alpha}{r}BA\) 这样的低秩子空间里,用很少的参数拿到全量微调的大部分效果,可合并、可拔插,再配上量化的底座(QLoRA)就能在一张显卡上微调大模型。

    8机器人中的它:用几百条演示微调一个基础模型

    机器人学习里的预训练大致经历了三个阶段。冻结的视觉编码器:在 ImageNet、人类视频(R3M)或大规模图像上自监督(MVP、VC-1)预训练一个编码器,冻结后在它的特征上训练策略,就是 18.3 节和 18.4 节讲过的“线性探针”思路的延伸。从视觉-语言模型出发:RT-2(Brohan 等 2023)把动作写成文本 token(17.5 节),在大规模视觉-语言模型上用机器人数据微调;它采用联合微调,把原来的网络视觉问答数据和机器人轨迹混在一起训练,正是 FIG 4 的回放,目的是不忘掉从网络上学到的物体和概念。在跨本体机器人数据上预训练的通用策略:Octo(Octo Model Team 2024)在 Open X-Embodiment 的 80 万条轨迹上预训练,论文报告能在普通的消费级显卡上用几个小时把它微调到新的传感器输入和动作空间;OpenVLA(Kim 等 2024)是一个 70 亿参数的 VLA,在 97 万条真实机器人演示上训练。

    OpenVLA 的论文给出了一组很能说明问题的数字。在每个任务只有 10 到 150 条演示的 Franka 机械臂任务上,全量微调需要 8 张 A100 每个任务训练 5 到 15 小时;LoRA(秩 32)只训练 1.4% 的参数,平均成功率 68.2%,与全量微调的 69.7% 相当,只用一张 A100 训练 10 到 15 小时;作者还发现秩的大小对成功率影响很小。部署时,4 位量化推理的成功率与 16 位推理相当,显存不到一半(8 位量化反而变差,作者归因于推理速度变慢)。π0(Black 等 2024)则沿用了语言模型“预训练 + 后训练”的说法:先在大量多机器人数据上预训练,再用精心筛选的高质量数据把它微调到叠衣服这类复杂的灵巧任务上。

    真实系统里

    先对齐接口,再谈微调:新机器人的相机视角、动作空间(关节位置还是末端位姿,绝对量还是增量)、控制频率和动作归一化的统计量,都要和预训练时的约定一致,或者明确地为它们换一个新的输入/输出头(Octo 就是这样适配新动作空间的)。对不上的接口比任何微调方法的差别都大。 数据少时先试最便宜的:冻结编码器 + 小策略头,或 LoRA;把一部分演示留作验证集,按验证成功率或损失早停(FIG 2 里过拟合的红线和绿线)。 别只看新任务:如果模型还要做原来的任务,微调后要在原来的任务上重新测;需要保留语言理解或旧技能时,混入原始数据联合微调。 一个底座,多个适配器:每台机器人、每个任务一个 LoRA,按需加载,原始权重不变。

    9常见误区

    误区 1:微调一定比冻结好

    数据少、任务又在预训练分布之内时,全量微调和 LoRA 都可能比它们出发时的线性探针还差:FIG 2 的“同一家族”、\(N=16\) 里,探针约 0.05 N·m,两种微调从探针的解出发,1000 步后却都超过 0.2 N·m,训练越久越差。没有验证集、按固定步数训练,是这种退化最常见的原因。

    误区 2:新头随便初始化,学习率照搬预训练

    随机的新头在前几百步产生大而无意义的梯度,会把预训练特征冲掉(FIG 4 里随机头让遗忘大了约四倍)。先做线性探针再微调(LP-FT),或者先冻结主干训练几百步头再解冻;微调的学习率通常比预训练小一个数量级左右,有时还对靠近输入的层用更小的学习率(ULMFiT 的分层学习率)。

    误区 3:以为 LoRA 天生不会遗忘

    LoRA 的改动一旦合并、并且模型用于旧任务,它和全量微调一样会改变旧答案:FIG 4 里 LoRA 的旧机器人误差(约 0.17 N·m)和全量微调(约 0.18 N·m)差不多。秩小一些通常改得少一些、忘得也少一些(Biderman 等 2024 的标题就是“LoRA 学得少,忘得也少”),但这不是保证。真正不会遗忘的,是把适配器拿掉、换回原始权重。

    误区 4:只改秩,不管 \(\alpha\) 和学习率

    增量是 \(\frac{\alpha}{r}BA\),同一个学习率下,改 \(r\) 或改 \(\alpha\) 都会改变每一步的实际步长。比较不同的秩时要说清 \(\alpha\) 怎么取(固定 \(\alpha\) 还是固定 \(\alpha/r\)),否则看到的可能只是学习率的差别。另外,只在部分矩阵上加 LoRA(原论文主要用在注意力的 \(W_Q\)、\(W_V\) 上)和在所有线性层上加,效果和参数量都不同。

    误区 5:把“参数少”当成“显存少”和“算得快”

    LoRA 省的是梯度和优化器状态,冻结的底座仍要整个放进显存(16 位 70 亿参数就是 14 GB),前向和反向的计算量也几乎没少,因为梯度仍要穿过整个网络;激活值的显存随批次和序列长度增长,FIG 6 的估算没算它。要再省就得量化底座(QLoRA)、用梯度检查点、或减小批次。

    10小练习

    1. 给一个 4096×4096 的权重矩阵加秩 \(r=8\) 的 LoRA,需要训练多少个参数?
    \(B\) 是 4096×8,\(A\) 是 8×4096,合计 \(r(d+k)=8\times8192=65{,}536\),约为整个矩阵(选项 D,\(4096^2\))的 0.39%。选项 A 只算了 \(B\) 或 \(A\) 中的一个。
    2. 如果把 LoRA 的 \(A\) 和 \(B\) 都初始化为零,会怎样?
    \(\partial L/\partial B=sGA^\top\)、\(\partial L/\partial A=sB^\top G\):\(A=0\) 使前者为零,\(B=0\) 使后者为零,这是一个梯度恒为零的驻点。所以 LoRA 只让 \(B=0\),\(A\) 随机。选项 D 是两者都随机初始化的后果。
    3. 新机器人和预训练用的机器人属于同一家族,你只有 16 个测量点。FIG 2 和 FIG 3 建议用哪种方法?
    家族内的任务能被冻结特征表达,探针只有 7 个参数,16 个点就把它确定得很好(约 0.05 N·m);全量微调和 LoRA 有上百到上千个参数,长时间训练会拟合噪声(1000 步后都超过 0.2 N·m);从零训练在这么少的数据下最差。
    4. LoRA 训练完、把 \(\frac{\alpha}{r}BA\) 合并进 \(W_0\) 之后,推理的计算量和原模型相比如何?
    \(W=W_0+\frac{\alpha}{r}BA\) 与 \(W_0\) 形状相同,前向计算没有任何变化(FIG 5 的合并误差只是浮点舍入)。选项 A 是不合并时的做法(方便切换适配器),选项 B 描述的是 Houlsby 式适配器,它因为中间有非线性而无法合并。
    5. 一个线性层在一个 4 样本批次上的梯度 \(\partial L/\partial W\)(32×32)的秩最多是多少?为什么?
    每个样本贡献一个秩 1 的外积(误差信号乘以输入),4 个秩 1 矩阵之和的秩不超过 4,FIG 5 的“一次梯度”正好有 4 个非零奇异值。选项 C 只对单个样本成立。这条事实是“微调改动低秩”的一个直观来源。

    11延伸阅读

    • M. McCloskey & N. J. Cohen, Catastrophic Interference in Connectionist Networks: The Sequential Learning Problem, Psychology of Learning and Motivation, 1989 — 灾难性遗忘的经典描述
    • J. Yosinski, J. Clune, Y. Bengio & H. Lipson, How Transferable Are Features in Deep Neural Networks?, NeurIPS 2014 — 逐层测量特征的可迁移性
    • J. Howard & S. Ruder, Universal Language Model Fine-tuning for Text Classification, ACL 2018 — ULMFiT:分层学习率与逐步解冻
    • X. Li, Y. Grandvalet & F. Davoine, Explicit Inductive Bias for Transfer Learning with Convolutional Networks, ICML 2018 — L2-SP:把参数拉回预训练值
    • J. Kirkpatrick et al., Overcoming Catastrophic Forgetting in Neural Networks, PNAS 2017 — EWC:按 Fisher 信息加权的正则
    • N. Houlsby et al., Parameter-Efficient Transfer Learning for NLP, ICML 2019 — 瓶颈适配器
    • A. Aghajanyan, S. Gupta & L. Zettlemoyer, Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning, ACL 2021 — 微调的内在维度很低
    • E. J. Hu et al., LoRA: Low-Rank Adaptation of Large Language Models, ICLR 2022 — 低秩增量 \(\Delta W=BA\)、零初始化的 \(B\)、合并推理
    • A. Kumar, A. Raghunathan, R. Jones, T. Ma & P. Liang, Fine-Tuning can Distort Pretrained Features and Underperform Out-of-Distribution, ICLR 2022 — LP-FT:先探针、后微调
    • T. Dettmers, A. Pagnoni, A. Holtzman & L. Zettlemoyer, QLoRA: Efficient Finetuning of Quantized LLMs, NeurIPS 2023 — NF4、双重量化、分页优化器
    • D. Biderman et al., LoRA Learns Less and Forgets Less, TMLR 2024 — LoRA 与全量微调在学习与遗忘上的系统比较
    • S. Rajbhandari, J. Rasley, O. Ruwase & Y. He, ZeRO: Memory Optimizations Toward Training Trillion Parameter Models, SC 2020 — 混合精度 Adam 每参数 16 字节的显存分析
    • A. Brohan et al., RT-2: Vision-Language-Action Models Transfer Web Knowledge to Robotic Control, CoRL 2023 — 在视觉-语言模型上联合微调机器人动作
    • Octo Model Team, Octo: An Open-Source Generalist Robot Policy, RSS 2024 — 在 Open X-Embodiment 上预训练、可微调到新机器人的通用策略
    • M. J. Kim et al., OpenVLA: An Open-Source Vision-Language-Action Model, CoRL 2024 — 7B VLA,LoRA 微调与量化部署