跳到主要内容

数据截至 (上游 commit c187ef3271d5)

站在别人的权重上 — 不从随机数起步,从别人练好的地方起步

这一章讲三件事。第一件:前面十一章有一个共同的浪费,一直没人点破。 每一次训练都是从一堆随机数开始的 —— 可**「怎么认出一条边、一块纹理」这种本事, 别人早就在一百万张图上练出来了,而且和你要做的事没什么两样。**

第二件,是这一章的核心动作:把别人练好的那一大截原样锁住,只换最后一小截。 这么做省的不只是时间 —— 它同时把「要多少数据」这道门槛砍掉了一个数量级。 第 05 章那句「每类至少几百张」的钩子,在这一章兑现。

第三件,是掰开一个同名不同事的词。 「冻结」在这本书里出现过两次: 第 05 章那次冻住全部权重、被改的是输入图像;这一章冻住主干、被改的是新接上去的头。 书从不对照,读者极易以为是同一招。

在全书链条里的位置: 三个零件在这一章一个都没换 —— 换的是起点。 训练循环、数据形状、损失的选法全部照旧, 只是那堆权重不再是随机数,而是别人练好的结果。

1. 顶层全景:一个在一百万张图上练过的网络,改去分垃圾

这一章的主走查:拿一个已经在一百万张图、一千个类别上练过的网络, 把它最后那一小截换掉,改成认六种垃圾12

先把两组数摆在一起,这一章的全部道理就在这个对比里:

别人练它用的我们改它用的
图片数量超过 100 万张两千三到两千五百张
类别数1000 个6 个

我们手上的数据只有人家的约四百分之一 —— 从头练是绝无可能的。 可接着别人的练,10 轮就到 76%。

别人练好的网络(100 万张图 / 1000 类)

├─① 全部权重锁死 ────────→ 一个数都不许动

├─② 砍掉最后那一小截 ────→ 原来吐 1000 个数

├─③ 接上一小截新的 ──────→ 改成吐 6 个数

├─④ 只练这一小截 ────────→ 训练循环一个字没改

└─⑤ 考它 ───────────────→ 76%,而瞎猜只有 27%

图说:这一章真正的新东西只有 ①②③。 ④⑤ 和第 04 章一模一样。

2. 为什么不从头训:底层那些本事,谁都用得上

先看现象。 你要做一个认狗品种的模型,手上只有几千张狗照片。 从随机数开始练,头几轮它连「哪里是边、哪里是毛」都分不出来 —— 而这件事,别人早就练会了。

书给这套做法起的名字叫迁移学习: 把一个已经在大量数据上练过的网络, 拿一份小得多、和任务相关的数据接着往下练3

它为什么成立 —— 书给的理由,是这一章最要紧的一句话。 网络从训练图片里学到的东西是分层的:浅层学的是简单的纹理,越往深走, 认出来的结构越复杂(耳朵、鼻子这类)4

而猫和狗虽然有差别,共同点多得多 —— 书原样列了出来: 毛、四条腿、一张嘴、两只眼睛、一个鼻子4这些共同点不必重学一遍,直接从别人那里接过来就行。

换成文字也一样: 书说这类可复用的东西,在图像上是边缘和纹理, 在语言上是语法结构5

由此换来四样好处5:

好处书怎么说
省算力巨量的算力已经花在原来那次训练上了,你不用再花一遍
收敛快它不是从随机权重起步,而是从一个已经练好的状态起步,所以更少的轮次就够
省数据从零练要大数据集,接着练通常小得多的专门数据集就够
能用得起没有这条路,大多数公司和研究者根本用不上最好的模型 —— 从头练贵得离谱
成绩

│ ╭──────── 接着别人练:起点就高,爬得也快
│ ╭───╯
│ ╭───╯ ╭──── 从随机数练:起点是零
│ ╭──╯ ╭─────╯
│╭╯ ╭─────╯
└──────────────────────→ 训练时长

图说:这是书那张对比图的形状6左端那个差距就是全部要点:一个从零开始,另一个开局就站在别人练好的地方。

第 05 章那句钩子,在这里兑现。 那一章说过:标目标检测的数据, 一个类别通常要几百张精细标注的图;而如果用别人练好的网络接着练, 每类几十张到一百张就可能够了7省下来的,正是这一节讲的那些「谁都用得上的本事」。

3. 三条路线:锁多少、放多少

先看现象: 上一节说「锁住别人的、只练自己的」。可到底锁多少?

书给了三条路线,按「放开多少」从多到少排8:

3.1 第一条:全部重练

做法: 拿别人练好的权重当起点,但所有参数都参与训练。

关键在学习率必须压到极小 —— 书给的量级是 1e-5 或更小9

为什么必须压这么小,书讲得很好: 学习率大了,那些权重会被挪得很远; 挪远了,它原本学会的通用本事就被冲掉了 —— 书用的词是「忘掉」9

什么时候用它: 你的数据集又大又杂,大到值得把所有层都调一遍, 而且调完模型不会丢掉原有的能力9

3.2 第二条:只换最后那个头(这一章的主走查用的就是它)

做法: 把前面那一大截整个冻住,只把最后负责「判类别」的那一小截换掉、重新练4

书拿「猫的分类器改成狗的分类器」讲这一条,而且讲得很清楚4:

原来的网络 改造之后
┌──────────────┐ ┌──────────────┐
│ 输出:猫的品种 │ ← 换掉这一截 → │ 输出:狗的品种 │
├──────────────┤ ├──────────────┤
│ │ │ │
│ 一大截卷积 │ ← 原样冻住 → │ 一大截卷积 │
│ │ │ │
├──────────────┤ ├──────────────┤
│ 输入层 │ │ 输入层 │
└──────────────┘ └──────────────┘

