阶段 2 · 看懂图像

自监督:把数据本身
变成它的标签

上一章《ViT 视觉 Transformer》把图片切块喂给注意力,靠的却是几亿张人工标注。 这一章讲一个更狠的思路:互联网上有几十亿张图,只是没有标签—— 那就想办法让图自己当自己的标签。

1

瓶颈:标注是这条线的天花板

对照项监督学习自监督学习
需要什么人工标注的标签 只要原始数据,标签从数据里自己造
数据量上限受限于你能标多少 互联网上有多少就能用多少
成本ImageNet 花了约两年、近 5 万名标注员 爬数据 + 显卡,不需要人
学到的针对那个任务的判别能力 通用的表示,换个任务还能用

自监督的做法是人为地在数据里挖一个洞,然后让模型把它填上。 这个洞的答案本来就在数据里——所以不需要人来标。 但模型为了填对这个洞,被迫学会理解数据的内在结构。 把"预测标签"换成"预测数据的一部分",这就是全部的核心 trick。

🎯 类比

像教小孩认字时用的填空练习。"小__在树上叫"——答案是"鸟",但这个答案 从句子本身就能推出来,不需要老师额外标注。
小孩做完一万道填空题,自然就学会了语法和常识——尽管从来没有人教过他"什么是主语"。

互动 · 同样干 90 天,人工标注 vs 一台爬虫

人工标注到手
—
爬虫抓到手
—
追平爬虫要多少人
—

2

三条路线:怎么造那个"洞"

路线造什么洞代表特点
生成式
Generative
遮住一部分,让模型重建它 MAE(掩码自编码器)、BEiT、GPT(预测下一个词) 直观,重建目标明确。但容易学成"抠图"—— 模型可能只学会了纹理补全,没学到语义
对比式
Contrastive
不重建,只要求"同一张图的两种变换"在表示空间里靠近 SimCLR、MoCo、CLIP 学到的表示质量最高。 代价是需要大量负样本、极大 batch
预测式 / 蒸馏式 让一个"学生"网络去预测"老师"网络的输出 BYOL、DINO、data2vec 不需要负样本,batch 可以小。但要小心"表示坍塌"

两个词后面要反复用,先记住:正样本是同一张图的另一种变换(该拉近的),负样本是别的图(该推远的)。

三条路线挖的三个"洞"

重建 abc 拉近 推远 同一张图的两种变换 别的图 学生老师 追 滑动平均挪一小步 生成式:遮住一块再重建 对比式:拉近、推远 预测式:学生追老师

互动 · 老师到底落后学生多少步

量出来的滞后(真去比)
—
(1−m) 有多小
—
老师一步能挪到学生的
—

这三条路线其实都赢了,只是在不同的地方:生成式赢了语言——GPT 的"预测下一个词"就是最成功的自监督; 对比式赢了图文对齐——CLIP 是很多多模态模型的地基; 预测式在纯视觉里也一直有人用。 它们的思想是同一个:不需要人来标,让数据自己出题。

3

对比学习:一张图的两种"样子"应该长得像

这是理解对比学习最直观的一句话: 把同一张图做两次随机增强,模型应该认为它们"是同一个东西"; 而把它和别的图放在一起,应该认为"不是同一个东西"。

互动 · 相似度矩阵与 InfoNCE 损失

👆 这一章的核心大图

上面那张相似度矩阵就是这一章的全部:每一行是一个视图,橙色格子是它该认出的"另一半",其余都是干扰项。 后面讲的温度、坍塌、五种防坍塌手段,都是在跟这张矩阵较劲。

sim 是余弦相似度——两根箭头夹角的余弦:同向时接近 1,垂直时接近 0,反向时接近 −1。 一个视图的表示记作 zi,它该认出的另一半记作 zi+; 分母里的 Σj 要对所有候选求和。

sim 就是两根箭头夹角的余弦

这一步最容易看漏的地方:N 张图进去,出来的是 2N 个东西

① N 张图 ② 每张做两次随机增强 → 2N 个视图 ③ 两两算相似度 → 2N × 2N 1a2a3a4a 1b2b3b4b 两次增强不一样,所以同 一张图的两行也不同 橙色 = 每一行唯一的正样本 标签不用人标:谁的另一半就是谁 所以 InfoNCE 就是一个 2N 分类问题
👆 先悬停,再拖那个滑块

把鼠标停在下面公式里有下划线的符号上——上面「温度 τ」和「正负样本的分离度」两个滑块会分别亮起来。 公式里的符号,就是你拖的那个控件。

⚠️ 温度 τ 是个很敏感的旋钮

