跳到主要内容

迁移学习、LoRA 与蒸馏

预训练模型带来的是从别的数据分布中学到的参数。复用它,可能比从头学习所有特征需要更少的任务样本;但旧表示也可能恰好丢掉了新任务需要的信息。选择方法前,先判断要改变的是输出分类头、内部表示,还是最终部署的模型本身。

先试冻结表示

假设一个文档路由器要选 keepsummarizediscard。冻结文本编码器,把文档映射成 hRdh\in\mathbb R^d,只训练输出层:

z=Wh+b,p=softmax(z).z=Wh+b,\qquad p=\operatorname{softmax}(z).

d=768d=768、类别数为 3,分类头只有 3×768+3=2,3073\times768+3=2{,}307 个参数。编码器完全冻结、预处理确定时,可以缓存向量,训练分类头不必反复运行编码器。这个基线能直接回答:现有表示是否已经把所需类别分开?

如果关键语句在输入截断时就被删掉,输出头无法凭空找回。如果表示把“已经保存”和“尚未保存”混在一起,只调分类边界也可能不够。先检查这些失败,再决定是否增加训练轮数。《动手学深度学习》的微调章节解释了复用特征与更新预训练参数的区别。

全量微调还会训练主干模型,自由度更大,也需要更多梯度、优化器内存,并可能覆盖已有能力。应在相同划分上比较冻结分类头、部分解冻和完整适配,不能仅凭可训练参数更多就认定更好。

LoRA 限制怎样更新参数

对线性层 WRdout×dinW\in\mathbb R^{d_{out}\times d_{in}}LoRA冻结原权重,学习一个低秩增量:

冻结的预训练权重与可训练的低秩矩阵 A、B 并行,两个分支的输出相加。查看清晰大图

输入 x 同时经过两条分支:蓝色权重保持冻结,橙色分支先经过秩为 r 的瓶颈,再回到输出维度。训练只更新 A 和 B;图中 B 的零初始化让新增分支在起点不改变原层输出。

W=W+sBA,ARr×din,BRdout×r.W'=W+sBA, \quad A\in\mathbb R^{r\times d_{in}}, \quad B\in\mathbb R^{d_{out}\times r}.

rr 是选定的秩,ss 是缩放系数。可训练矩阵元素从 dindoutd_{in}d_{out} 变为 r(din+dout)r(d_{in}+d_{out})。一个 4096×40964096\times4096 的层,秩取 8 时,需要训练 65,536 个元素,原矩阵则有 16,777,216 个,相差 256 倍。但总训练内存不会因此直接缩小 256 倍:底模权重、激活、适配哪些层以及其他可训练头仍然占内存。

用一个小矩阵就能看出秩的限制:

A=[11],B=[21],BA=[2211].A=\begin{bmatrix}1&-1\end{bmatrix},\qquad B=\begin{bmatrix}2\\1\end{bmatrix},\qquad BA=\begin{bmatrix}2&-2\\1&-1\end{bmatrix}.

s=1s=1,输入 (3,1)(3,1) 得到的输出修正为 (4,2)(4,2)。两个输出方向都由同一个输入差值控制。秩为一的增量无法表达任意 2×22\times2 矩阵变化。多层适配和非线性让完整网络比这个例子复杂,但秩仍是实际约束。

LoRA 改变权重的更新方式,不会把原架构变小。底模与数值表示、运行时兼容时,可以把适配增量合并到权重后推理;保留独立适配器则便于切换任务。适配器必须匹配底模检查点和 tokenizer,不能只因模型名字相近就混用。

蒸馏改变由谁学习

知识蒸馏让学生模型学习教师提供的信息。分类教师可以输出完整分布,而不是只给获胜标签。用温度 TT 平滑 logits:

pi(T)=exp(zi/T)jexp(zj/T).p_i^{(T)}=\frac{\exp(z_i/T)}{\sum_j\exp(z_j/T)}.

构造 logits (2,0,2)(2,0,-2)T=1T=1 时概率约为 (0.867,0.117,0.016)(0.867,0.117,0.016)T=2T=2 时约为 (0.665,0.245,0.090)(0.665,0.245,0.090)。较软的目标暴露了教师怎样排列次优选择。常见训练目标把硬标签损失与师生分布差异结合;温度、混合系数和取均值方式都会影响梯度尺度,应一起记录。

from math import exp

def softmax(logits, temperature):
shifted = [(v - max(logits)) / temperature for v in logits]
weights = [exp(v) for v in shifted]
total = sum(weights)
return [v / total for v in weights]

for temperature in (1.0, 2.0):
print([round(v, 3) for v in softmax([2, 0, -2], temperature)])

生成式教师也能产生示范或候选解释,但要针对任务筛选、检查。与教师一致,只能说明模仿得好;教师系统性标错,学生也会继承错误。最终应以独立标签或真实任务结果评价学生。

这些方法回答不同的问题

方法改变什么主要检查点
冻结编码器加分类头固定特征上的决策边界表示有没有保留所需信息
全量微调部分或全部主干权重新任务改善时旧能力是否退化
LoRA选定层中的低秩增量适配位置和秩是否足够
蒸馏学生行为,常使用更小架构压缩后独立任务质量是否保留

它们可以组合:教师提供样本,学生用 LoRA 学习。但 LoRA 不会证明学生更小,教师标签也不会因此正确。量化是另一个维度:量化改变数值表示,蒸馏改变学出来的模型,LoRA 限制更新方式。

怎样设计一次有效适配

同源样本共享信息时,应按原文档、用户或时间划分数据。先固定测试集,再生成改写;否则同一句话的变体可能跨越训练和测试,夸大成绩。用有标签的验证集选择秩、学习率、停止时机和类别阈值。

对文档路由器,除了每类召回率,还要测误删有用文档的代价、目标输入长度下的延迟,以及不确定样本的转交比例。与简单规则、冻结分类头比较,并放入否定、近似重复、新主题和类别比例变化的样本。这些情况才真正考验路由器要学的区别。

Agent traces 可以提供训练材料,前提是记录里的标签值得重复。历史上做过的动作不自动等于正确动作。先纠正反复出现的错误,再把记录变成监督数据;训练后还应在留出数据上校准决策概率

PEFT quicktour 把 LoRA 变成一个小练习:建立适配器配置,查看可训练参数量,再保存、重新加载适配器。对照保存的文件和加载时仍需要的基础模型,理解适配器 checkpoint 究竟包含什么。

探索关联打开关联网络