# CLS 05 · 对比学习:视图、投影与历史字典 按问题继续 InfoNCE概率与梯度、h/z、温度、队列陈旧性、实测与评价协议 对应课堂(13 页) 可先阅读已有结果,再决定是否运行。重算时请核对各节记录的数据、参数、环境与日期。 **学习路径:** [视图、投影头与历史字典](/course/study/contrastive-views.html) [P08同源视图](/course/pages/l3-r2-p08.html) → [P12投影头](/course/pages/l3-r2-p12.html) → [P17一次队列更新](/course/pages/l3-r2-p17.html) 先把一张图的两种观察放入同一候选表,算出正例概率;再追踪梯度怎样经过z回到h,以及旧key为什么需要缓慢变化的编码器。[温度的概率与梯度算例](/course/blocks/temperature-ranking-probability-gradient.html)、[队列身份](/course/blocks/moco-key-queue-identity.html)都可以独立引用。 动手只选一个入口:想检查增强留下什么,选[LAB 06](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/7c4f531113d7473abc174e2e014e1340);想追踪真实key、FIFO和EMA,选[LAB 07](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/0d1b8f6fbf6a476c93ffcc169f2ec1f4)。读完用一张图或一段trace指出输入、候选和两种参数更新,再用独立读出评价它是否对任务有用。后文同时保留论文迁移进展和小型实验的失败结果,二者的数据与协议分别写明。 拍同一只杯子,改变光照、裁剪和背景,类别仍然是杯子。若能把这些变化视为同一对象的不同观察,训练目标就可以来自图像自身:两次观察的表示应该接近,其他图像的表示提供区分参照。但如果下一项任务是分辨红杯和蓝杯,“改变颜色仍然算同一个”就不再无害。**对比学习的正例关系,是设计者通过数据和增强作出的任务假设。** 它不是无标签数据自动告诉我们的普遍相同性。 ## 从两张视图到一个可微分的选择题 给原图 $x$ 独立采样增强 $t,t'$,得到 $v=t(x),v^+=t'(x)$。编码器 $f_\theta$ 产生表示 $h=f_\theta(v)$;投影头 $g_\phi$ 产生 $z=g_\phi(h)$,通常再做 $\ell_2$ 归一化。余弦相似度便是单位向量点积 $s(q,k)=q^Tk$。正例 key 来自同一原图另一视图,候选负例来自其他原图。 对一个 query $q$、一个正例 $k^+$ 和若干负例 $k_j^-$,写出 InfoNCE 形式: $L_q=-\log\frac{\exp(s(q,k^+)/\tau)}{\exp(s(q,k^+)/\tau)+\sum_j\exp(s(q,k_j^-)/\tau)}.$ 这里 $\tau>0$ 是温度,分母包含正例。它把“拉近正例、推开负例”写成在当前候选集合里选中正例的交叉熵。候选身份来自采样过程,不是人工类别;两张不同原图可能都是杯子,所以负例并不保证语义类别不同。实例区分与类别聚合之间存在真实张力。 SimCLR 的一个 batch 有 $N$ 张原图,生成 $2N$ 个视图。对其中任一视图,排除自身,余下 $2N-1$ 项中有一个正例和 $2N-2$ 个负例。自身相似度通常接近 1,若误把它留进分母,就额外加入一个不可避免的强竞争者。损失平均两个方向:视图 A 找 B,B 也找 A。可核对 [SimCLR §2、式 1 与 Algorithm 1](https://proceedings.mlr.press/v119/chen20j/chen20j.pdf)。 ## 温度改变竞争强度,不改变这组相似度的排序 固定三项相似度:正例 0.8,两个负例 0.4、0.2。直接代入上式得到: | 温度 $\tau$ | 正例概率 | 负例 0.4 的概率 | 负例 0.2 的概率 | 损失 $-\log p_+$ | | --- | --- | --- | --- | --- | | 1.0 | 0.4506 | 0.3021 | 0.2473 | 0.7971 | | 0.5 | 0.5713 | 0.2567 | 0.1721 | 0.5599 | | 0.1 | 0.9796 | 0.0179 | 0.0024 | 0.0206 | 因为正例已经领先,低温度放大它的优势。若把正例改成 0.3、最强负例仍为 0.4,低温度则会更强地惩罚错误排序。不能仅因降低温度使这张表的损失变小,就宣称表示更好了。 梯度把这个现象写得更精确。令 $p_j$ 为候选 softmax 概率,则 $\frac{\partial L}{\partial s_+}=\frac{p_+-1}{\tau},\qquad \frac{\partial L}{\partial s_j^-}=\frac{p_j}{\tau}.$ 温度既出现在 $1/\tau$ 中,也改变 $p$。所以“温度越低,所有梯度越大”不成立:本例正例梯度的绝对值在 $\tau=0.5$ 时约 0.8575,在 0.1 时反而约 0.2037,因为预测已饱和。最相似负例会获得更多概率和更强排斥,但过度强调困难负例也可能放大假负例或噪声。 ![同一相似度的温度变化与 MoCo 队列更新](/course/repair/assets/cls06-temperature-queue.svg) 上半图按表中真实计算值画出候选概率;下半图是长度 6 的 FIFO 队列,加入两个新 key 后移出两个最老 key。温度控制一次比较,队列控制比较对象从哪里来。 ## 为什么损失作用在 z,迁移却常读 h 假设 $h=(u,c)$,$u$ 编码形状,$c$ 编码颜色。若增强经常改变颜色,两个视图可能有相同 $u$、不同 $c$。直接要求整个 $h$ 相同,会压制颜色差异;增加投影头以后,$g(h)=u$ 这样的映射可以在 $z$ 中满足不变性,而 $h$ 仍可能留下颜色。这是一个**可行性构造**,不是声称真实网络一定学成两根独立坐标。 损失计算在 $z$ 不代表编码器没学:链式法则给出 $\partial L/\partial\theta=(\partial L/\partial z)(\partial z/\partial h)(\partial h/\partial\theta)$。梯度穿过投影头更新编码器。SimCLR 通过实验发现非线性投影头有益,并把投影前表示用于下游;这支持区分目标空间与读出空间,不能推广成“h 永远保留全部被增强抹掉的信息”。图像已经被转成灰度时,该视图根本不含原颜色;若所有训练视图都删掉颜色,表示也没有从这些输入恢复真实颜色的依据。 在 [LAB 06](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/7c4f531113d7473abc174e2e014e1340?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=7c4f531113d7473abc174e2e014e1340&utm_term=get_notebook) 中,应同时检查颜色/形状任务、增强设置和 $h/z$ 读出。最有解释力的比较是:同一原图划分、相同模型容量与读出预算,只改变颜色增强;再看形状读出和颜色读出是否朝不同方向变化。不能用颜色损失下降代替形状泛化,也不能把随机二维向量当作实际训练出的特征。 [此段独立阅读](/course/notebook-blocks/a7a8f9c43bc64c6e8609e87186f7cb77.html) ## 队列解决候选数量,EMA 缓和特征坐标系漂移 当前 batch 较小时,每个 query 可比较的负例有限。MoCo 把近期 batch 的 key 特征保存为队列,下一批仍可使用,因而字典大小不完全受当前 batch 限制。长度 6 的队列从 `[a,b,c,d,e,f]` 加入 `[g,h]` 后成为 `[c,d,e,f,g,h]`。里面存的是先前编码好的向量;它不保存那些图片的完整计算图,也不在每一步重算所有旧向量。 这节省了候选编码计算,却产生一致性问题。若编码器每步剧烈变化,昨天向量的某个方向和今天向量的同一方向可能不再表达类似内容。MoCo 使用 query 编码器参数 $\theta_q$ 做正常梯度更新,key 编码器则采用参数指数移动平均: $\theta_k\leftarrow m\theta_k+(1-m)\theta_q.$ 取 $m=0.9$,旧 $\theta_k=(0,2)$,当前 $\theta_q=(2,4)$,新 key 参数是 $(0.2,2.2)$。若下一步 query 仍相同,新 key 为 $(0.38,2.38)$。平均的是**网络参数**,不是队列向量,也不是 Adam 的梯度动量;旧 key 不会因这一步 EMA 自动刷新。$m=0$ 令 key 立即跟随 query,$m=1$ 则把 key 冻结。较慢变化让历史 key 更可比,但不能消除全部陈旧性。[MoCo §3 与 Algorithm 1](https://arxiv.org/html/1911.05722v3) 给出队列、动量编码器和停止 key 分支梯度的配合。 | 组织方式 | 候选从哪里来 | 是否保留旧特征 | 主要计算取舍 | | --- | --- | --- | --- | | SimCLR 批内比较 | 当前 batch 的两视图 | 不需要队列 | 更多候选通常要求更大 batch 及其通信/激活 | | MoCo 字典 | 当前正例与历史 key 队列 | 是 | 候选数与 batch 部分解耦,需控制 key 漂移 | 这是计算组织的不同答案,不是一个方法必然取代另一个。扩大队列会让最旧特征更老;增大 batch 会改变优化与负例分布;调整温度则改变同一批候选如何竞争。做消融时不能三项同时改,再把收益全部归给 EMA。 ## 训练学会区分视图以后,还要回答哪个下游问题 冻结线性评价(linear probe)先固定编码器 $f$,仅训练 $\hat y=Wh+b$;它检验标签能否用指定线性读出从表示取得。kNN 不更新编码器,用训练集表示及标签给测试点投票,结果仍依赖距离、归一化、$k$ 与支持集。微调允许 $f$ 更新,检验的是初始化加适配方案。检测或分割则需要空间特征和任务头,整图线性分类成绩不能自动给出边界能力。 完整协议至少明确:原始样本的训练/验证/测试划分,预训练是否接触无标签测试图,冻结时的 `eval`/BatchNorm 状态,读 $h$ 还是 $z$,标签预算,验证集选超参数的方法。两视图必须在原图划分之后生成。同一原图一张裁剪放训练、另一张放测试,会把近重复泄漏包装成泛化。 ### 同一个颜色干预,真的改变了学到的表示 LAB 06 已在 2026-09-22 本地 CPU 完成真实两视图训练:600 张训练图、240 张保留图,RGB 16×16,卷积编码器输出 48 维 $h$,投影头输出 24 维 $z$,InfoNCE 温度 0.2,batch 60,Adam 学习率 0.002,固定种子 20260922、40 epoch。预训练不使用类别标签;标签只供冻结表示的 5NN 与线性读出使用。对照唯一指定变化是每个视图是否以 50% 概率交换红/蓝通道。 | 表示与训练 | 形状 5NN | 颜色 5NN | | --- | --- | --- | | 随机编码器 $h$ | 72.50% | 100.00% | | 保留颜色增强,训练后 $h$ | 47.50% | 100.00% | | 随机换色增强,训练后 $h$ | 85.83% | 49.17% | | 随机换色增强,训练后 $z$ | 95.42% | 52.92% | ![真实两视图训练与冻结读出](/assets/display/f482e1157acae587ec308bdd.webp) 保留颜色时模型可利用容易的颜色区别,形状 5NN 甚至低于随机表示;换色使这种线索不可靠,形状读出提高、颜色读出接近二类机会水平。**$h$ 也会丢失颜色,$h$ 优于 $z$ 不是保证**:本次 $z$ 的形状 5NN 反而更高。同一换色 $h$ 的线性形状读出是 98.75%,再次说明“表示质量”不能脱离读出协议。这里报告的是一个固定种子的小型受控实验,不是 SimCLR 在自然图像上的通用排名。 LAB 07 的小型 MoCo 使用同一图像来源、真实 FIFO 特征队列与 EMA key 编码器,训练 15 epoch。其 $h$ 形状 5NN 为 38.33%,低于随机基线 72.50%;损失由约 4.79 变到 4.27,也没有保证目标语义变得好读。它完成了训练机制,但给出了一个失败的表示结果。MoCo 与 LAB 06 的训练轮数和组织不同,不能据这些数作方法优劣排名;可以据此检查为什么视图目标、候选和下游形状任务不一致。 [LAB 07](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/0d1b8f6fbf6a476c93ffcc169f2ec1f4) 把队列/EMA 精确算例和图像两视图训练放在同一条学习链中。阅读训练输出时,先确认参数确实由损失更新,再比较相同协议下随机初始化与训练后表示;若小数据上的自监督结果没有领先,就讨论增强、数据量和读出限制,而不改变测试口径。 从 [CLS 04 的重建](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/23b0affc4b824723927bd0938fd2bbda) 到本册,目标从恢复像素变为识别视图关系;下一册 [CLS 06](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/c0645a4db6e04188ab5b119e87c53bed) 再问:没有显式负例时,为什么表示没有全部变成同一个常量?这些路线共同要求我们区分训练信号、实际优化以及表示的使用证据。 [此段独立阅读](/course/notebook-blocks/38813722014249e6a8ee5e14b736dca2.html) ## 研究者为什么有理由继续沿这条路线走? MoCo原论文Table 2(b)在同一Faster R-CNN、ResNet-50-C4设置下比较预训练起点: | 预训练 | box AP | AP50 | AP75 | | --- | --- | --- | --- | | ImageNet-1M 人工类别监督 | 53.5 | 81.3 | 58.8 | | ImageNet-1M MoCo | 55.9 | 81.5 | 62.6 | 两者均在VOC trainval07+12检测标注上全层微调24k次,评价为VOC test2007,取5次实验平均;AP是COCO式多IoU阈值指标,AP50/AP75是指定阈值。MoCo相对提高2.4 AP,说明视图对比学出的参数在这套下游协议下提供了有效起点。 这不是冻结模型直接会检测:检测头与主干都用检测监督适配。它也不把所有预训练和下游总算力配平。相同论文的另一种主干结构收益不同,因此结论应保留具体模型与协议。 这份研究证据和上面的LAB07失败结果并不冲突:前者是论文规模、数据与下游协议下的能力进展;后者是小型教学实现的某次表示结果。机制跑通和用途改善应分别判断。 [把一次学习走通,也读清实现顺序](/course/blocks/moco-one-step-paper-and-code.html) 对照本页图解与LAB07的步内时序;[模拟问答:旧 key 还能比较吗?](/course/blocks/moco-point-at-the-figure-dialogue.html) 提供可指认key身份的模拟问答。第一次动手只选 [LAB 06 · 颜色干预:视图、投影与读出](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/7c4f531113d7473abc174e2e014e1340?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=7c4f531113d7473abc174e2e014e1340&utm_term=get_notebook) 的颜色干预或 [LAB 07 · MoCo:历史 key、队列与两种更新](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/0d1b8f6fbf6a476c93ffcc169f2ec1f4?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=0d1b8f6fbf6a476c93ffcc169f2ec1f4&utm_term=get_notebook) 的队列路径之一,不要求两本重复训练。 [此段独立阅读](/course/notebook-blocks/aa9100c6e89d426aa1200f6c622cd2fb.html)