softmax 之前,相似度会先除以 τ。τ 越小,最像的那一个越突出——τ = 0.1 时, 一点点的相似度差异就被放大十倍,模型被逼着非常确定地区分正负样本。
τ 太大,所有样本的权重都差不多,负样本的区分作用就消失了,模型学不到细粒度特征。
SimCLR 论文里 τ = 0.1(很低),说明对比学习需要"严格"的判别压力。 这个超参数对结果影响很大,是当初一个真正的调参难点。

4

最大的麻烦:表示坍塌

对比学习有一个极其诱人的作弊方案,而且模型真的会找到它: 如果模型把所有图片都编码成同一个向量——比如全都输出 [1, 0, 0, …]—— 那么任何两张图的相似度都是 1,正样本的相似度当然是满分。 可负样本的相似度也一起变成 1 了——softmax 把概率平摊,损失卡在 ln(2N−1) 的瞎猜水平,降不下去。模型什么都没学到。 (每个视图被编码成一个向量,这些向量所在的地方就叫表示空间。)

互动 · 坍塌长什么样

防坍塌手段怎么起作用
负样本 最直接。如果所有样本都挤在一起,负样本的相似度也会变成 1, 分母变大,损失反而升高。所以负样本天然地排斥坍塌
超大 batch SimCLR 用 4096 的 batch,就是为了让每个正样本有足够多的负样本可对比。 这是它最大的工程代价
动量编码器 + 队列 MoCo 的解法:用一个动量更新的慢编码器产生负样本, 并把它们存进一个队列。这样 batch 只要 256,队列却有 65536 个负样本
停止梯度 + 预测头 BYOL 的做法,完全不用负样本。 靠"学生预测老师、老师用学生参数的滑动平均更新"打破对称性
居中 + 锐化 DINO 的做法:居中防止某个维度主导(抗坍塌), 锐化防止输出太均匀(会引入坍塌)。两者必须同时用,缺一个就崩

BYOL 为什么不用负样本也不坍塌?如果学生和老师一模一样、又都只求"两边输出一样", 最省事的解就是都输出同一个常数。让老师慢半拍(滑动平均)、学生比老师多一层预测头, 两边就不再完全对称,这个偷懒解不再是最省事的。停止梯度是指老师那一边不往回传梯度。
DINO 用的是另一对反向的力:居中把每个维度的均值拉回 0,防某一维独大; 锐化让输出别太均匀。两者必须同时用,缺一个就崩。

投影头是接在编码器后面的一个小网络,损失在它的输出上算。 它替编码器吸收掉只对这个出题游戏有用的信息——所以训完就扔掉,下游只用编码器(SimCLR 发现这样下游更好)。

💡 为什么说"自监督比监督学习更难"

监督学习里,标签是外部给的、固定的,模型没有作弊空间。
自监督里,目标是自己定的——所以你一旦把目标设得不够严谨, 模型就会找到那个"最低成本满足目标"的退化解,也就是坍塌。
设计一个好的自监督任务,比设计网络结构难得多。

5

从 SimCLR 到 CLIP

互动 · 自监督方法进化时间轴

方法核心机制解决了什么
SimCLR 2020 大批量 + 强增强 + 投影头 证明了对比学习可以追平监督学习。但需要 4096 的 batch
MoCo 2019 动量编码器 + 负样本队列 小 batch 下也有竞争力,把对比学习从大厂门槛变成了小实验室也能做的
BYOL 2020 不用负样本,学生预测老师 推翻了"必须有负样本"的共识。但为什么不坍塌,至今仍在研究
DINO(自监督) 2021 自蒸馏(老师和学生来自同一个网络)+ 居中锐化 注意力图自己就浮现出了物体轮廓—— 完全不用标注,也不做分割任务,模型却学会了"哪里是物体"。这是当年最惊人的发现之一
MAE(掩码自编码器) 2021 遮住 75% 的图块,重建 训练效率极高——只对可见的 25% 做编码, 比对比学习快 3 倍以上。成了 ViT 预训练的标准方法
CLIP 2021 4 亿对图文对比学习 零样本分类(zero-shot transfer)——给一个新类别的名字就能认,不需要该类的训练样本。 它的图像编码器成了很多多模态模型的标准部件

CLIP 把对比学习的两端换成了一张图和它配的那句话:正样本是配对的图文,负样本是同一批里别的图文。 损失还是这套 InfoNCE,只是两边一边是图、一边是文字。

互动 · 这条谱系的真正分水岭:负样本从哪来