图说:被冻住的那一大截,书给了个名字叫卷积基座; 改造之后变的只有两样:喂进去的图片,和最后要判的那些类别4

3.3 第三条:先训头,再一层层往前放开

做法: 先照第二条只练最后那一截,然后从靠近输出的那一层开始,一层一层往前解冻, 接着练;放开到你想要的层数为止10

它的好处书说得准: 让模型学到新数据的专属特征, 又不至于把最前面那几层里那些通用的、深层的本事毁掉10

什么时候用它: 书的口径是 —— 第二条的结果还不够好的时候, 可以从网络末端再往回多练几层,但绝大部分网络务必保持不动4

4. 「冻结」在这本书里是两件事,别搞混

这一节是我们掰开的,书从不对照。

「冻结」这个词在这本书里出现过两次,动作看起来一样,目的完全相反。

第 05 章那次这一章
冻住的是网络的全部权重网络的主干(留最后一小截不冻)
被改的是输入的那张图像本身新接上去的那一小截的权重
训完得到的是一张图一个模型
书里在哪风格迁移11特征提取4

读一遍这张表就明白它们为什么不是一回事: 第 05 章那次训完你手上没有新模型,只有一张画; 这一章训完你手上没有新图,只有一个能上线的模型。

共同点只有一个:两次都是「把梯度挡在某些东西外面」。 不同的是挡在哪儿 —— 一次挡在整个网络外面(于是梯度只能去改图), 一次挡在主干外面(于是梯度只能去改那一小截头)。

判断(我们的,不是书里的):这两处不对照,是这本书结构上的一处失手。 两个例子只隔了五章多一点,用的又是同一个词; 一个第一次读到「冻结」的人,几乎一定会以为是同一招。 点破它只要一句话。 如果错,会错在: 如果作者认为「冻结 = 不更新这部分参数」这个定义本身已经足够、 剩下的读者自己能推,那这是留白不是失手 —— 但推得出来的前提是读者记得五章前那个例子 里被更新的不是参数而是像素,而书在那一章也没有把这一点讲成一条规矩。

5. 到哪儿找模型:四道筛子

先看现象: 公开平台上的模型多到数不清。凭什么挑?

书给的第一步不是筛,是「先认路」 —— 它建议花时间把平台上按任务分的那些大类看一遍12理由书用一句谚语说了:手里只有一把锤子的人,看什么都像钉子12

认完路之后,四道筛子13:

筛子怎么用
① 按任务大类收窄先判断你的问题属于哪一类。书举的例子:要把图里的东西连轮廓一起标出来,那属于「视觉」这个大类下的「生成掩码」这一档
② 按参数量收窄你未必有一块很强的显卡 —— 参数多的模型跑不动
③ 按许可证收窄不是所有公开模型都允许商用。 要用于商业用途,模型的许可证必须允许
④ 看模型说明页剩下的数量可控之后,逐个看说明

第 ③ 道最容易被跳过,而它是唯一会带来法律后果的一道。 「许可证」是模型作者附在模型上的一份使用条款,规定别人能拿它干什么、不能干什么 —— 书举的可商用许可证例子是 Apache 2.013

第 ④ 道那个「模型说明页」是使用一个模型的起点,书列了它该写清三件事14:

  1. 这个模型表现如何;
  2. 该怎么把它用起来;
  3. 它基于哪一篇论文。

书还提了一个很实用的细节:同一个模型常常有好几档大小 —— 书举的例子是同一个模型的 tiny / small / large / huge 四档。 通常越大越准,但也吃掉多得多的资源15。 另外很多模型页上能直接试跑 —— 输一段文字或传一张图,当场看结果14

6. 主走查:把一个认一千种东西的网络,改成认六种垃圾

下面每个数都来自书。

第 ① 步,选底座。 一个叫 DenseNet-121 的很深的卷积网络。 它的特点是每一层都直接连到下一层,让信息流动最大化; 它是在一份超过 100 万张图、分成 1000 个类别的图像库上练出来的1

第 ② 步,认识自己的数据。 六类垃圾:纸板、玻璃、金属、纸、塑料、其他; 总共两千三到两千五百张图216照第 04 章那套「按类别分文件夹」的方式加载,统一缩放到 224×22417

第 ③ 步,切三份。 六成训练、两成验证、两成测试18

第 ④ 步,加载并全部冻住。 把那个网络连权重一起加载进来, 然后把每一个参数都标成「不参与求梯度」 —— 这就是冻结19

第 ⑤ 步,换头。 这一步是整条走查的关键,值得逐格看20:

原来的最后一截: 输入 1024 个数 → 输出 1000 个数 ← 1000 个类别
↓ 整个换掉
新的最后一截: 输入 1024 个数 → 输出 6 个数 ← 6 类垃圾

图说:前面那一大截吐出来的仍然是 1024 个数,一个字没变 —— 变的只是「拿这 1024 个数去判几个类」。 这 1024 个数就是第 2 节说的那些「谁都用得上的本事」的成品。

第 ⑥ 步,配尺子。 多分类,所以用带 softmax 的那把(CrossEntropyLoss); 书特意提醒:输出层不要再手动加一次 softmax,因为那把尺子内部已经做了20。 (这正是第 03 章立下的那条规矩,这一章执行了。)

