一个模型在旧任务上准确率 0.9450,在陌生任务上是 0.0000。 只在陌生任务上接着训 400 步, 它涨到 0.7378——代价是旧任务从 0.9450 掉到 0.0800。 把两批数据混起来一起训, 旧任务回到 0.9183、新任务还有 0.7000。这就是灾难性遗忘,也是微调最需要防的一件事。
前四章讲的都是数据:怎么标、怎么查、怎么导出。 从这一节开始动模型本身——微调就是用这批数据去改已有模型的参数。
一、微调改的是参数,不是提示词
提示词工程在输入端做文章,模型参数一个都不动。你写一句「请用客服的语气回答」, 模型每次都要现场按这句要求调整输出,关掉对话就忘了。 微调是把已有权重当成起点,用你的数据继续做梯度下降。训完之后, 那个「客服语气」被写进了几百万个参数里,下次不写提示词它也照做。 所以两者的成本结构完全不同:提示词每次调用都要付 token,微调是一次性付训练费、 之后每次只付问题的钱。这一点在下一节会用具体数字算给你看。 微调真正擅长的是三件事:统一格式(每条回答都带固定的字段)、 统一口吻(不用每次提醒它别用「亲」)、统一判断口径(什么算「可退」、什么算「需转人工」)。 这三件都是「说法的分布」,不是「知识的集合」。 反过来,微调不擅长的是「记住一批会变的事实」。 今天把公司制度训进去,下个月制度改了,你得重新标一遍、重新训一遍。 这类需求属于知识库,不属于微调。
二、灾难性遗忘:新本领是踩着旧本领上位的
Demo 造了两个任务。 任务 A 是平面上四个角附近的四类点,任务 B 是另一块区域的三个类——模型从来没见过 B。 先用 A 训 400 步(模拟预训练),再用 B 接着训 400 步(模拟直接微调),最后把 A 和 B 混在一起训。 三份权重在三份测试集上打分:
| 阶段 | 任务 A(旧本领) | 任务 B(新本领) |
|---|---|---|
| 预训练后 | 0.9450 | 0.0000 |
| 只在 B 上微调 | 0.0800 | 0.7378 |
| A+B 混合训练 | 0.9183 | 0.7000 |
| 看第二行: | ||
| B 从 0 涨到 0.7378,A 从 0.9450 掉到 0.0800。这不是「学新的忘了旧的」这么轻描淡写—— | ||
| 0.0800 在四分类里比瞎猜(0.25)还差,说明旧任务的分界面被彻底改写了。 | ||
| 为什么会这样?因为梯度下降只认当前这批数据的损失。 | ||
| 它不知道「昨天那批数据也很重要」,所以它会把参数往「让 B 更准」的方向一路推, | ||
| 推到 A 的分界面翻过去为止。 | ||
| 第三行是解法:把 A 的数据混进来一起训,A 回到 0.9183、B 还有 0.7000。 | ||
| 注意 B 从 0.7378 降到 0.7000——两件事同时做,每一件都会稍微让一步。这就是「混合训练」的代价, | ||
| 也是它比「只训新数据」更可信的原因。 |
三、三条工程上的应对,按代价从低到高
① 混入旧数据。 最有效。 经验做法是新数据里掺 10% 到 30% 的旧数据,比例太低不管用、太高学不动新东西。 ② 调小学习率。 改得慢,遗忘也慢,但学得也慢。实战里它常和①一起用,很少单独用。 ③ 只训一部分参数。 冻结底层(语言能力),只改最后几层(任务头)。 遗忘最小,但能学的东西也最少,复杂任务会欠拟合。 有一个现实问题比技术问题更难: 上一批数据谁存着?很多团队的微调是「找业务部门要了一批对话记录就开训」,训完那批数据就散了。 等到第二次微调想起来要混旧数据,已经找不到了。 所以第一版微调上线时就要做一件事: 把训练数据按版本存档,和模型版本一一对应。 这份存档的成本几乎为零,但没有它, 第二次微调就只剩「从头再来」一条路。
四、微调能做什么、不能做什么
一句话分界:改的是「说法的分布」,微调行;改的是「知识的集合」,微调不行。 能做的:把回答固定成 JSON、把语气固定成「不用表情符号」、把「什么算紧急工单」的判断标准固定下来、 把行业术语的写法统一。 不能做的:让它记住昨天刚改的价格、让它引用一份 300 页的合同原文、 让它学会一个它预训练时完全没接触过的推理链。 还有一件常被忽略的事:微调之后模型会变「窄」。一个专门训来做退换货问答的模型,你问它写诗, 它会答得很差—— 这不是故障,这是你把它的能力收窄了。所以生产环境常见做法是「通用模型 + 微调模型」并存, 按意图路由,而不是拿一个微调模型干所有事。
五、动手 Demo:学新本领冲掉旧本领:0.9450 掉到 0.0800
造两个任务:A 是平面上四个角附近的四类点,B 是另一块区域的三个类。 先只用 A 训 400 步(模拟预训练),再只在 B 上接着训 400 步(模拟「拿新数据直接微调」), 最后 A 和 B 混在一起训 600 步。三份权重分别在 A、B 两份测试集上打准确率。
W0, b0 = train_soft(Xa, ya, K, ep=400, lr=0.6, seed=1) # 预训练
W1, b1 = W0.copy(), b0.copy() # 从预训练权重出发,不是从零
for _ in range(400): # 只在 B 上继续训
p = softmax(Xb @ W1 + b1)
g = (p - np.eye(K)[yb]) / len(yb)
W1 -= 0.6 * (Xb.T @ g)
b1 -= 0.6 * g.sum(0)
Xm = np.vstack([Xa, Xb]) # 把旧数据混回来
ym = np.concatenate([ya, yb])
W2, b2 = train_soft(Xm, ym, K, ep=600, lr=0.5, seed=3)
实跑输出:
--------------------------------------------------------------------
微调:学新本领会把旧本领冲掉,这叫灾难性遗忘
--------------------------------------------------------------------
阶段 任务 A(旧本领) 任务 B(新本领)
--------------------------------------------------
预训练后 0.9450 0.0000
只在 B 上微调 0.0800 0.7378
A+B 混合训练 0.9183 0.7000
看第二行:**B 从 0.0000 涨到 0.7378,代价是 A 从 0.9450 掉到 0.0800。**
这就是**灾难性遗忘**:参数被新任务推着走,原来那套分界面被彻底改写了。
第三行是解法:**把旧数据混进来一起训。**A 回到 0.9183、B 也有 0.7000。
代价是要保留旧数据——这在真实项目里往往是个组织问题,不是技术问题:**上一批数据谁存着?**
三条工程上的应对,按代价从低到高:
① 混入旧数据 最有效。新数据里掺 10% 到 30% 的旧数据
② 调小学习率 改得慢,遗忘也慢,但学得也慢
③ 只训一部分参数 冻结底层,只改最后几层,遗忘最小
三行输出就是这一节的全部证据。 第一行 0.9450/0.0000:模型在 A 上很准,在 B 上完全不会——因为 B 的三个类它从来没见过, 而输出层里那三个位置永远是低分。 第二行 0.0800/0.7378:只训 B 之后,B 学会了,A 塌了。 0.0800 这个数比随机猜(四分类是 0.25)还低,意思是它不仅忘了 A,还学到了反向的判断。 这不是数据造得极端。 真实场景里同样的事天天发生:拿客服对话微调一个通用模型,别的能力不一定会掉, 但你上一版微调学会的那个能力,会被这一版覆盖掉。 第三行 0.9183/0.7000 是混合训练的结果。A 基本恢复了,B 让了 0.0378。 这就是「混合」的本质:不是两全,是两边各让一点。 要说明一点:这里是分类任务,遗忘表现为「准确率掉」。 到了生成任务,遗忘的表现是「回答风格漂了」「原来会的格式不写了」,更难量化。 所以生成任务的微调,必须留一批旧任务的样例做回归测试。
30 秒实验
- 把第二步的学习率从 0.6 改成 0.1,看 A 掉到多少。这就是「调小学习率能减缓遗忘」的实测样子。
- 把混合训练里 A 的样本数乘 3(权重变大),看 A 能不能回到 0.94 以上、B 会掉多少。 旧数据的比例是可以调的旋钮。
- 把第二步的 400 步改成 100 步,看 A 掉多少。 步数少,遗忘也少——所以「先训少一点看看」是安全的第一版策略。
常见误区
- 「微调就是从零训一个新模型」。微调是从已有权重出发,只走一小段路; 从零训(预训练)是另一个量级的事,成本差几百倍。
- 「新数据越多越好,旧数据不用管」。旧数据不管,旧能力就被覆盖。 混合训练是必须项,不是优化项。
- 「微调完模型只会变强,不会变弱」。 它一定会变窄——专门做退换货的模型写诗会变差,这是设计,不是 bug。
自测三问(点开对答案)
1. 微调和提示词工程最本质的区别是什么? —— 提示词只改输入,参数一个不动,关掉对话就失效;微调改的是参数,能力被写进权重里。 2. 灾难性遗忘为什么比「学新的忘了旧的」更严重? —— 因为旧任务的准确率会掉到比随机猜还低——分界面被改写成反向的,不是简单地变模糊。 3. 混合训练为什么不能两全? —— 因为它用的是同一批参数容量。让新任务准一点,旧任务就要让一点,表现为一边涨一边微降。微调、知识库、长文本、预训练——这四个词经常被混着用。 下一节用成本把它们分开,并且算出一个「什么时候该换手段」的打平点。
- ☐ (本节完,下一节 5.1.2 微调与长文本、知识库、预训练的区别)