SimCLR:batch 内能凑出
—
MoCo:队列里固定有
—
要凑到 65536,batch 得开到
—

M

数学 · 一行 softmax,就是整个 InfoNCE

第 3 节那个损失函数只有一个动作:在一排"有多像"里,给"自己"那一项算出一个概率。 下面这张图把这一步摊开——左半边进、右半边出,三个数字全部真算。

数学节 · 一行损失怎么算(拖两个滑块,每一步都跟着变)

正样本的相似度 sim(z, z⁺)
—
认出自己的概率 p⁺
—
损失 L = −ln p⁺
—

互动 · 每个符号管图上的哪一块(卡片下面那张画的是「分子只要一项、分母要全部」)

🎯 用「点名」理解这一行

老师手里有一张全班名单。点名时他要回答的只有一个问题: "在所有人里,我敢不敢保证站起来的是这个人?"
分子 = 这个人自己有多像他;分母 = 全班所有人"像他"的程度加起来。
所以这个损失不关心"像不像",它只关心"他敢不敢保证"—— 这也正是温度 τ 那么要紧的原因:它决定这场点名有多严。

🎬 自己验一遍

把「温度 τ」从 0.1 拖到 0.5 再拖回来:左半边那一排相似度一个数字都没变, 变的只有右半边的概率形状。这就是第 3 节说的"τ 是个很敏感的旋钮"—— 它不改数据,只改判罚的严不严。
再回头看第 3 节那张相似度矩阵:上面这张图是它的一个小例子——那里每行有 7 个候选, 这里简化成 6 个。一行变成一个损失,2N 行取平均,就是这一章从头到尾在做的事。

6

自监督不便宜

成本具体表现什么时候真的会痛 → 换什么
算力比监督学习贵 SimCLR 要一整个 TPU(Google 的训练芯片)集群——4096 的 batch 至少要 32 块 TPU v3。MoCo 的存在意义就是把门槛降下来 只有一两张卡、还要快速迭代 → 先用现成的预训练模型微调;一定要自己预训练,就选 MoCo 这类小 batch 的做法
没有统一的好坏标准 监督学习看准确率就行。自监督的"预训练质量"只能在下游任务上试—— 线性探测、微调、KNN,三个指标经常给出不一致的排名。 所以你没法在预训练阶段就知道哪个方法更好 要在一堆方法里选型 → 固定一种下游协议(通常线性探测),别拿不同协议的数字横着比
学到的表示有偏 增强策略里有"颜色抖动",模型就会忽略颜色—— 这在"区分香蕉和柠檬"的任务上是灾难。增强策略隐含了"什么是不重要的"这个假设, 而这个假设会写进表示里。任何自监督方法都带着一条这样的 归纳偏置,只是它平时藏在一个叫 augmentation 的函数里。 下游任务依赖被抖掉的那个属性(颜色、方向、尺度)→ 改增强策略,或直接换成监督预训练
对超参极其敏感 温度 τ、增强强度、投影头维度、学习率—— 任何一项设置不当都会显著影响结果。复现别人的自监督结果通常比监督学习更难 换了数据或规模 → 得重新扫一遍 τ 和增强强度;照抄别人的配置通常不灵
数据里的偏见会被放大 自监督学的是"数据里有什么"。 数据里如果 90% 的医生是男性,学到的表示就会把"医生"和"男性"绑在一起—— 而且没有任何标签能让你发现这件事 数据本身有系统性偏见 → 先查数据构成,再决定要不要自监督;没有标签能替你兜底

三个量各一句:线性探测把编码器冻住、只训最后一层线性分类器;微调是整个网络接着训; KNN 干脆不训练,直接按表示找最近的邻居投票。它们经常给出不一致的排名—— 线性探测只看表示能不能被一刀切开,微调还能顺手把表示改掉,量的不是同一件事。

互动 · 那张相似度矩阵,比模型本身还大

相似度矩阵元素数
—
按 fp32 存下来
—
ResNet-50 主干参数
2350 万

互动 · 你写进增强策略里的那句话,模型会当真的

7

小结

自监督听起来像一句工程口诀("没有标签就自己造"),但它其实站在七条线里的 一条上——而且这条线在这一章露出了一条很锋利的边界。

