对应 Maps to:Stanford CS324 Winter 2023 Advances in Foundation Models,2/8 客座报告 Colin Raffel:Building ML Models like Open-Source Software。 依据说明:课程网站没有提供 slides 或录像。Raffel 在 2021 年 12 月发表过同题的博客 A Call to Build Models Like We Build Open-Source Software,2022–2023 年在多所大学做过同题报告,报告摘要列出的研究方向是:合并多个模型并保留各自的能力、用便宜的可传输更新给模型”打补丁”、模块化的架构、给模型参数做版本控制。本讲以这篇博客为主线,技术部分依据 Raffel 和合作者的论文:Matena & Raffel 2022(Fisher 加权合并)、Sung, Nair & Raffel 2021(固定稀疏掩码)、Yadav et al. 2023(TIES-Merging)、Kandpal et al. 2023(Git-Theta)、Don-Yehiya et al. 2023(ColD Fusion)、Borzunov et al. 2023(Petals),以及同一时期的相关工作 Ilharco et al. 2023(任务算术)、Wortsman et al. 2022(model soups)、Frankle et al. 2020 与 Ainsworth et al. 2023(线性模式连通性、Git Re-Basin)。报告具体讲了其中哪些,我无法确认;文献里的数字都是我在原文(或博客)里读到的;§9”2023 年之后”是我补充的。 配套代码 Code:
code/lecture13/(PyTorch;4 个脚本 + 1 个模块。代码 01 约 20 秒,02 约 90 秒,03 第一次约 60 秒、之后约 10 秒,04 约 100 秒) 预计阅读时间:3 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
学完这一讲,你应该能够:
- 说清 Raffel 的论点:今天的基础模型是”一次性、集中式、发布后冻结”的,开源软件则是”很多人持续地贡献、审查、合并”的;要让模型也这样开发,需要哪几样技术(增量更新、合并、版本控制、测试、模块化)。
- 定义任务向量 ,说出它的几个经验性质(短、几乎两两正交、能量集中),并会用任务算术做加法(多任务)和减法(去掉一种行为)。
- 比较几种合并方法——简单平均、任务算术、TIES、Fisher 加权平均——以及它们和多任务训练、集成的区别;解释干扰从哪里来、为什么任务越多越难合并。
- 用线性模式连通性和置换对称性解释:为什么从同一个预训练模型出发的微调可以平均,两个独立训练的模型却不行;以及为什么”补丁”只能打到它出发的那个版本上。
- 说出几种”便宜的补丁”(稀疏掩码、低秩、模块),以及”补丁小”和”不弄坏别的功能”为什么是两回事。
- 描述模型的版本控制(Git-Theta)、以下游评测为”测试”的持续集成、社区迭代改进(ColD Fusion)和协作推理(Petals),以及开放权重生态里的许可问题。
0.2 先修与本讲范围 Prerequisites & scope
| 默认你已经会 Assumed | 本讲只给直觉,后面几讲再展开 Previewed only |
|---|---|
| 第 6 讲 §3–4:全量微调、灾难性遗忘、LoRA 与”一个基座,很多插件” | 发布规范与分阶段发布(第 18 讲) |
| 第 6 讲 §6:模型编辑(改一个事实) | 许可、版权与监管(第 19 讲) |
| 第 9 讲 §7:去中心化训练 | |
| 第 10 讲 §4–5:OPT 的公开日志、BLOOM 的开放协作 | |
| 第 12 讲 §7:Pythia——开放的训练过程 |
0.3 本讲地图 Map
§1 模型怎样被"发布"、软件怎样被"开发":Raffel 的论点
§2 任务向量:把一次微调看成一个 diff ← 代码 01
§3 任务算术:加法、减法、类比 ← 代码 01
§4 合并的方法与干扰:平均、任务算术、TIES、Fisher ← 代码 02
§5 为什么只有"同一个起点"才行:线性模式连通性与置换对称性 ← 代码 03
§6 便宜的补丁:稀疏、低秩、模块 ← 代码 04
§7 版本控制、测试与社区协作 ← 代码 04
§8 开放权重的生态与许可
§9 2023 年之后:开放模型的爆发与合并实践
§10–14 小结、常见误区、练习、延伸阅读、下一讲预告
0.4 记号 Notation(只列本讲新增的,其余见第 1 讲 §0.4)
| 符号 | 含义 | 例子 |
|---|---|---|
| 预训练模型(base model)的全部参数,摊平成一个向量 | 第 1 讲 base model:109,056 维 | |
| 在任务 上微调之后的参数 | ||
| 任务 的任务向量(task vector) | ||
| 合并时的缩放系数 | ||
| 模型 的(对角)Fisher 信息:每个参数对任务 有多重要 | ||
| 归一化准确率 | 合并模型在任务 上的准确率 ÷ 专门模型的准确率,再对任务平均 | 1.0 = 一个模型顶 个 |
| 损失屏障(barrier) | 两个模型之间直线路径上,损失比两端连线高出的最大值 | 0 = 两者在同一个”盆地” |
0.5 关于数字 · About the numbers
讲义里的实验数字都来自 code/lecture13/ 的实际输出(固定种子、PyTorch 单线程,同一台机器上重复运行逐字相同;微调出的模型缓存在本目录的 checkpoints/,删掉后重新训练得到逐位相同的结果)。所有实验都从第 1 讲的 base model 出发,在 5 个小任务上微调:3 个”读评论”(verdict、food、service)、2 个”读两位数”(parity、tens)。我们的模型只有 11 万参数,而论文里的模型有上亿到上百亿参数——几处结果和论文不一样(最重要的:TIES 和 Fisher 合并没有赢过任务算术;稀疏补丁之间几乎不重叠,合并时照样干扰),完整清单在代码 README 的”关于实验结果”里。
1. 模型怎样被”发布”,软件怎样被”开发” · The argument
1.1 今天的模型:一次性、集中式、发布后冻结
回想前几讲的”配方”:在海量数据上预训练一个大模型,然后适配到下游任务(第 1、6 讲)。Raffel 的博客从这个配方的一个副作用说起:
- 预训练很贵,所以只有少数人能做。 博客引用 Lambda 的估计:训练 GPT-3 大约要 460 万美元。于是最常用的预训练模型几乎都出自大公司里的小团队,研究社区的大多数人只能”用”,不能”造”。
- 模型被大量使用。 博客提到 Hugging Face 上的 BERT 检查点被下载了数千万次——一个模型就是成千上万个应用的地基(第 1 讲的”同质化”)。
- 但模型发布之后几乎从不更新。 它们停在发布时的状态,直到被下一个模型取代。可是有很多理由需要更新:训练方法有了改进、发现了有问题的输出、发现模型记住了隐私数据(第 16 讲)、世界上的事实变了(第 6 讲 §6 的模型编辑)。而且没有一个标准的方法去做这些更新。
1.2 开源软件是怎样开发的
拿 Python 做对照。如果 Python 也是”一次性发布、之后冻结”,它不会有今天的大部分功能。开源软件靠的是一整套基础设施:
| 软件开发的做法 | 它解决了什么 |
|---|---|
| 版本控制:一串原子的补丁(commit),一个主仓库,少数维护者 | 每次修改都可以单独审查、回溯、撤销 |
| pull request + 自动测试 | 贡献者提出修改,测试通过、审查之后才合并 |
| 向后兼容 | 以前能用的代码,升级之后还能用 |
| 合并冲突 | 两个修改改了同一处时,需要(有时手动)解决 |
| 分叉(fork) | 无法调和的分歧可以分道扬镳(Debian 派生出了几十个发行版,包括 Ubuntu) |
| 语义化版本号(补丁版 / 次版本 / 主版本) | 一眼看出一次升级改动有多大 |
| 包与依赖管理 | 模块化地复用别人的组件 |
博客的核心主张:模型应该由一个大社区持续地更新和改进,为此要把上面这些想法移植到模型上。
1.3 一张对照表:如果模型是一个代码仓库
| 软件 | 模型(本讲的对应) | 难点 |
|---|---|---|
| 一个 commit / diff | 一次微调 = 一个任务向量 (§2) | 梯度下降每一步都改动全部参数,没有”只改了第 37 行”这回事 |
| 合并两个分支 | 合并两个微调模型(§3–4) | 两个补丁改了同一批参数时会干扰;神经网络里”不同的行”也通过前向传播连在一起(§6.4) |
| 补丁只能打到对应的版本上 | 任务向量只对它出发的那个 有意义(§5) | 两个独立训练的模型之间没有”行号”的对应 |
| 小补丁、便宜地传输 | 稀疏更新、低秩更新、模块(§6) | 补丁小 ≠ 不弄坏别的功能 |
| 自动测试 / CI | 下游任务的评测(§7.2) | 测试很贵:要微调、要跑几十个任务 |
| 语义化版本号 | 补丁版:只改一小部分参数;次版本:改架构但保留大部分参数;主版本:换一个新模型(§7.2) | |
| 社区持续贡献 | ColD Fusion、BigScience、Petals(§7.3–7.4) | 数据不能共享;算力分散 |
这张表是本讲的路线图。下面先从第一行开始:一次微调,能不能看成一个 diff?
1.4 讲者背景
Raffel 是 T5 论文(第 3 讲 §4.4)的第一作者,发表这篇博客时在北卡罗来纳大学(UNC)任助理教授。T5 本身就是一个”被很多人用、却由一个团队一次性训练出来”的典型;而他之后的工作——参与 BigScience(T0,第 7 讲 §2)、参数高效微调、模型合并、Git-Theta、Petals——都可以看成在为”像开源软件一样构建模型”补齐一块块基础设施。
2. 任务向量:把一次微调看成一个 diff · Task vectors
2.1 定义
Ilharco et al.(ICLR 2023)给出了最简单的定义:把预训练模型和微调后模型的全部参数各摊平成一个长向量,相减:
这就是”任务 的 diff”。有了它,“把补丁打上去”就是 ,“撤销”就是减回去——一切都是向量运算。问题在于:这种逐元素的加减有没有意义?神经网络是高度非线性的,参数空间里的”直线”不一定对应函数空间里有意义的东西。§2–§5 都在回答这个问题。
2.2 实验设置:5 个小任务
代码 01 在第 1 讲的 base model 上分别微调 5 个任务(每个 300 个训练样本,AdamW、学习率 1e-4、400 步,全部参数都训练):
| 任务 | 提示(例子) | 答案 | 组 |
|---|---|---|---|
| verdict | opinion: the soup was tasty but the host was rude. verdict: | good / ok / bad | 评论 |
| food | the rice tasted fresh, so i say | great / awful | 评论 |
| service | our waiter was rude. in short: | kind / rude | 评论 |
| parity | is 37 even or odd? it is | even / odd | 数字 |
| tens | how many tens are in 37? there are | 1 … 9 | 数字 |
两个设计细节:
- 答案都是语料里已有的词,只是格式没见过。我们的模型是字符级的,输入嵌入和输出层共享权重(第 3 讲 §3.8);如果答案是全新的词,每个任务都要大幅改动那几个字符的嵌入,任务之间冲突得一塌糊涂。写代码时我先用了新词(loved / yum),合并后的模型基本坏掉,才改成这样。
- 数字任务的测试集只用训练时没见过的 30 个两位数,测的是规则,不是背诵。
结果(测试集准确率;最后一列是第 1 讲验证集的 bit/字符,越低越好):
| 模型 | verdict | food | service | parity | tens | 验证集 bpc |
|---|---|---|---|---|---|---|
| base model | 0.847 | 0.463 | 0.517 | 0.410 | 0.147 | 0.409 |
| 微调 verdict | 1.000 | 0.450 | 0.660 | 0.410 | 0.177 | 0.420 |
| 微调 food | 0.807 | 1.000 | 0.480 | 0.410 | 0.093 | 0.460 |
| 微调 service | 0.400 | 0.360 | 1.000 | 0.410 | 0.093 | 0.470 |
| 微调 parity | 0.850 | 0.410 | 0.503 | 1.000 | 0.160 | 0.483 |
| 微调 tens | 0.647 | 0.437 | 0.573 | 0.590 | 0.817 | 0.518 |
每个模型都学会了自己的任务(tens 在没见过的数上是 0.817),别的任务大多停在 base model 附近——但也有副作用:微调 service 之后 verdict 从 0.847 掉到 0.400。每次微调都让原来的语言建模能力变差一点(0.409 → 0.420–0.518)。base model 在 verdict 上就有 0.847,因为 good / ok / bad 正是语料里 rating: 后面的词,只是格式换了(第 6 讲 §1.2 讲过”格式差异”)。
2.3 任务向量的几何
代码 01 演示 2 量了这 5 个任务向量:
它们很短。 只有 1.4%–3.2%。微调没有”重写”模型,只是在预训练的位置附近挪了一小步。这是任务算术能工作的前提:在一个点附近,函数近似是线性的(§3.4)。
它们几乎两两正交。 余弦相似度在 −0.018 到 +0.054 之间:
| verdict | food | service | parity | tens | |
|---|---|---|---|---|---|
| verdict | 1 | +0.054 | +0.052 | +0.029 | −0.018 |
| food | 1 | +0.052 | +0.010 | +0.012 | |
| service | 1 | +0.020 | +0.002 | ||
| parity | 1 | +0.001 |
两个 109,056 维的随机向量的余弦大约是 ±0.003(),所以这些余弦虽小,多数是”真的”。同组(评论 × 评论、数字 × 数字)的平均余弦 +0.040,跨组 +0.009——和 Ilharco et al. 在 CLIP 上看到的一样:MNIST、SVHN、GTSRB 这几个”认数字”的任务彼此最像,EuroSAT 和 RESISC45(都是卫星图)彼此最像。他们推测,正是因为不同任务的向量接近正交,相加时才互相干扰得不多。
为什么高维空间里的向量容易正交? 在 维空间里随便取两个方向,它们的余弦大约是 量级。一亿维的空间里,“几乎正交”是常态,不是巧合。真正有信息量的是偏离正交的程度——它反映了任务之间的相似性。
改动不是均匀分布的。 嵌入只占参数的 8.2%,却占了 的 20%–43%:字符级模型里,答案那几个字符的嵌入(同时也是输出层)被改得最多。MLP 占参数的 61%,占改动的 40%–60%。
能量很集中。 绝对值最大的 1% 的分量占 的 20%–41%,最大的 10% 占 49%–69%。但能力并不全在这些大分量里:
| 只保留最大的 k 比例 | k = 1% | 5% | 20% | 100% |
|---|---|---|---|---|
| verdict | 0.873 | 0.980 | 1.000 | 1.000 |
| food | 0.463 | 0.467 | 0.840 | 1.000 |
| service | 0.547 | 0.553 | 0.663 | 1.000 |
| parity | 0.410 | 0.410 | 0.827 | 1.000 |
| tens | 0.093 | 0.093 | 0.300 | 0.817 |
只留 20%,verdict 还是满分,其余掉到 0.30–0.84;只留 1%,基本退回 base model。这张表会在两个地方再用到:TIES-Merging 的”修剪”(§4.3),以及”稀疏补丁要在训练时就选好位置”(§6.1)。
3. 任务算术:加法、减法、类比 · Task arithmetic
Ilharco et al. 提出了三种运算,全都是 的形式, 在留出的开发集上选:
| 运算 | 想要的效果 | |
|---|---|---|
| 加法 | 一个模型同时会多个任务(不需要再训练) | |
| 取负 | 忘掉一个任务或一种行为,别的不受影响 | |
| 类比 | “A 之于 B 如 C 之于 D”:没有 D 的数据也能提升 D |
3.1 加法:两次互不知情的微调,相加就得到一个两个任务都会的模型
代码 01 演示 3 把 10 对任务向量两两相加(),按归一化准确率(合并模型的准确率 ÷ 专门模型的准确率,两个任务平均):
| 任务对 | 同组? | 归一化 | 验证集 bpc |
|---|---|---|---|
| verdict + food | 是 | 1.000 | 0.488 |
| verdict + parity | 否 | 1.000 | 0.514 |
| food + service | 是 | 0.978 | 0.634 |
| verdict + tens | 否 | 0.968 | 0.552 |
| verdict + service | 是 | 0.947 | 0.493 |
| food + tens | 否 | 0.917 | 0.700 |
| service + parity | 否 | 0.833 | 0.611 |
| food + parity | 否 | 0.770 | 0.637 |
| service + tens | 否 | 0.613 | 0.657 |
| parity + tens | 是 | 0.482 | 0.723 |
10 对的平均 0.851。一半的对子在 0.9 以上——两个人各自微调、互不知情,把”补丁”直接相加,就得到一个两个任务都会的模型。Ilharco et al. 在 CLIP 上(8 个图像分类任务里任取两个)的平均是 98.9%,比我们好得多:我们的模型小得多,“近似线性”的区域也小得多(§3.4)。
两个值得注意的地方:
- 代价藏在验证集上。 每个补丁都带着一点”遗忘”,两个加起来遗忘更多(0.488–0.723,单个任务 0.420–0.518)。
- 余弦相似度不能预测哪一对合并得好。 同组和跨组的平均几乎一样(0.852 vs 0.850);最差的是同组的 parity + tens(0.482)。两个任务的提示都以一个两位数结尾,要从同一个位置读出不同的东西(奇偶 vs 十位)——这是一个猜测,§4.4 会看到干扰的另一面。
3.2 减法:只用”坏的例子”,去掉一种行为
第 1 讲的迷你世界里,故事句的代词和职业有关:pilot 后面 85% 是 she,tailor 后面 85% 是 he(这是我们随意设定的偏斜,第 1 讲 §0)。base model 学到了这个偏斜。能不能把它”减掉”?
代码 01 演示 4 的做法和 Ilharco et al. 减少 GPT-2 有害输出的做法一样:
- 造一份极端的刻板印象数据:4 个有偏斜的职业,代词总是多数的那个(pilot / potter 永远 she,tailor / judge 永远 he);
- 在上面微调 200 步,得到”刻板印象向量” ;
- 从 base model 里减掉它:。
“偏斜” = 8 个职业的 的平均:
| 模型 | 偏斜 | 验证集 bpc |
|---|---|---|
| base model | 0.152 | 0.409 |
| 在刻板印象上微调 | 0.377 | 0.419 |
| 0.094 | 0.410 | |
| 0.050 | 0.413 | |
| 0.053 | 0.421 | |
| 0.242 | 0.480 | |
| 同样长的随机向量 | 0.146 | 0.409 |
| 在 50 / 50 的数据上微调 | 0.033 | 0.418 |
几点观察:
- 减掉一半就把偏斜降到三分之一,验证集几乎不变。我们从没告诉模型”正确的比例是多少”,只给了”坏的例子”。
- 减太多会矫枉过正: 时所有职业一起偏向 he()。
- 方向才是关键:减掉一个同样长度的随机向量几乎没有作用。
- 在 50 / 50 的数据上直接微调效果更好一点(0.033)。如果你有”好的数据”,这当然更直接;任务向量的好处是减法不需要再训练、 可以事后调、同一个向量还能加回去(撤销)。
- 刻板印象微调还”传染”到了没有偏斜的职业:baker、singer 都从 0.5 左右偏到了 0.2 以下。一个补丁的影响范围常常比你以为的大——这也是为什么需要回归测试(§7.2)。
Ilharco et al. 的数字:GPT-2 Large 减掉”有害文本”任务向量后,有害输出从 4.8% 降到 0.8%,WikiText-103 困惑度从 16.4 变成 16.9(他们要求在 0.5 以内);对照的”梯度上升”(直接在有害数据上最大化损失)把有害输出降到 0,代价是困惑度爆炸到 以上。图像上,CLIP ViT-L/14 减掉任务向量后,目标任务的准确率平均下降 45.8 个百分点,ImageNet 上几乎不变。
3.3 类比
如果任务 A、B、C、D 满足”A 之于 B 如 C 之于 D”,那么 。Ilharco et al. 的例子:情感分类,从”亚马逊评论”迁移到”Yelp 评论”——用”亚马逊上的语言模型任务向量”、“Yelp 上的语言模型任务向量”和”亚马逊上的情感分类任务向量”组合出”Yelp 上的情感分类”,不需要 Yelp 的标注数据。这和 word2vec 的 king − man + woman ≈ queen 是同一个味道,只不过运算发生在权重空间里。我们的代码没有做类比(练习 4 让你试)。
3.4 为什么能工作:小步之内近似线性
一个直觉的解释:在 附近做一阶泰勒展开,
如果这个近似成立,模型的输出对 是线性的: 的效果 = 的效果 + 的效果。再加上任务 A 的输入 上,(B 的补丁不影响 A 的输入),两个补丁就互不干扰。
两个前提都只是”近似”:
- “小步”: 越短,线性近似越好。这就是我们用小学习率(1e-4)的原因;写代码时我先用 3e-4 和 1e-3,任务向量更长,相加后原验证集坏到 2–4 bit/字符(README “关于实验结果”)。
- “互不影响”:Ortiz-Jimenez et al.(NeurIPS 2023)把它叫做”权重解耦”(weight disentanglement),发现它随预训练和规模而增强——这可以解释为什么任务算术在大模型上好用得多,在我们的 11 万参数模型上差一截。
4. 合并的方法与干扰 · Merging methods and interference
4.1 从一个模型的多个版本说起:model soups
最早引起注意的合并其实是同一个任务的多个微调版本。通常的做法是用不同超参数微调很多次,留下开发集上最好的那个,其余扔掉。Wortsman et al.(ICML 2022)的 model soups 把它们的权重平均起来:准确率和鲁棒性往往比最好的单个模型还高,而且和集成(ensemble)不同,推理成本没有任何增加——平均之后还是一个模型。他们的 ViT-G 汤在 ImageNet 上达到 90.94% 的 top-1 准确率(当时的最好成绩)。
“平均”能工作,是因为这些模型都从同一个预训练模型出发,落在同一个”盆地”里(§5)。下面看不同任务的模型合并。
4.2 Fisher 加权平均:给每个参数一个”发言权”
Matena & Raffel(NeurIPS 2022)从贝叶斯的角度看合并:每个微调模型给出了参数的一个”后验分布”,合并 = 找一组参数,同时让所有后验的概率都高。用拉普拉斯近似,把模型 的后验近似成以 为中心的高斯分布,精度矩阵取 Fisher 信息 。几个高斯的乘积的峰值是:
只用对角 Fisher 时,就是逐个参数的加权平均:对任务 重要的参数( 大),合并时更多地听任务 的。普通平均相当于假设所有 都相同(各向同性的高斯)。对角 Fisher 的估计很简单:
论文报告 Fisher 合并在鲁棒微调、模型集成上好于简单平均,在”中间任务训练""领域自适应预训练”这类迁移场景里,用低得多的成本达到了和梯度迁移相当的效果。
4.3 TIES-Merging:修剪、选符号、只平均同意的
Yadav, Tam, Choshen, Raffel & Bansal(NeurIPS 2023)认为直接相加有两种干扰:
- 冗余:每个任务向量里大部分分量很小,只是噪声,相加之后会淹没别的任务的重要分量;
- 符号冲突:同一个参数,任务 A 想让它变大、任务 B 想让它变小,相加之后互相抵消。
所以分三步(TRIM、ELECT SIGN、MERGE):
1. 修剪:每个 τ_t 只保留绝对值最大的 k%(论文默认 20%),其余置 0
2. 选符号:每个参数的符号 = sign(Σ_t 修剪后的 τ_t) —— 谁的总量大听谁的
3. 不相交的平均:只对符号和选出的一致的那些任务求平均
最后 θ = θ_0 + λ · 合并后的向量
论文在多种模态、任务数、模型大小上报告 TIES 好于之前的方法,并认为解决符号冲突尤其重要。
4.4 在我们的 5 个任务上比一比
代码 02 演示 1 把 5 个任务模型合并成 1 个(测试集准确率;超参数都在开发集上选):
| 方法 | verdict | food | service | parity | tens | 归一化 | bpc |
|---|---|---|---|---|---|---|---|
| 5 个专门模型(上限) | 1.000 | 1.000 | 1.000 | 1.000 | 0.817 | 1.000 | — |
| base model(不合并) | 0.847 | 0.463 | 0.517 | 0.410 | 0.147 | 0.483 | 0.409 |
| 简单平均() | 1.000 | 0.603 | 0.480 | 0.410 | 0.093 | 0.522 | 0.413 |
| 直接相加() | 0.723 | 0.567 | 0.947 | 1.000 | 0.147 | 0.683 | 1.384 |
| 任务算术() | 0.993 | 0.887 | 1.000 | 0.893 | 0.243 | 0.814 | 0.548 |
| TIES(k = 50%,) | 0.840 | 0.643 | 0.643 | 0.590 | 0.213 | 0.596 | 0.470 |
| Fisher 加权平均 | 0.827 | 0.453 | 0.717 | 0.590 | 0.330 | 0.598 | 0.458 |
| 多任务微调(共享数据,2000 步) | 1.000 | 1.000 | 1.000 | 1.000 | 1.000 | 1.045 | 0.793 |
怎么读这张表:
- 简单平均几乎等于没合并:每个任务向量被缩小到 1/5,只有本来就接近会的 verdict 到了 1.000。直接相加又走得太远:任务之间互相干扰,原验证集从 0.409 坏到 1.384。
- 任务算术在两者之间选出 ,是最好的合并:5 个任务里 4 个在 0.89 以上,只有 tens 掉得多。它只用到 5 个任务向量和一小份开发集——不需要训练数据,也不需要再训练。
- TIES 和 Fisher 平均都比简单平均好,但都没有赢过任务算术。 这和论文不一样(TIES 论文在 T5、ViT 上报告它稳定地超过任务算术)。一个可能的原因在 §2.3 的表里:我们的小模型里,被修剪掉的小分量也携带了不少能力;Fisher 平均则和简单平均一样受”1/5 稀释”的影响。我没有为了得到论文的结论去调更多的超参数——这是一个真实的”小模型上不成立”的例子。
- 多任务微调几乎完美(tens 甚至从 0.817 升到 1.000:一起学 parity 帮了 tens),但原验证集 0.793 比任务算术还差,而且它需要把 5 份数据放在一起重新训练——这正是开源协作里做不到的事。合并的价值在于:只交换参数,不交换数据。
4.5 任务越多越难
代码 02 演示 2 对 2、3、4、5 个任务的全部组合做合并,报告归一化准确率的平均:
| 合并几个任务 | 组合数 | 简单平均 | 任务算术 | TIES | Fisher | 任务算术选的 |
|---|---|---|---|---|---|---|
| 2 | 10 | 0.626 | 0.924 | 0.868 | 0.816 | 0.5–1.0 |
| 3 | 10 | 0.531 | 0.831 | 0.756 | 0.702 | 0.6–0.9 |
| 4 | 5 | 0.521 | 0.812 | 0.692 | 0.641 | 0.6–0.7 |
| 5 | 1 | 0.522 | 0.814 | 0.596 | 0.598 | 0.6 |
大体上所有方法都随任务数增加而变差(任务算术在 4、5 个任务时持平)。Ilharco et al. 在 CLIP 上看到同样的趋势:2 个任务 98.9%,8 个任务全部相加 91.2%。简单平均掉得最快—— 个任务时每个补丁只剩 ——3 个任务以上就和 base model 差不多。任务算术选出的 随任务数增加而变小:任务越多,越要”少走一点”来减少干扰。
4.6 干扰从哪里来:随机撞车,而不是系统对抗
代码 02 演示 3 把每个任务向量修剪到最大的 20%,再数每个参数被几个任务同时改动、方向是否一致:
| 同时改动它的任务数 | 占参数的比例 | 其中符号冲突 | 符号完全随机时的期望 |
|---|---|---|---|
| 0 | 36.0% | — | — |
| 1 | 37.3% | — | — |
| 2 | 19.2% | 49.2% | 50.0% |
| 3 | 5.9% | 73.8% | 75.0% |
| 4 | 1.3% | 84.4% | 87.5% |
| 5 | 0.3% | 84.8% | 93.8% |
每个任务只留 20%,5 个任务加起来却覆盖了 64% 的参数,其中 27% 被两个以上的任务同时改动。而这些重叠的参数里,符号冲突的比例和”符号完全随机”几乎一样。两两之间看,冲突比例都在 45%–52%,只有评论组内部略低于 50%。
这告诉我们:不同任务之间不是在系统地”对着干”,而是随机地撞车——这和任务向量几乎正交是同一件事的两面。但随机撞车也有代价:直接相加时,一半的重叠改动互相抵消。TIES 的”选符号”在每个冲突的参数上只听多数派的,少数派的改动被丢掉;如果这些改动并不都是噪声(在我们的模型里似乎不是),TIES 就会吃亏。
4.7 合并、多任务训练、集成:怎么选
| 需要共享数据? | 需要再训练? | 推理成本 | 存储 | 效果(一般而言) | |
|---|---|---|---|---|---|
| 个专门模型 | 否 | 否 | 1 个模型 / 次(但要知道用哪个) | 个模型 | 每个任务最好 |
| 集成(ensemble) | 否 | 否 | 倍 | 个模型 | 好 |
| 多任务训练 | 是 | 是 | 1 | 1 | 通常最好 |
| 参数合并 | 否 | 否(只需一小份开发集选 ) | 1 | 1 | 介于中间,随任务数下降 |
合并的独特之处在最后一行:它是唯一一个”不共享数据、不再训练、推理成本不变”的方法。这正好对应开源协作的约束:贡献者各自有数据和算力,交回来的只是参数。
5. 为什么只有”同一个起点”才行 · Why a shared starting point matters
5.1 线性模式连通性
Frankle et al.(ICML 2020)研究了一个问题:从同一个参数出发、用不同的随机性(数据顺序)训练出两个模型 、,它们之间的直线 上,损失会不会先升后降?如果不会(损失屏障 ≈ 0),就说两者线性模式连通(linearly mode connected):它们在同一个”盆地”里。他们发现,从随机初始化开始训练时通常不连通,但只要先训练一小段再分叉,就连通了——训练早期很快就”选定”了一个盆地。
Neyshabur, Sedghi & Zhang(NeurIPS 2020)在迁移学习里看到同样的现象:从同一个预训练模型出发微调的模型,留在损失地形的同一个盆地里,它们在特征空间里相似、在参数空间里接近。这就是 §2–§4 的一切能工作的原因:所有任务向量都从同一个 出发。
代码 03 演示 1 在两个微调模型之间走直线:
- verdict ↔ parity:验证集 bpc 两端 0.420 / 0.483,路径上最低 0.415,没有任何”山”(屏障 = 0)。任务准确率在路径上”交接”,而且很突然:–0.8 时两个任务都在 0.99 以上;中点 时 parity 还停在 0.410。
- parity ↔ tens:bpc 两端 0.483 / 0.518,中点反而更低(0.440,中点离 base model 更近,遗忘更少)。但找不到一个 让两个任务同时高。
所以合并失败不一定是因为损失地形里有山——平坦的盆地里也会有任务之间的干扰。
5.2 置换对称性:同一个函数,很多份”抄本”
神经网络有大量对称性。最简单的一种:把 MLP 的第 个和第 个隐藏神经元连同它们的进出权重一起交换,输出完全不变。TinyGPT 里可以这样置换的有:残差流的 64 个维度(LayerNorm 只用到均值和方差,对维度顺序不敏感)、每层 MLP 的 256 个单元、每层 4 个注意力头的顺序、每个头内部 q / k 和 v 的维度。
代码 03 演示 2 把 base model 的所有这些单元随机重排:
- 输出和原模型只差 3e-5(浮点运算顺序不同),验证集 bpc 都是 0.409——同一个函数;
- 参数之间的距离 38.8,比参数本身的范数(33.3)还大——完全不同的参数;
- 把两者平均:中点的 bpc 是 6.463,比均匀乱猜()还差。
第 个神经元和第 个神经元被平均到了一起,而它们本来在做不同的事。这说明”参数平均”本身没有意义;它只在两个模型的隐藏单元已经对应好时才有意义。从同一个预训练模型出发的微调,自动满足这个条件。
5.3 两个独立训练的模型:先对齐,再平均
Entezari et al.(ICLR 2022)猜想:如果把置换对称性考虑进去,独立训练的模型之间的屏障大多会消失。Ainsworth, Hayase & Srinivasa 的 Git Re-Basin(ICLR 2023)给出了几种对齐算法(按权重匹配、按激活匹配等),在 MLP 和 ResNet 上把独立训练的模型对齐后再插值,第一次在 CIFAR-10 的 ResNet 上做到了屏障接近 0;他们也发现模型越宽越容易对齐,并给出了反例。
代码 03 演示 3 用不同的初始化种子(1 而不是 0)、完全相同的数据和设置,再从零预训练一个 base model(验证集 0.411,和原模型 0.409 一样好),然后:
- 直接插值:中点 bpc 6.255,屏障 5.845——和”抄本平均”差不多。
- 按激活对齐后再插值:在同一批验证集文本上跑两个模型,对每一类可置换的单元算两两相关系数,用匈牙利算法求”总相关最大”的一一对应(先按注意力模式对齐头,再对齐头内部的维度),然后重排第二个模型。中点 4.024,屏障降到 3.614。
对齐确实消掉了一部分屏障,但远没有消失;参数距离也只从 38.6 降到 36.0。两个独立训练的 Transformer 并不只是彼此”换了顺序的抄本”。原因至少有两个:我们的模型只有 64 维(Git Re-Basin 发现越窄越难对齐);注意力头内部的对称性不只是置换——q 乘一个可逆矩阵 、k 乘 ,注意力分数完全不变,这种连续的对称性按单元一一配对是对不齐的。
5.4 补丁只能打到它被写出来的那个版本上
代码 03 演示 4 把这件事落到”补丁”上:在另一个 base model 上微调 parity(它自己用起来是满分),把这个任务向量加到我们的 base model 上:
| 模型 | parity 准确率 | 验证集 bpc |
|---|---|---|
| base model | 0.410 | 0.409 |
| + 自己的补丁(在 base 上微调) | 1.000 | 0.483 |
| + 别人的补丁(在另一个 base 上微调) | 0.410 | 0.427 |
| + 别人的补丁,先按对齐的置换”翻译” | 0.410 | 0.418 |
完全没用,“翻译”之后也没用。这就像一个 diff 只能打到它被写出来的那个版本上——换了版本,行号全对不上。
这解释了开源模型生态的一个现象:大家都从同一个公开的 base model 出发微调(同一个 BERT、同一个 T5、后来同一个 Llama 版本)。共享的起点不只是为了省算力,更是任务向量能够互相合并、补丁能够互相交换的前提。用开源软件的话说:base model 就是主干(trunk),一切分支都从它长出来。也因此,换一个新的 base model(“主版本升级”)意味着所有下游的补丁都要重做——这是 §7.2 版本号设计要面对的问题。
6. 便宜的补丁:稀疏、低秩、模块 · Cheap, communicable updates
6.1 稀疏补丁:只改最重要的那一小部分参数
梯度下降每一步都改动全部参数,所以一次微调的”diff”和模型一样大。分布式训练和联邦学习早就在研究怎样减少通信:只更新一部分参数,或者压缩更新(第 9 讲 §7.4)。Sung, Nair & Raffel(NeurIPS 2021)提出固定稀疏掩码(FISH mask):训练开始前,用 base model 在任务数据上算一遍对角 Fisher 信息,选 Fisher 最大的 个参数,整个训练过程只更新它们。Raffel 的博客引用这项工作:只更新 0.5% 的参数,可以达到和全部参数训练相近的效果。
代码 04 演示 1(学习率 1e-3;最后一行是全部参数、学习率 1e-4):
| 任务 | k | 补丁大小 | Fisher 掩码:准确率 | bpc | 随机掩码:准确率 | bpc |
|---|---|---|---|---|---|---|
| food | 0.5% | 4.3 KB | 0.823 | 1.293 | 0.570 | 0.591 |
| food | 2% | 17.0 KB | 0.997 | 1.865 | 0.930 | 0.482 |
| food | 10% | 85.2 KB | 1.000 | 1.188 | 1.000 | 0.559 |
| food | 100% | 426.0 KB | 1.000 | 0.460 | — | — |
| tens | 0.5% | 4.3 KB | 0.180 | 0.897 | 0.050 | 0.460 |
| tens | 2% | 17.0 KB | 0.770 | 0.893 | 0.273 | 0.546 |
| tens | 10% | 85.2 KB | 1.000 | 1.135 | 1.000 | 0.934 |
| tens | 100% | 426.0 KB | 0.817 | 0.518 | — | — |
(稀疏补丁每个改动存 4 字节下标 + 4 字节新值;稠密补丁存全部 109,056 个 float32。)
- 补丁可以很小:只改 2% 的参数(17 KB,整个模型的 1/25),food 就到了 0.997。Fisher 选的位置比随机位置有效得多:0.5% 时 0.823 vs 0.570;tens 在 2% 时 0.770 vs 0.273。
- 但有一个我写代码前没想到的代价:Fisher 掩码的模型把原验证集弄坏得多得多(bpc 0.89–1.87;随机掩码 0.46–0.93;全部参数 0.46–0.52)。Fisher 大的参数是”对这个任务的输出最敏感”的参数——比如答案那几个字符的嵌入——它们对一般的语言建模也最敏感;再加上学习率大,改得又猛又集中。补丁小和不弄坏别的功能是两回事。
- 小心混杂因素:稀疏补丁的学习率是全部参数的 10 倍,所以 tens 在 10% 时(1.000)反而超过了全部参数(0.817)。这说明的是学习率,不是”稀疏更好”——第 6 讲 §3.4 遇到过同样的问题(BitFit 和全量微调的学习率差了 30 倍)。
6.2 低秩补丁:LoRA
另一种”小补丁”是第 6 讲 §4.6 的 LoRA:权重更新限制成低秩 。第 6 讲代码 03 里,一个 LoRA 插件只有 36.9 KB,整个模型 434.1 KB;合并进 之后,推理没有额外成本。LoRA 后来成了开源社区交换”补丁”最常见的格式:一个 base model、成百上千个 LoRA(第 6 讲 §4.8”一个基座,很多插件”)。
6.3 模块:让不同的贡献在计算图上也分开
博客列出的第三条路是模块化:adapter(第 6 讲 §4.2)、混合专家层(第 3 讲 §8.1)、读外部数据的模型(kNN-LM、REALM、RAG,第 3 讲 §8.2)。设想一个模型可以插上”新语言输入模块""检索模块""生成模块”,再配一个包管理器,声明每个模型由哪些子模块组成、兼容哪些版本——就像 Python 的依赖管理。
6.4 参数不重叠 ≠ 功能不重叠
稀疏补丁还有一个诱人的想法:如果每个贡献只改动一小部分参数,而且彼此不重叠,合并时不就没有冲突了吗?代码 04 演示 2 检验了这个想法:
| 补丁 | 覆盖的参数 | 被 ≥ 2 个补丁改动 | 归一化 | bpc | |
|---|---|---|---|---|---|
| Fisher 掩码 2% × 5 | 7.0% | 1.8% | 0.5 | 0.520 | 1.563 |
| Fisher 掩码 2% × 5 | 7.0% | 1.8% | 1.0 | 0.422 | 5.705 |
| 随机掩码 10% × 5 | 40.9% | 8.2% | 0.5 | 0.631 | 0.685 |
| 随机掩码 10% × 5 | 40.9% | 8.2% | 1.0 | 0.489 | 2.263 |
| (对照)稠密任务算术 | 100% | — | 0.6 | 0.814 | 0.548 |
5 个 Fisher 补丁一共只覆盖 7% 的参数、几乎不重叠,合并之后照样互相干扰,比稠密的任务算术还差。原因是:所有任务共享同一条残差流、同一批字符嵌入(第 12 讲 §2.1)。一个补丁改了”读这个位置的方式”,另一个补丁的输入就变了。在代码里,两个改了不同行的 commit 可以干净地合并;在神经网络里,“不同的行”仍然通过前向传播连在一起。这正是 §6.3 的模块化要解决的问题:让不同的贡献不仅在参数上分开,在计算上也分开(例如每个任务走自己的 adapter,或者用路由在专家之间选择)。
7. 版本控制、测试与社区协作 · Version control, testing and collaboration
7.1 Git-Theta:给参数做版本控制
普通的版本控制工具(以及 Git LFS)把模型检查点当成一个不透明的大文件:改一个参数,整个文件都是”新的”。Kandpal et al.(2023)的 Git-Theta 是 Git 的一个扩展,它理解检查点的内部结构,按参数组(每一层的每个矩阵)跟踪变化,因此能做到:
- 省通信的更新:只存、只传改动过的参数组;稀疏或低秩的更新可以按补丁的形式存储;
- 自动合并:两个分支改了同一个参数组时,可以调用合并策略(平均、任务算术……)而不是报冲突;
- 有意义的 diff:报告两个版本之间哪些层变了、变了多少;
- 插件系统:用户可以加入新的更新类型和合并策略。
论文演示了一个持续适配、修改预训练模型的场景。它还很初步,但方向很清楚:把 §2–§6 的技术变成日常工具。
7.2 测试:下游评测就是单元测试,但很贵
开源软件靠自动测试决定能不能合并。模型的”测试”是什么?博客的回答:下游任务上的表现——以及能力测试和偏见测试(例如共指消解里的性别偏见数据集)。困难在于:
- 贵:每个下游任务可能要微调几百到几千步,而一个模型通常要在几十个任务上评测。
- 一个改动的影响范围很难预料:§3.2 的刻板印象补丁”传染”到了没有偏斜的职业;§6.1 的稀疏补丁把语言建模弄坏了。
博客还提出了一套模型的语义化版本号:
- 补丁版(1.0.0 → 1.0.1):只改一小部分参数,性能不明显下降;
- 次版本(1.0 → 1.1):可以改架构,但保留大部分参数;
- 主版本(1.x → 2.0):换一个新模型,面向同样的用途。
“向后兼容”指的是:目标任务上的表现不下降,输入输出的类型不变。博客的例子:一个视觉模型如果不再支持深度图(RGB-D)输入,就破坏了向后兼容。
博客里有一个虚构的时间线,很好地把这些想法串在一起:某大学用有限的算力发布了社区语言模型 CLAMP 1.0.0;另一个组加入了稀疏更新,和一个并行的改进一起合并成 1.0.1;有人提交了一个压缩技术,因为在一个新的公平性测试上表现变差而被拒绝;一个”新语言模块”让版本升到 1.1.0;一个源代码模块超出了项目的范围,于是分叉成了另一个模型;最后,一个更高效的架构带来了 2.0.0。
7.3 社区迭代改进:ColD Fusion
Don-Yehiya et al.(ACL 2023)的 ColD Fusion 把”合并”变成一个循环:
共享模型 θ_r
├── 贡献者 1 在自己的数据上微调 → θ_r,1 ┐
├── 贡献者 2 …… → θ_r,2 ├─ 维护者平均 → θ_{r+1}
└── 贡献者 k …… → θ_r,k ┘
下一轮所有人从 θ_{r+1} 出发
贡献者不分享数据,只交回微调后的模型。论文在 35 个数据集上迭代,得到的模型在它见过的所有数据集上都表现很好,作为新任务的微调起点也更好:平均比 RoBERTa 高 2.33 分,架构完全不变。
代码 04 演示 3 做了一个玩具版:4 个贡献者(verdict、food、parity、tens),每轮各微调 200 步,平均成新的共享模型;service 不参与,用来看”没见过的任务”。每轮跑一次回归测试:原验证集 bpc 不能超过 base model 的 1.1 倍(≤ 0.449)。
| 第几轮 | 归一化(4 个任务) | bpc | 回归测试 | service(零样本) |
|---|---|---|---|---|
| 0(base) | 0.475 | 0.409 | 通过 | 0.517 |
| 1 | 0.518 | 0.412 | 通过 | 0.737 |
| 2 | 0.544 | 0.423 | 通过 | 0.853 |
| 3 | 0.593 | 0.442 | 通过 | 0.780 |
| 4 | 0.803 | 0.463 | 不通过 | 0.660 |
| 5 | 0.846 | 0.488 | 不通过 | 0.597 |
贡献者微调时混入预训练文本(回放,第 6 讲 §3.4):
| 第几轮 | 归一化 | bpc | 回归测试 | service(零样本) |
|---|---|---|---|---|
| 1 | 0.509 | 0.406 | 通过 | 0.637 |
| 3 | 0.587 | 0.406 | 通过 | 0.717 |
| 5 | 0.604 | 0.407 | 通过 | 0.790 |
- 迭代很关键。 第 1 轮之后只有 0.518——和一次性的简单平均差不多(§4.4)。但一轮一轮迭代下去,共享模型在 4 个任务上同时变好(第 5 轮 0.846):每一轮大家都从”已经包含别人改进”的版本出发,干扰被一点点消化掉。
- 测试守门。 代价是共享模型离原来的语言模型越来越远,第 4 轮起过不了回归测试——就像一个项目不停合并新功能,却没人跑老的测试。回放让 bpc 一直在 0.41 以内,但任务上的进步慢得多(第 5 轮 0.604,parity 一直没学会)。守住旧功能和加新功能之间有真实的取舍;回归测试的作用是让这个取舍变得可见。
- 没参与的任务:零样本准确率先升后降(0.517 → 0.853 → 0.597),回放的版本则一直在升(→ 0.790)。ColD Fusion 报告共享模型是更好的”微调起点”;我们的 service 任务太简单(从 base model 微调 50 步就满分),看不出起点的差别。
7.4 协作训练与协作推理
“社区一起造模型”在 2022–2023 年已经有了几个真实的例子:
- BigScience / BLOOM(第 10 讲 §5):上千名研究者、一年的开放协作,训练了 176B 参数的多语言模型,并公开了数据治理、训练日志和模型。它证明了”大模型可以不出自一家公司”,但训练本身仍然是在一台超级计算机上集中进行的。
- 去中心化训练(第 9 讲 §7):Ce Zhang 等人研究在慢速、异构的网络上训练,把重的通信放在快的链路上。
- Petals(Borzunov et al. 2023,Raffel 是作者之一):让很多人各自贡献一张消费级 GPU,每人托管模型的几层,像 BitTorrent 一样拼成一个完整的 BLOOM-176B。推理速度约每秒 1 步,足够做交互式应用,比把模型卸载到内存里快得多。和大多数推理 API 不同,Petals 暴露了模型的隐藏状态,所以用户可以在上面训练、分享自己的参数高效插件(prompt tuning、adapter)——“一个共享的 base model + 社区贡献的补丁”。
8. 开放权重的生态与许可 · The open-weights ecosystem
8.1 模型仓库与文档
Hugging Face Hub 在 2023 年已经成了”模型的 GitHub”:成千上万的检查点、数据集和 demo,大多数从少数几个 base model 微调而来。Ilharco et al. 做 NLP 实验时,就在 Hub 上找到了 427 个和 T5-base 兼容的检查点,挑出能帮助目标任务的任务向量加上去。社区也逐渐建立了”文档”的规范:模型卡(Mitchell et al. 2019,第 2 讲 §3 讲了数据的文档)说明模型的用途、训练数据、评测、局限和伦理考虑。
8.2 “开放”是一个光谱
2022–2023 年的大模型,开放程度差别很大:
| 开放程度 | 例子(2022–2023) | 你能做什么 |
|---|---|---|
| 只有 API | GPT-3、ChatGPT | 调用;不能看参数,不能微调(或只能用平台的微调服务) |
| 申请后获取权重 | OPT-175B、LLaMA(2023 年 2 月,研究用途) | 研究用途下可以微调、分析 |
| 开放权重 + 使用限制 | BLOOM(BigScience RAIL 许可) | 下载、微调、部署,但不能用于许可列出的有害用途 |
| 权重 + 数据 + 代码 + 中间检查点 | Pythia(第 12 讲 §7)、BLOOM 的训练过程 | 复现、研究训练动态 |
“像开源软件一样构建模型”需要的不只是开放权重:要能修改和合并,需要共享的 base model 和工具(§5、§7.1);要能审查贡献,需要测试和文档(§7.2、§8.1);要能真正”复现”,还需要数据和训练代码。
8.3 许可:开源软件的许可证为什么不够用
开源软件的许可证(MIT、Apache 2.0、GPL)关心的是代码能不能被复制、修改、再分发。模型多了几个新问题:
- 使用限制:BigScience 的 RAIL(Responsible AI License)在允许自由使用的同时,列出了一些禁止的用途。这和传统开源”不能歧视使用领域”的原则有张力,引发了”这还算不算开源”的争论。
- 衍生品:微调过的模型、合并出的模型、一个 LoRA 补丁,算不算”衍生作品”?许可证的条款是否传递给它们?
- 训练数据的权利:模型是在受版权保护的数据上训练的,这对模型本身的许可意味着什么?(第 19 讲)
这些问题在 2023 年都没有定论;法律部分留到第 19 讲,这里只指出:技术上的可合并性和法律上的可合并性是两回事——两个许可证不兼容的模型,技术上能平均,法律上可能不能分发。
9. 2023 年之后 · Since 2023
- 开放权重模型的爆发。 LLaMA 在 2023 年 2 月以研究许可发布,几周之内社区就在它上面做出了大量指令微调模型(例如 Stanford 的 Alpaca)。2023 年 7 月的 Llama 2 允许商用(附带条件),同年 9 月的 Mistral 7B 用 Apache 2.0 发布。此后 Qwen、DeepSeek 等系列持续发布开放权重的模型。Raffel 设想的”共享的 base model + 社区补丁”的生态,以开放权重模型为主干真实地出现了——虽然 base model 本身仍然主要由资源充足的机构一次性训练。
- 合并成了日常实践。 开源工具 mergekit(Goddard et al. 2024)把任务算术、TIES、DARE(Yu et al. 2023:随机丢掉大部分分量再放大,和 TIES 的修剪思路相近)、球面插值等方法做成了配置文件;2024 年前后,开放排行榜上排名靠前的模型里有相当一部分是合并出来的。Sakana AI 的”进化式模型合并”(Akiba et al. 2024)用进化算法自动搜索合并配方。一些大模型的后训练流程也把多个检查点的平均作为一个步骤。
- 从”合并”到”路由”。 与其把所有专门模型压成一个,不如保留它们、按输入选一个或几个来用:LoRA 的组合与检索、Branch-Train-Merge(Li et al. 2022)把领域专家训练好再合并或组合、Branch-Train-MiX(Sukhbaatar et al. 2024)把几个领域专家合成一个混合专家模型。Raffel 组的综述把这一类方法称为 “MoErging”(Yadav et al. 2024)。
- 理解为什么能合并。 “权重解耦”(Ortiz-Jimenez et al. 2023,§3.4)、在切空间里微调让任务算术更可靠;对置换和更一般的对称性的研究也在继续。
- “开源 AI”的定义之争。 开放源代码促进会(OSI)在 2024 年发布了”开源 AI 定义”,要求开放的不只是权重,还包括足够详细的训练数据信息和代码。很多”开放权重”的模型不满足这个定义。
哪些结论仍然成立? 任务向量与任务算术;共享的起点是合并的前提;干扰随任务数增加;“只交换参数、不交换数据”作为协作方式的价值。被修正或补充的:合并从研究走进了日常工具链,但 base model 的训练并没有像 Raffel 设想的那样变成社区持续更新的过程——社区协作主要发生在 base model 的下游(微调、合并、插件),而不是 base model 本身。
10. 小结 · Summary
- 问题:基础模型由少数机构一次性训练、发布后冻结;开源软件由社区持续地贡献、审查、合并。Raffel 主张把版本控制、合并、测试、版本号、模块化这些想法移植到模型上。
- 任务向量 是”一次微调的 diff”。它们很短(我们的模型里只有 的 1.4%–3.2%)、几乎两两正交(同组略相似)、能量集中,但能力不全在最大的分量里。
- 任务算术:相加得到多任务模型(我们的 10 对平均 0.851,CLIP 上 98.9%);取负去掉一种行为(我们的刻板印象偏斜 0.152 → 0.050,GPT-2 有害输出 4.8% → 0.8%); 在开发集上选,减太多会矫枉过正。
- 合并方法:简单平均被稀释、直接相加走得太远;任务算术、TIES、Fisher 各有道理。在我们的小模型上任务算术最好(5 个任务 0.814),TIES 和 Fisher 没有赢过它——和论文不同。任务越多越难合并;干扰来自”随机撞车”。合并的独特价值:不共享数据、不再训练、推理成本不变。
- 共享的起点:同一个预训练模型出发的微调在同一个盆地里(线性模式连通,屏障 = 0);置换对称性让独立训练的模型无法直接平均(屏障 5.845),按激活对齐只能消掉一部分(3.614);别的 base model 上做的补丁打不到我们的模型上。
- 便宜的补丁:稀疏(2% 的参数、17 KB 就能学会一个任务)、低秩、模块。但补丁小 ≠ 不弄坏别的功能(Fisher 掩码的遗忘严重得多);参数不重叠 ≠ 功能不重叠。
- 工具与流程:Git-Theta 按参数组做版本控制和自动合并;下游评测充当测试,回归测试守住向后兼容;ColD Fusion 式的迭代合并让社区逐轮改进一个共享模型;Petals 让社区一起托管一个大模型。
- 生态:开放是一个光谱;模型的许可比代码复杂(使用限制、衍生品、训练数据)。2023 年之后,开放权重和合并实践都爆发了,但社区协作主要发生在 base model 的下游。
11. 常见误区 · Common pitfalls
- “任务向量几乎正交,所以相加不会干扰。” 正交是参数空间里的说法;功能上的干扰来自共享的残差流和嵌入。我们的余弦都很小,但 parity + tens 相加只有 0.482(代码 01)。
- “合并就是平均。” 简单平均会把每个补丁稀释到 ;5 个任务时几乎等于没合并(0.522)。需要 这样的放大系数(代码 02)。
- “TIES / Fisher 一定比任务算术好。” 在论文的模型上通常如此;在我们的小模型上不是(0.596、0.598 vs 0.814)。方法的优劣依赖规模和任务,要在自己的设置上验证。
- “两个一样好的模型平均之后也一样好。” 只有在它们从同一个起点出发时才成立;两个独立训练的模型平均之后比乱猜还差(代码 03)。
- “补丁可以随便移植到别的模型上。” 任务向量只对它出发的那个 有意义;换了 base model,补丁完全失效(代码 03 演示 4)。
- “只改 0.5% 的参数,就不会弄坏别的功能。” 改得少不等于改得安全:Fisher 掩码改的正是最敏感的参数,遗忘比全部参数微调严重得多(代码 04)。
- “稀疏补丁互不重叠,所以可以无冲突地合并。” 参数不重叠,功能仍然通过前向传播耦合(代码 04 演示 2)。
- “开放权重 = 开源。” 开放权重只是光谱上的一档;许可可能带使用限制,数据和训练代码可能不公开。
- “多任务训练总是更好,所以合并没有意义。” 多任务训练需要共享数据和重新训练;在数据不能共享的协作场景里,它根本不是一个选项。
12. 练习 · Exercises
练习 1(λ 的意义) 任务算术 。证明: 时它就是 个微调模型的简单平均。 呢?
参考答案
,正是 。 是”把所有补丁都完整地打上去”:。如果补丁之间完全不干扰(线性 + 解耦), 是理想的;干扰越大,最优的 越小(代码 02 演示 2:5 个任务时选出 0.6)。
练习 2(为什么高维向量几乎正交) 两个独立的、各分量服从标准正态的 维随机向量,余弦相似度的标准差大约是多少?用它解释代码 01 里”随机向量的余弦 +0.0031”。
参考答案
。 是 个均值 0、方差 1 的独立项之和,标准差 ;。所以余弦的标准差约 。 时约 0.0030,代码 01 的 +0.0031 正好在一个标准差左右。任务向量之间的余弦(多数在 0.01–0.05)是这个尺度的几倍到十几倍,所以虽小,但不是噪声。
练习 3(Fisher 合并的推导) 两个模型的后验分别近似为 、(对角)。证明两者乘积的峰值是 (逐元素)。如果某个参数 、,合并结果是什么?
参考答案
对数乘积 (逐元素)。对 求导令其为 0:,得 。 时 :模型 1 对这个参数”没有意见”,完全听模型 2 的。这就是 Fisher 合并比简单平均好的地方:每个参数由真正在乎它的模型决定。代码里的 merge_fisher 加了一个很小的 eps,避免两个 Fisher 都是 0 时除以 0。
练习 4(改代码:类比) 设计一个”类比”实验:在 food 任务的格式下,把答案换成 good / bad(而不是 great / awful),得到任务 A’;你能否用 、 和别的向量组合出 A’ 的任务向量?写下你的设计和预期(不要求运行)。
参考答案
一种设计:A = food(great / awful),B = A’(good / bad,目标),C = 一个”用 great / awful 作答的评论任务”(例如把 verdict 的答案映射成 great / ok / awful),D = verdict(good / ok / bad)。“A 之于 B 如 C 之于 D”:答案词从 great / awful 换成 good / bad。于是 。预期:如果”换答案词”这个改动在两个任务里对应同一个权重方向,组合出的模型在 A’ 上会明显好于 base model;但在我们的字符级小模型里,答案词的改动集中在字符嵌入上,和格式的改动纠缠在一起,效果可能有限(具体以你运行的结果为准)。
练习 5(改一行代码,预测结果) 把 merge_lab.FT_CFG 的学习率从 1e-4 改成 1e-3(删掉 checkpoints/ 重新训练)。你预测任务向量的长度、两两相加的归一化准确率、合并后的验证集 bpc 会怎样变化?
参考答案
学习率大 10 倍,任务向量会长得多(离 更远),线性近似变差:两两相加的归一化准确率应该下降,合并后的 bpc 会上升得多。写代码时我的原型用过 1e-3(另一组任务):单个任务的 bpc 已经到 1.5–3.9,四个任务相加后超过 7 bit/字符(README “关于实验结果” 第 2 条)。这就是”小步”前提的重要性(§3.4)。具体数字以你运行的结果为准。
练习 6(损失屏障) 代码 03 演示 1 里,parity ↔ tens 路径中点的 bpc(0.440)比两端(0.483、0.518)都低。用”离 base model 的距离”解释这个现象。如果把路径换成 之外的另一条路,比如 ,你预测 bpc 曲线会怎样?
参考答案
中点是 ,两个补丁各打一半,离 比两端都近(、 几乎正交,中点到 的距离约为端点的 ),所以遗忘更少、bpc 更低。路径 从”只打 A”走到”A、B 都完整地打上”( 的相加),离 越来越远,bpc 应该单调上升,终点就是代码 01 演示 3 里 parity + tens 的 0.723。
练习 7(置换的计数) TinyGPT 有多少种”函数不变的置换”(只算 §5.2 列出的几类)?取对数,和参数个数比较。
参考答案
残差流 64!;每层 MLP 256!,两层 ;每层头的顺序 4!,两层 ;每个头内部 q / k 的 16! 和 v 的 16!,共 8 个头,。总数 。:,,,合计约 ,即约 种抄本。参数空间里同一个函数有天文数字般多的”副本”,随机取两个独立训练的模型,它们恰好”对齐”的可能性可以忽略——这就是为什么需要对齐算法。
练习 8(概念:为什么从同一个起点出发就能平均) Neyshabur et al. 说从同一个预训练模型出发的微调留在同一个盆地里。用 §2.3 的”任务向量很短”和 §5.2 的”置换对称性”两个事实,给出一个直觉解释。
参考答案
微调只在 附近走一小步(1%–3% 的长度),走不出 所在的盆地;而且这一小步改变不了”第 个神经元在做什么”——每个隐藏单元的角色由预训练决定,微调只是微调它。所以两个微调模型的第 个神经元仍然在做同一件事,隐藏单元自动对齐,平均才有意义。两个独立训练的模型则各自选了 种排列中的一种(练习 7),而且还可能在”连续”对称性上不同。
练习 9(概念:回归测试的阈值) 代码 04 演示 3 用”bpc ≤ base 的 1.1 倍”做回归测试,第 4 轮起不通过。如果你是 CLAMP 的维护者,你会怎样设计一套更好的测试?至少说出三类测试,以及每类测试的成本。
参考答案
(1)通用能力:原验证集的 bpc / 困惑度(便宜,一次前向);(2)已有任务的回归:每个之前合并进来的任务,在它的测试集上不能掉超过某个幅度(中等,需要每个任务的评测集;如果评测需要微调就很贵);(3)行为与安全测试:偏见(例如代码 01 的代词偏斜)、有害输出、隐私(第 16 讲的 canary)(中等到贵);(4)接口兼容:输入输出格式、分词器不变(便宜)。成本最高的是需要”再微调才能评测”的下游任务,所以实践中会用少样本提示或线性探针来代替完整微调。
练习 10(概念:开放程度) 一个模型公开了权重(带 RAIL 许可),但没有公开训练数据和训练代码。对于”像开源软件一样构建模型”的目标,它满足了哪些要求、缺了哪些?
参考答案
满足:可以下载、微调、合并(有共享的 base model,§5.4);可以分享补丁(任务向量、LoRA)。缺少:无法复现或审查训练过程(不知道数据里有什么、有没有测试集泄漏,第 2 讲);无法做”主干上的修改”(例如修复预训练数据里的问题后重新训练);许可的使用限制可能和其他补丁的许可冲突,影响合并后的再分发。它更像”只发布了编译好的二进制、但允许打补丁”的软件。
13. 延伸阅读 · Further reading
原课相关(2/8 Building ML Models like Open-Source Software)
- Raffel. A Call to Build Models Like We Build Open-Source Software. 2021(博客)。colinraffel.com/blog
- Matena & Raffel. Merging Models with Fisher-Weighted Averaging. NeurIPS 2022. arXiv:2111.09832
- Sung, Nair & Raffel. Training Neural Networks with Fixed Sparse Masks. NeurIPS 2021. arXiv:2111.09839
- Yadav, Tam, Choshen, Raffel & Bansal. TIES-Merging: Resolving Interference When Merging Models. NeurIPS 2023. arXiv:2306.01708
- Kandpal et al. Git-Theta: A Git Extension for Collaborative Development of Machine Learning Models. ICML 2023. arXiv:2306.04529
- Don-Yehiya et al. ColD Fusion: Collaborative Descent for Distributed Multitask Finetuning. ACL 2023. arXiv:2212.01378
- Borzunov et al. Petals: Collaborative Inference and Fine-tuning of Large Models. ACL 2023(System Demonstrations). arXiv:2209.01188
任务算术、合并与线性模式连通性
- Ilharco et al. Editing Models with Task Arithmetic. ICLR 2023. arXiv:2212.04089
- Wortsman et al. Model soups: averaging weights of multiple fine-tuned models improves accuracy without increasing inference time. ICML 2022. arXiv:2203.05482
- Frankle et al. Linear Mode Connectivity and the Lottery Ticket Hypothesis. ICML 2020. arXiv:1912.05671
- Neyshabur, Sedghi & Zhang. What is being transferred in transfer learning? NeurIPS 2020. arXiv:2008.11687
- Entezari et al. The Role of Permutation Invariance in Linear Mode Connectivity of Neural Networks. ICLR 2022. arXiv:2110.06296
- Ainsworth, Hayase & Srinivasa. Git Re-Basin: Merging Models modulo Permutation Symmetries. ICLR 2023. arXiv:2209.04836
2023 年之后
- Ortiz-Jimenez, Favero & Frossard. Task Arithmetic in the Tangent Space: Improved Editing of Pre-Trained Models. NeurIPS 2023. arXiv:2305.12827
- Yu et al. Language Models are Super Mario: Absorbing Abilities from Homologous Models as a Free Lunch(DARE). 2023. arXiv:2311.03099
- Goddard et al. Arcee’s MergeKit: A Toolkit for Merging Large Language Models. 2024. arXiv:2403.13257
- Yadav et al. A Survey on Model MoErging: Recycling and Routing Among Specialized Experts for Collaborative Learning. 2024. arXiv:2408.07057
14. 下一讲预告 · Next lecture
到这里,我们讨论的基础模型都只处理一种东西:文本。第 14 讲进入 多模态基础模型:CLIP 用 4 亿对图文做对比学习,学到一个图像和文本共享的表示空间,于是可以用一句”a photo of a dog”做零样本分类;DALL·E、扩散模型、Imagen 反过来从文本生成图像;Flamingo 把一个冻结的语言模型和一个冻结的视觉编码器接起来,做少样本的图文问答;Gato 和 VPT 则把”行动”也当成 token。代码会在一个合成的”图文配对”世界里从零做 CLIP 式的对比学习和零样本分类,在二维数据上实现带 classifier-free guidance 的扩散模型,并用 VPT 的”逆动力学模型”给没有标注的视频打伪标签。