第 ⑦ 步,练。 批大小 32、学习率 0.01、10 轮;训练循环和第 04 章逐字相同21。 路标22:

训练损失验证损失
第 1 轮385.32125.90
第 10 轮328.92112.78

第 ⑧ 步,考试。 拿测试那两成图跑一遍,取每张图六个输出里最大的那个当预测23

准确率 76%24书自己算的对照(瞎猜)是 27%25

第 ⑨ 步,看它错在哪。 摆成第 03 章那种方格图看,多数类别判得很好, 但玻璃和塑料这两类之间还是会混26这很好理解 —— 透明、反光,连人有时都看错。

判断(我们的,不是书里的):第 ⑦ 步那张路标表里有一个书没提的信号 —— 这一次训练几乎没怎么练动。 十轮下来训练损失从 385.32 掉到 328.92,只掉了不到 15%(准确说是 14.6%); 而第 04 章那个从零训的小网络,损失是成倍往下掉的。 我们认为原因在学习率:0.01 配 Adam,对「只训一个新接上去的分类头」来说偏大, 每一步挪得太远,损失就在一个水平线上来回晃。 书自己讲全量重练时说过要用 1e-5 量级(那一段在本章第 3.1 节)—— 那条建议管的是「重练别人的权重」,和这里的新头不是一回事,所以这不算书自相矛盾; 但书对这个几乎没动的损失曲线只评了一句「训练和验证损失都降下来了, 练久一点还能更好」27,没有去看那个 14.6%。 如果错,会错在: 如果那个损失值是「整个轮次所有批次相加」而不是平均 (代码里确实是相加),那么绝对值大是正常的,但降幅仍然只有 14.6% —— 这一条不受影响。真正可能推翻它的是:如果这份数据本身就有大量互相冲突的标注 (比如「其他」这一类本来就没有清晰边界),那么损失降不下去是数据的问题,不是学习率的问题。 判据摆在那儿:把学习率降到 1e-3 重跑一次,一试便知。

判断(我们的,不是书里的):那个 27% 的对照,不是「在整个测试集上瞎猜」的成绩。 书算这个对照时,把那个「永远猜最多的那一类」的假模型放进了按批次的循环里, 每一批都重新拟合一次25。 于是它其实是「在每一小批 32 张图里各自找出最多的那一类,再猜那一类」—— 这比真正的瞎猜占便宜(因为它偷看了每一批的标签分布), 也可能比真正的瞎猜吃亏(因为小批次里的多数类不稳定)。 不管偏哪边,它都不是书想表达的那个东西。 如果错,会错在: 如果六个类别的数量本来就很接近、而且每一批都足够大, 那么两种算法的结果会几乎相同,这条批评就无关痛痒。 判据是:六类各有两千三到两千五百张里的一部分,类别不算特别不平衡, 所以偏差多半不大 —— 但方法本身仍然是错的,而第 03 章立的规矩正是「必须和瞎猜比一次」。

7. 另起一处:一个 2.7 亿参数的小模型,两轮学会分垃圾邮件

这一处和主走查不是同一条流水线 —— 换了数据、换了模型、换了整套工具。 它存在的理由只有一个:证明这一套不只适用于图像。

先说这个模型有多小。 书用的是一个小语言模型,最小档只有 2.7 亿个可调的数28

书自己给了参照:那些旗舰模型的参数量是它的一千倍。 书点名的是 GPT —— 那一族模型的名字 —— 的第 5 代,以及另一家的旗舰28

那三个字母各取自一个词:生成式 —— 指它会自己往外吐新内容,而不是只判一个类别; 预训练 —— 也就是第 2 节那件「先在大数据上练一遍」; 以及第 11 章那套结构的名字。(这一句拆解是我们补的,书没有解释过这三个字母。)

「小语言模型」这个说法书当场解释了:它通常是从一个大模型「派生」出来的, 派生的办法叫蒸馏28 —— 让小模型去学大模型的输出,把大模型的本事「熬」进小模型里。 (「蒸馏」这个词书只给了名字,没有展开,上面那半句解释是我们补的。)

走一遍:

  1. 数据: 垃圾邮件识别,训练约 8200 条、测试约 2700 条,每条是一段文字加一个标签29;
  2. 先查平衡: 书特意去数了一下 —— 4125 条是垃圾、4050 条不是,50.5% 对 49.5%, 几乎完全平衡30这一步很值得学: 书说本来预期垃圾邮件数据会很不平衡(「至少我的收件箱是这样」), 结果一数发现不是 —— 先数一遍,别猜;
  3. 切词: 把文字交给和这个模型配套的切词器,统一补齐到 512 个 token,超了就截断31;
  4. 练: 用 AdamW、学习率 0.001、批大小 8、只练 2 轮32;
  5. 考: 准确率 95.6%,而多数类占比只有 50.5%33

这个对照比主走查那次干净得多: 数据几乎完全平衡,所以「瞎猜」就是 50%; 95.6% 对 50.5%,领先 45 个百分点,这个模型确实学到了东西。

书还给了一条很实在的硬件提醒: 练语言模型比这本书里任何其他训练都吃算力得多, 建议至少有一块 8 GB 的显卡 —— 这里的 8 GB 说的是 显存 —— 显卡上自带的那块内存,模型和这一批数据都得装得进去; 没有的话,去用云端提供的免费显卡34