它对应哪条线 ④ 学习即压缩——学到一个"表示",就是把数据里与身份无关的变化全部丢掉。
一句话 这一章的做法,本质上是在用「认出自己」这个任务,逼模型把一张图里所有 "不是这张图的本质"的东西压缩掉:翻转、裁剪、调色之后的它还得是它, 所以这些变化必须被扔掉,留下的才是"这张图是谁"。
它牺牲了什么 牺牲了"什么该丢"的那个裁判。监督学习里标签告诉你哪些差别重要; 自监督里这个判断由你自己写的增强策略决定——而它可能丢掉你真正需要的信息 (增强里塞了颜色抖动,模型就真的不认颜色了,回扣「什么被牺牲了」这条暗线)。
💡 检验一下:你现在能指着哪个互动说这句话

回到第 4 节那张图(标题是「坍塌长什么样」)。 把「表示的分散程度」这个滑块一路拖到 0——8 个点会全部挤到圆心, 两两平均相似度升到接近 1。

那个瞬间你看到的就是「压缩过头」:模型把每张图的信息都压没了, 只剩下一个所有输入都一样的向量——你再也分不出第 3 张和第 7 张。 所以"压缩"和"压缩过头"之间没有一条公式能替你划线。 第 4 节那张表里的五种手段,都是在替你守这条线。

这一章整件事,就是在这条轴上找一个没人能替你划的位置

下游性能 最好的位置在这附近,但没有公式替你划 压缩不足:变化也留着 丢掉变化,留下身份 压缩过头 = 坍塌 − 左侧的一切 —— 负样本 · 大 batch · 动量队列 · 停止梯度 · 居中锐化 —— 都是替你守这条线的装置 +

它在暗线里站在哪

暗线这一章的回答
信息流动 数据形状:一张图 [3,224,224] → 编码器 → 表示 [2048] → 投影头 → [128]; 和别的章不同的一步是 batch 翻倍:N 张图各做两次增强 → [2N, 128] → 相似度矩阵 [2N, 2N] → 一个标量损失。
唯一留下来的东西是编码器,那个相似度矩阵算完就扔
什么被牺牲了 牺牲了目标函数的客观性。监督学习的损失是数据给的,你改不了; 自监督的损失是你编的——编错了没有报错,只有坍塌。 另外还牺牲了可评估性:预训练完看不出好坏,只能拿到下游任务上试, 而线性探测 / 微调 / KNN 经常给出互相矛盾的排名
参数账本 ResNet-50 主干 23.5M 参数,外面再挂一个投影头 (2048→2048→128,约 4.5M)——投影头训完就扔,不传给下游。
batch 4096 → 两个视图共 8192 个样本 → 一张 8192×8192 的相似度矩阵 (约 6700 万个浮点数)。MoCo 反过来:batch 只要 256, 但维护一个 65536 个负样本的队列。
图文对比的规模:CLIP 用了 4 亿对图文
它假设了什么 假设"增强之后的东西语义不变"——翻转、裁剪、调色不改变"这是什么"。 这是对世界的一个断言,不是数学结论。
它还假设"不同图之间应该有区别"——这一条更隐蔽,但它就是负样本的来源。 两个假设只要有一个不成立(比如你要辨认的是"同一件商品的哪个颜色"), 学到的东西就是错的
违背了哪个直觉 "损失降下来了就学到了"——错的。坍塌会卡住损失:所有表示挤成一团, 负样本也成了满分,损失卡住降不下去。
第二个反直觉:训练时做的事(认出自己的另一个视图)可以和你想要的能力 (识别物体种类)毫无关系,但它仍然有用。 代理任务和下游任务之间没有逻辑联系,只有统计联系
🎯 前后钩子

它接住了上一章《ViT 视觉 Transformer》的什么:那一章 把图片切块喂给注意力,代价是海量人工标注。这一章把标签来源换掉—— 增强不再只是训练技巧,它直接定义了"什么是本质"。

它给下一章留了什么:自监督解决了"没有标签",但它连"怎么切数据"都还没问。 文字进来之前,得先切成模型认得的单位——这就是 《分词与子词》要回答的问题。

一句话带走进自监督

自监督 = 把数据本身变成标签,用法是"挖个洞让模型填"。 三条路线:生成式(重建)、对比式(拉近正样本、推远负样本)、预测式(学生猜老师)。
对比学习的核心是 InfoNCE——本质上是"从一堆候选里认出自己"的分类问题, 温度 τ 控制判别压力。
最大的坑是表示坍塌:模型把所有东西编码成同一个向量,损失卡在 ln(2N−1) 的瞎猜水平,降不下去。 防它的手段有负样本、大 batch、动量队列、停止梯度、居中锐化。
它比监督学习更难设计,因为目标是自己定的—— 你一旦没把目标定严,模型就会找到那个最偷懒的退化解。

8

拓展阅读

上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。

📄 这一章的说法从哪来

💻 工业界怎么写

∑ 更严格的形式