判断(我们的,不是书里的):这一节加载模型用的类,可能和它要加载的权重对不上。 书用的是第一代 Gemma 的那两个类去加载第三代的模型权重35。 而在这个库里,第三代有自己专用的类 —— 我们在库的源码里核到了 Gemma3ForSequenceClassification 这个类的定义36用旧代的类去加载新代的权重,轻则报警告,重则直接加载失败。 如果错,会错在: 如果这个库做了向后兼容、让旧类也能读新代的配置,那么书里这段照抄能跑; 我们没有实际跑过这段代码,所以只说「可能」判据是能查的:那个专用类的定义就在源码里,行号已给出。

8. 书里的立场与证据

书里给了证据的:

  • 76% 与 27% 的对照 —— 真跑出来的数(但 27% 那个的算法有问题,见第 6 节末的判断块);
  • 玻璃和塑料互混 —— 有方格图为证;
  • 95.6% 与 50.5% —— 真跑出来的数,而且先数了一遍类别分布再下结论;
  • 训练损失与验证损失的十轮路标 —— 原样印出来了(书自己没读出里面的信号)。

作者的经验判断(书里没给证据):

  • 「全量重练用 1e-5 或更小」 —— 一个经验量级,没有对照实验9;
  • 「越大的模型通常表现越好」 —— 定性说法15;
  • 「大部分网络务必保持不动」 —— 经验规矩,没有说「大部分」是多少4

书里没交代来历的: 主走查那个网络出自哪一年、哪一篇,全书一字未提; 它练用的那份图像库同样只有名字。这一章仍然是零文献。

书里过时的写法: 加载那个网络时用的 pretrained=True, 这个参数从 torchvision 0.13(2022)起已经改成 weights= —— 第 04 章已经提过一次,这一章又出现了一遍19。 照抄能跑,但会收到一条弃用(这个写法以后会被删掉)警告。

9. 边界与局限

这本书对的地方先说清: 这一章的**「为什么成立」讲得是全书最好的之一** —— 猫狗共享「毛、四条腿、两只眼睛」那个例子,一句话就把迁移学习的道理说透了。 三条路线的分档也很实用,而且每条都给了适用条件。 第 7 节那次「先数一遍类别分布,别猜」更是好习惯的示范。

但有四处要当心:

  1. 损失几乎没降,书没读出来 —— 见第 6 节末的第一个判断块;
  2. 那个 27% 的对照算法有问题 —— 见第 6 节末的第二个判断块;
  3. 加载语言模型用的类可能对不上代 —— 见第 7 节末的判断块;
  4. pretrained=True 已过时 —— 见第 8 节末。

这一章没覆盖的:

  • 书在前言里许诺过的那一类省钱微调法,正文一次都没出现。 这是全书唯一一处许诺落空。 前言说这一章会讲「只调很小一部分参数就能把现成模型 改造到自己任务上」的那类做法(它有个名字叫参数高效微调,常见的一种叫 LoRA), 而我们在全书搜过:这两个名字只在前言出现过,正文零命中37;
  • 第三条路线(一层层往前解冻)只有描述,没有代码。 三条路线里只有第二条给了实现;
  • 怎么判断「该锁多少层」没有可操作的判据。 书只说「数据集大而杂就全练」, 大到什么程度、杂到什么程度,没有数;
  • 微调之后怎么确认它没有把原来的本事忘掉,没有讲。 第 3.1 节提了「忘掉」这个风险, 但全章没有任何一处去测它;
  • 两次微调都没有和「不用迁移学习、从零练同一份数据」比过。 这一章从头到尾没有那条对照曲线 —— 书那张成绩对比图是示意图,不是实测。

10. 可带走的

主走查一行写完: DenseNet-121(在 100 万张图、1000 类上练过)→ 全部权重冻住 → 把最后那一截从「1024 进、1000 出」换成「1024 进、6 出」→ 配 CrossEntropyLoss(不再手动加 softmax) → 两千三到两千五百张垃圾照片、六二二切分、批 32、学习率 0.01、10 轮 → 76%,书给的对照 27%;玻璃和塑料互混。

  1. 前面十一章都从随机数起步,这一章从别人练好的地方起步 —— 这就是迁移学习;
  2. 它成立的理由:网络浅层学的是边缘和纹理这类通用的东西,深层才学具体的部件;
  3. 猫和狗的共同点(毛、四条腿、两只眼睛)远多于差别 —— 这一句就是全章的道理;
  4. 换成文字也一样:那些可复用的东西在语言上是语法结构;
  5. 它换来四样:省算力、收敛快、省数据、以及「用得起」;
  6. 三条路线:全部重练 / 只换最后那个头 / 先训头再一层层往前放开;
  7. 全部重练时学习率必须压到 1e-5 量级,否则原有的通用本事会被冲掉;
  8. 「冻结」在这本书里是两件事 —— 第 05 章冻全部、改的是图;这一章冻主干、改的是头;
  9. 换头只换「拿这 1024 个数去判几个类」,前面那一大截吐出来的东西一个字没变;
  10. 选模型四道筛子:任务大类 → 参数量 → 许可证 → 模型说明页;
  11. 许可证那一道是唯一带法律后果的 —— 不是所有公开模型都能商用;
  12. 同一个模型常有好几档大小,越大通常越准也越吃资源;
  13. 一个 2.7 亿参数的小模型,2 轮就学会了分垃圾邮件(95.6% 对 50.5%);
  14. 小语言模型多半是从大模型蒸馏出来的;
  15. 「先数一遍类别分布,别猜」 —— 书本来以为垃圾邮件数据不平衡,一数发现几乎五五开;
  16. 书在前言许诺的那类省钱微调法,正文一次都没出现 —— 全书唯一一处许诺落空。

11. 原文地图

主题原书章原文位置
迁移学习的定义Chapter 10text/12-ch10-chapter-10.txt:10(搜「transfer learning, which is a technique」) · text/12-ch10-chapter-10.txt:78(搜「further trained for a specific new task」)
为什么成立:分层特征与猫狗共同点Chapter 10text/12-ch10-chapter-10.txt:164(搜「simple textures」) · text/12-ch10-chapter-10.txt:166(搜「fur, four legs」)
四样好处与那张对比图Chapter 10text/12-ch10-chapter-10.txt:99(搜「starts without knowledge」) · text/12-ch10-chapter-10.txt:107(搜「fine-tuning requires less data」) · text/12-ch10-chapter-10.txt:113(搜「would not be able to use the best models」)
三条路线Chapter 10text/12-ch10-chapter-10.txt:119(搜「different approaches to transfer learning」) · text/12-ch10-chapter-10.txt:127(搜「very low learning rate」) · text/12-ch10-chapter-10.txt:169(搜「convolutional bases」) · text/12-ch10-chapter-10.txt:180(搜「thaw the next layers」)
选模型的四道筛子Chapter 10text/12-ch10-chapter-10.txt:32(搜「if the only tool you have is a hammer」) · text/12-ch10-chapter-10.txt:45(搜「limit the number of parameters」) · text/12-ch10-chapter-10.txt:51(搜「Another important filter is the license」) · text/12-ch10-chapter-10.txt:56(搜「available in different sizes」)
模型说明页Chapter 10text/12-ch10-chapter-10.txt:61(搜「model card is the starting point」)
底座网络与图像库规模Chapter 10text/12-ch10-chapter-10.txt:186(搜「Densenet-121」) · text/12-ch10-chapter-10.txt:189(搜「1 million images」)
垃圾数据集与六个类别Chapter 10text/12-ch10-chapter-10.txt:202(搜「2,300 to 2,500」) · text/12-ch10-chapter-10.txt:312(搜「cardboard」)
预处理与切分Chapter 10text/12-ch10-chapter-10.txt:264(搜「Resize((224, 224))」) · text/12-ch10-chapter-10.txt:277(搜「60% for training」)
冻结与换头Chapter 10text/12-ch10-chapter-10.txt:319(搜「freeze」) · text/12-ch10-chapter-10.txt:335(搜「original model predicted 1,000 classes」)
超参数与训练路标Chapter 10text/12-ch10-chapter-10.txt:254(搜「LEARNING_RATE = 0.01」) · text/12-ch10-chapter-10.txt:390(搜「Epoch: 0, Loss: 385」)
成绩与对照Chapter 10text/12-ch10-chapter-10.txt:445(搜「percentage of correctly predicted classes」) · text/12-ch10-chapter-10.txt:452(搜「compare the value with a dummy classifier」) · text/12-ch10-chapter-10.txt:441(搜「glass and plastic」)
勘误 对照按批次重新拟合Chapter 10text/12-ch10-chapter-10.txt:460(搜「dummy_clf.fit(X_batch」)
小语言模型与蒸馏Chapter 10text/12-ch10-chapter-10.txt:481(搜「small language models」) · text/12-ch10-chapter-10.txt:484(搜「270 million parameters」)
垃圾邮件数据与平衡性Chapter 10text/12-ch10-chapter-10.txt:486(搜「8,200 text examples」) · text/12-ch10-chapter-10.txt:577(搜「50.5% of the data」)
切词、训练与成绩Chapter 10text/12-ch10-chapter-10.txt:586(搜「512 tokens」) · text/12-ch10-chapter-10.txt:536(搜「EPOCHS = 2」) · text/12-ch10-chapter-10.txt:700(搜「95.6%」)
硬件提醒Chapter 10text/12-ch10-chapter-10.txt:505(搜「at least 8 GB」)
勘误 用旧代的类加载新代权重Chapter 10text/12-ch10-chapter-10.txt:549(搜「gemma-3-270m-it」)
勘误 前言许诺的省钱微调法Prefacetext/02-fm-preface.txt:72(搜「parameter-efficient」)

Footnotes

  1. 出处:「Chapter 10」第 185-189 段(text/12-ch10-chapter-10.txt:186,搜「Densenet-121」与 text/12-ch10-chapter-10.txt:189,搜「1 million images」)。原文:这个例子里用一个预训练网络当起点,再拿一份专门的数据集训练它;用的模型是 DenseNet-121,一个非常深的卷积网络,它通过稠密连接把每一层直接连到下一层,以最大化信息的流动;这个网络是在 ImageNet 上训练的,那是训练图像分类模型最著名的基础之一,由超过 100 万张图、分成 1000 个不同的物体类别组成。 2

  2. 出处:「Chapter 10」第 202-205 段(text/12-ch10-chapter-10.txt:202,搜「2,300 to 2,500」)。原文:我们拿这个模型当起点,训练它去识别不同类别的垃圾;数据集在 Kaggle 上,包含 2300 到 2500 张图、来自六个不同类别:塑料、金属、玻璃、纸板、纸、其他。 2

  3. 出处:「Chapter 10」第 9-12 段(text/12-ch10-chapter-10.txt:10,搜「transfer learning, which is a technique」)与第 77-79 段(text/12-ch10-chapter-10.txt:78,搜「further trained for a specific new task」)。原文:迁移学习是一种把预训练模型在一个任务上学到的知识转移到新任务上的技术;这个过程里,预训练网络的大部分被冻住,只有最后几层拿新数据训练;微调是迁移学习的一种特殊形式 —— 我们为新任务训练预训练模型的部分或全部层。另一处的定义:迁移学习是把一个已经在大量数据上预训练过的神经网络,用一份更小的、与任务相关的数据集继续训练以适配某个新任务的过程。

  4. 出处:「Chapter 10」第 133-173 段(text/12-ch10-chapter-10.txt:164,搜「simple textures」、text/12-ch10-chapter-10.txt:166,搜「fur, four legs」、text/12-ch10-chapter-10.txt:169,搜「convolutional bases」)。原文:图 10.5 用一个训练来分猫的模型、要改成认狗的例子讲特征提取式微调;为什么这行得通?网络从训练图像里学到不同层次的信息 —— 它从简单的纹理开始,越往网络深处走,认出的结构越复杂(比如耳朵、鼻子等等);尽管猫和狗无疑有差别,但它们的相似之处多得多:毛、四条腿、一张嘴、两只眼睛、一个鼻子;微调后的模型不必从头重学这些相似之处,直接从预训练模型采纳即可。在卷积网络里,这些被冻住的网络权重与层被称为卷积基座;微调后的网络里改变的是喂进输入层的图像,以及狗品种这个目标的规模。原文还说:如果结果仍不满意,可以从网络末端往回再训练几层 —— 但绝对应当让网络的大部分保持不变。 2 3 4 5 6 7 8

  5. 出处:「Chapter 10」第 104-115 段(text/12-ch10-chapter-10.txt:107,搜「fine-tuning requires less data」与 text/12-ch10-chapter-10.txt:113,搜「would not be able to use the best models」)。原文:迁移学习所需的算力和能耗远少于从零训练;这意味着模型收敛更快,因为它从一个已经训练好的状态起步、而不是从随机权重起步,因此可以用更少的轮次完成训练。另一个要点是微调需要更少的数据 —— 从零训练需要大数据集,而微调通常用小得多的专门数据集就够,因为预训练网络已经从原始数据里学会识别许多通用特征并能复用它们;在图像处理里这可能是识别边缘或纹理,在语言处理里可能是识别语法结构。还有很实际的考虑:没有迁移学习,大多数公司和研究者根本用不上最好的模型,因为训练它们已经贵得让人望而却步。 2

  6. 出处:「Chapter 10」第 85-103 段(text/12-ch10-chapter-10.txt:99,搜「starts without knowledge」)。原文:从零训练的模型(图中实线)一开始没有任何知识,因此起步阶段表现不出任何能力;而带着先验知识起步的模型(图中虚线)从一个更高的水平开始;后者所需的算力显著更少,因为巨量算力已经花在原始模型的训练上了。这张图是示意图,没有坐标刻度,也不是实测曲线。

  7. 出处:「Chapter 4」第 1461-1476 段(text/06-ch04-chapter-4.txt:1461,搜「almost always use a pretrained network」与 text/06-ch04-chapter-4.txt:1476,搜「few hundred well-annotated images」)。原文:我们几乎总是应当为目标检测使用一个预训练网络 —— 它已经「见过」数百万张图,现在只需要学会检测那些特定物体;用了预训练,每类几十张到 100 张图就可能足够;而不借助预训练时,每个类别通常需要几百张标注良好的图。

  8. 出处:「Chapter 10」第 118-123 段(text/12-ch10-chapter-10.txt:119,搜「different approaches to transfer learning」)。原文:迁移学习有不同的做法,从基于预训练网络训练完整模型和它的全部参数,到只训练一小部分参数、并在冻住的权重之上使用大量模型特征;如果后一种做法效果不够,可以渐进地解冻各层。

  9. 出处:「Chapter 10」第 125-131 段(text/12-ch10-chapter-10.txt:127,搜「very low learning rate」)。原文:这种方法里我们为新的具体问题训练预训练模型的全部参数;通常我们用一个非常低的学习率(例如 1E-5 或更小),意思是只对原本学到的权重做极小的调整,以免模型「忘掉」那些通用知识;这种做法适合你的数据集足够大、足够多样,大到值得对所有层做有意义的调整而模型又不会丢掉它最初的能力。 2 3 4

  10. 出处:「Chapter 10」第 177-183 段(text/12-ch10-chapter-10.txt:180,搜「thaw the next layers」)。原文:这是一种把冻结与全量微调结合起来的分步方法 —— 先像特征提取那样只训练模型的最后一部分(分类层),其余保持冻住;然后从最靠近输出层的那几层开始,一层一层解冻,继续训练;一步步做下去,直到放开我们想训练的层数为止;这种做法让模型学到新数据集的专属特征,又不至于冒着毁掉最前面几层里那些深层通用特征的风险。 2

  11. 出处:「Chapter 4」第 2195 段(text/06-ch04-chapter-4.txt:2195,搜「weights are frozen and the target value」)。原文:在风格迁移里,权重被冻住,而被优化的目标变成了图像本身。这与本章「冻主干、训新头」的做法在动作上相似、在被改的东西上正好相反,而书从不对照这两处。

  12. 出处:「Chapter 10」第 23-34 段(text/12-ch10-chapter-10.txt:32,搜「if the only tool you have is a hammer」)。原文:一旦一个网络训练完成、可以直接使用,我们就称它为预训练网络;有一个活跃的社区在分享这类训练好的网络,让我们不必总是重新发明轮子;最有名的平台是 Hugging Face。作者建议花时间通读平台上按职责划分的那些领域,并引了一句老话:如果你手上唯一的工具是锤子,就很容易把所有东西都当成钉子 —— 你需要的是一个不止一件工具的工具箱。 2

  13. 出处:「Chapter 10」第 35-57 段(text/12-ch10-chapter-10.txt:45,搜「limit the number of parameters」、text/12-ch10-chapter-10.txt:51,搜「Another important filter is the license」)。原文:你可以按「描述你要解决的问题的那个大类」来收窄模型范围;熟悉了平台上的任务类型之后,你就会知道那个问题属于「计算机视觉」这个大类下的「生成掩码」这一档;但剩下的模型仍然太多,所以可以限制参数量 —— 因为你手头未必有一块极强的显卡。另一个重要的筛选条件是许可证:并不是平台上列出的所有模型都对所有用途授权 —— 比如你要商用,模型的许可证必须允许这样做,可以筛选 Apache 2.0 之类再看看该模型的许可证是否允许你的用例。 2

  14. 出处:「Chapter 10」第 58-70 段(text/12-ch10-chapter-10.txt:61,搜「model card is the starting point」)。原文:模型说明页是使用一个模型的起点,它包含以下信息 —— 这个模型表现如何、该怎么实现它、它基于哪一篇科学论文。原文还说很多模型可以直接推理:对语言模型输入文字、对图像模型输入图片,执行推理拿到结果,这有助于评估模型的运作与输出;也可以在文件与版本页里查看要下载的模型有多大。 2

  15. 出处:「Chapter 10」第 55-57 段(text/12-ch10-chapter-10.txt:56,搜「available in different sizes」)。原文:你还会注意到某些模型有不同的尺寸档位(书举的例子是同一系列的 tiny、small、large、huge 四档);更大的模型通常比更小的表现更好,但也需要多得多的资源。 2

  16. 出处:「Chapter 10」第 301-314 段(text/12-ch10-chapter-10.txt:312,搜「cardboard」)。原文打印出来的类别列表:['cardboard', 'glass', 'metal', 'paper', 'plastic', 'trash'],而输出层的节点数就直接取自类别数。

  17. 出处:「Chapter 10」第 260-274 段(text/12-ch10-chapter-10.txt:264,搜「Resize((224, 224))」)。原文:预处理把图片统一缩放到 224×224 再转成张量,并用 ImageFolder 加载 —— 图片按类别存放在各自的子文件夹里,这个方法负责组织数据集对象。这与第 04 章那套「按类别分文件夹」的做法完全相同。

  18. 出处:「Chapter 10」第 276-289 段(text/12-ch10-chapter-10.txt:277,搜「60% for training」)。原文:我们从整份数据里切出训练、验证、测试三份,60% 用于训练、验证和测试各 20%。

  19. 出处:「Chapter 10」第 316-328 段(text/12-ch10-chapter-10.txt:319,搜「freeze」)。原文:可以通过 models 模块的 densenet121 函数加载预训练网络,还需要传 pretrained = True 这个参数才会连权重一起加载;然后我们需要把所有模型参数「冻住」,做法是把每个参数的 requires_grad 属性设成 False。pretrained= 这个参数从 torchvision 0.13(2022)起已经改成 weights=,照抄能跑但会收到弃用警告 —— 这是我们补的,不在书里(来自通用知识)。第 04 章也提过一次同样的问题。 2

  20. 出处:「Chapter 10」第 330-341 段(text/12-ch10-chapter-10.txt:335,搜「original model predicted 1,000 classes」)。原文:当然,所有参数都冻住的话模型什么也学不到;这个模型把网络层分成 features 和 classifier 两部分,所以我们想只调整最后几层的话,直接覆盖掉 model.classifier 就行;那个全连接层要调整,是因为要识别的类别数变了 —— 原来的模型预测 1000 个类,而我们这里只有 6 个类;另外不应该再用 softmax 去激活输出以得到各类概率,因为 nn.CrossEntropyLoss 内部已经做了这一步。代码里新的那一截是「输入 1024、输出 6」。 2

  21. 出处:「Chapter 10」第 251-258 段(text/12-ch10-chapter-10.txt:254,搜「LEARNING_RATE = 0.01」)与第 346-352 段(text/12-ch10-chapter-10.txt:347,搜「CrossEntropyLoss and Adam」)。超参数:批大小 32、学习率 0.01、10 轮;损失函数与优化器用的是 CrossEntropyLoss 和 Adam,书说这里「没有意外」。

  22. 出处:「Chapter 10」第 388-393 段(text/12-ch10-chapter-10.txt:390,搜「Epoch: 0, Loss: 385」)。原文打印的两行:第 0 轮训练损失 385.32334792613983、验证损失 125.89920091629028;第 9 轮训练损失 328.9187126159668、验证损失 112.78194999694824。从 385.32 到 328.92,降幅约 14.6% —— 这个百分比是我们算的。

  23. 出处:「Chapter 10」第 400-417 段(text/12-ch10-chapter-10.txt:403,搜「provides logits of which we need to find the index」)。原文:评估需要测试数据上的预测,模型给出的是 logits,我们需要用 np.argmax 找出最大值的下标来取出预测类别。「logits」这个词第 03 章讲过:输出层没有被压成 0 到 1 的原始分数。

  24. 出处:「Chapter 10」第 445-450 段(text/12-ch10-chapter-10.txt:445,搜「percentage of correctly predicted classes」)。原文:整体看起来不错,这可以从准确率(也就是被正确预测的类别所占的百分比)看出来 —— 算出来是 76%。

  25. 出处:「Chapter 10」第 452-471 段(text/12-ch10-chapter-10.txt:452,搜「compare the value with a dummy classifier」与 text/12-ch10-chapter-10.txt:460,搜「dummy_clf.fit(X_batch」)。原文:不过只有把这个值和一个代表纯粹瞎猜的假分类器比较,我们才能给它定性;书创建了这个模型,算出准确率是 27%。但代码里 dummy_clf.fit(X_batch, y_batch) 写在按批次的循环内部,也就是每一批都重新拟合一次「永远猜多数类」这条策略。 2

  26. 出处:「Chapter 10」第 439-443 段(text/12-ch10-chapter-10.txt:441,搜「glass and plastic」)。原文:混淆矩阵显示,大多数类别都预测得很好(格子颜色很深),不过模型在区分玻璃和塑料时还有一些弱点。

  27. 出处:「Chapter 10」第 397-398 段(text/12-ch10-chapter-10.txt:397,搜「longer training could」)与第 473-474 段(text/12-ch10-chapter-10.txt:473,搜「trained a usable model in a very short time」)。原文:这次训练降低了训练损失和验证损失,不过练久一点结果还能更好;我们因此可以说,在很短时间内训出了一个可用的模型,因为我们从一个非常好的模型起步、再通过微调把它适配到了新任务上。

  28. 出处:「Chapter 10」第 479-485 段(text/12-ch10-chapter-10.txt:481,搜「small language models」与 text/12-ch10-chapter-10.txt:484,搜「270 million parameters」)。原文:这一节我们用一个小语言模型并为特定任务训练它;所谓小语言模型,通常是从一个大语言模型派生出来的,派生的过程叫蒸馏;这里用的模型是 Gemma-3,它的特点是参数极少 —— 最小的版本只需要 2.7 亿个参数,比 GPT-5、Gemini-2.5 Pro 这类重量级少了一千倍。「蒸馏就是让小模型去学大模型的输出」这半句解释书里没有,是我们补的(来自通用知识)。 2 3

  29. 出处:「Chapter 10」第 486-497 段(text/12-ch10-chapter-10.txt:486,搜「8,200 text examples」)。原文:我们现在训练这个小模型去区分垃圾邮件和非垃圾邮件;数据集在 Kaggle 上,训练集含将近 8200 条文本样例、测试集 2700 条,每一条都有一段文字和相应的标签。

  30. 出处:「Chapter 10」第 574-583 段(text/12-ch10-chapter-10.txt:577,搜「50.5% of the data」)。原文:拿到一份垃圾邮件数据,你可能会以为它很不平衡 —— 非垃圾邮件远多于垃圾邮件,至少我的收件箱是这样;我们可以数一下 0 和 1 各有多少来检查这一点,结果显示 50.5% 的数据被标为垃圾邮件。打印结果是 Counter({1: 4125, 0: 4050}),所以这份数据几乎是完美平衡的。

  31. 出处:「Chapter 10」第 584-593 段(text/12-ch10-chapter-10.txt:586,搜「512 tokens」)。原文:必须把数据集转成 token,做法是把文本特征传给切词器实例;还必须把文本序列补齐到同一长度,超过 512 个 token 的会被截断。

  32. 出处:「Chapter 10」第 532-541 段(text/12-ch10-chapter-10.txt:536,搜「EPOCHS = 2」)与第 626-642 段(text/12-ch10-chapter-10.txt:632,搜「AdamW」)。超参数:2 轮、批大小 8、学习率 0.001;损失函数是 CrossEntropyLoss、优化器是 AdamW。原文还说这次训练非常吃算力,光是两轮就要相当长的时间。

  33. 出处:「Chapter 10」第 694-706 段(text/12-ch10-chapter-10.txt:700,搜「95.6%」)。原文:准确率是 95.6%,而提醒一句,这份数据里占多数的那一类只占刚过 50%;因此我们可以对这个模型感到满意,它既可靠又高效。

  34. 出处:「Chapter 10」第 502-508 段(text/12-ch10-chapter-10.txt:505,搜「at least 8 GB」)。原文的提示框:训练语言模型比这本书里讲过的任何其他训练都吃算力得多,只有当你有一块至少 8 GB 的显卡时,做这里描述的训练才有意义;本地机器没有这样的配置的话,建议在云上训练(例如用 Google Colab),那里可以免费用到显卡。

  35. 出处:「Chapter 10」第 511-512 段(text/12-ch10-chapter-10.txt:511,搜「GemmaForSequenceClassification and GemmaTokenizer」)与第 544-554 段(text/12-ch10-chapter-10.txt:549,搜「gemma-3-270m-it」)。原文用的两个类是 GemmaForSequenceClassificationGemmaTokenizer(第一代 Gemma 的类),加载的模型名是 google/gemma-3-270m-it(第三代的权重)。

  36. 补充(不在书里,依据我们的 frontier 书架):这个库里第三代有自己专用的分类类。依据: shelf=ai-frontier-reference/transformers@src:src/transformers/models/gemma3/modeling_gemma3.py:1101 事实=源码里定义了 class Gemma3ForSequenceClassification,并把它列进了该模块的导出清单。我们没有实际运行书里那段代码,所以判断块里写的是「可能对不上」而不是「一定跑不通」。

  37. 出处:「前言」第 72 段(text/02-fm-preface.txt:72,搜「parameter-efficient」)。原文在介绍第 10 章时说,这一章会涉及参数高效微调。而我们在全书搜过:PEFT 只在前言出现过这一次,LoRA 全书零命中,第 10 章正文里一处都没有。