← 阅读室全部精读正在排版公式与图表…
PAPER ANALYZER · P26 · 共同基础

SimCLR:用两种观察方式学习同一张图像的稳定表示

学术型精读 · 概念、公式、实验、源码与可验收练习

Ting Chen、Simon Kornblith、Mohammad Norouzi、Geoffrey Hinton · ICML 2020 · 论文 · 官方代码 383d4143fd8c

一句话总结

SimCLR 将同一图像的两种增强视图作为正例,用对比目标学习表示;真正关键的是增强定义、投影头、归一化与评价协议,而不是仅记住“拉近正样本、推远负样本”。

先说明它没有使用什么标签

SimCLR 研究视觉表示的自监督学习。训练时不知道图像属于猫、汽车还是某种情绪,而是知道两张经过随机变换的图来自同一原图。这个配对关系构成监督信号。模型学习的不是一个固定类别分类器,而是可以供后续线性分类或微调使用的图像表示。

Figure 2 是最简洁的计算图:同一张图分别随机增强,经过共享编码器与投影头,再计算对比损失。共享意味着两条路径使用同一组参数,不是各自训练一个完全独立的网络。每次增强是独立采样,即使原图相同,两次裁剪、颜色扰动和模糊也可能不同。

如果只让所有视图彼此接近,模型可能把全部图像映射成同一个向量。SimCLR 同时把批次中其他图像的视图作为负例,使表示必须保留能够区分样本的信息。这个目标避免简单坍塌,但不自动等于按语义类别聚类;同类的不同照片也可能被当作负例。

数据增强实际上定义了学习问题

随机裁剪产生不同视野,颜色扰动减少仅依赖颜色统计的捷径,模糊进一步改变局部外观。Figure 3 展示裁剪可形成局部对全局或相邻区域的关系。模型被要求在这些变化下仍识别同一个来源,因此增强告诉模型“哪些变化应被忽略”,不是无关紧要的预处理。

Figure 5 的组合实验说明,单独一种增强往往不如合理组合。若只使用随机裁剪,两个视图可能共享颜色分布,模型可依赖容易的线索完成任务;加入强颜色扰动使这种捷径不再可靠,迫使模型利用更稳定的结构。这里的解释是基于实验与作者分析,不等于每个数据集都应使用同样强度。

对于情绪图像,增强必须经过标签语义检查。过大的裁剪可能去掉嘴角或眼部,水平翻转可能改变某些侧向信息,颜色与光照变化也可能破坏特定任务的线索。一个对对象识别有益的增强,不保证对微表情或细粒度情绪有益。先人工看增强后的样本,比直接照抄参数更重要。

两个视图都来自同一原图,而不是选择两张同类图片作为正例。后一种选择需要类别标签或另外的相似性规则,属于不同训练设计。做研究时要明确正负样本如何构造,因为对比损失名称相同并不意味着学习任务相同;样本关系才决定了哪些信息被保留或消除。

编码器输出与投影头输出要分开

编码器通常为残差网络,对增强图像得到表示 h。随后一个小型非线性投影头把 h 映射为 z,在 z 空间计算对比损失。下游线性评价使用 h,并移除投影头。初学者如果直接拿最后投影向量作为默认特征,可能得到与论文不同的结果,也错过了这篇论文重要的设计结论。

为什么增加一个最后丢弃的模块反而有用?对比目标要求对增强变化保持不变,而某些变化信息对下游任务仍然有价值。投影头可在 z 中适应对比目标,同时让 h 保留更丰富的信息。Figure 8 与 Table 3 提供支持:某些变换信息在 h 中仍可被预测,在投影后更弱。

这不是严格保证编码器永远保留所有有用信息,而是特定实验中的观察。投影头形式、输出维度、归一化与任务都会影响结果。原始 SimCLR 使用两层非线性头,当前官方仓库包含 SimCLRv2 的更深可配置投影头;默认层数三不能直接称为原始论文的两层设置。

把对比损失逐项读清楚

一个批次有 N 张原图,增强后共二 N 个视图。对其中一个视图作为锚点,另一个同源视图是唯一正例,其余二 N 减二个视图为负例。分母排除锚点自身,却包含正例。若把正例也从分母删除,或把同一个视图自身作为正确答案,就改变了损失定义。

相似度使用归一化后向量的点积,即余弦相似度,再除以温度。较小温度让高相似度候选获得更大权重,也会更强调难负例。温度不是越小越好;Table 5 显示对比任务准确率更高时,下游线性准确率反而可能更低,说明把预训练任务做得极端容易或极端尖锐并不等于更好的通用表示。

每一对正例计算两个方向:第一视图找第二视图,第二视图找第一视图。最后在全部原图与方向上平均。实现可能先对两个方向各自求平均再相加,因此与论文平均形式存在一个固定尺度因子;它影响损失数值与梯度尺度,读代码时应核对而不是只比较打印值大小。

批量越大,当前批次提供的负例越多。论文使用大批量训练并配合 LARS 优化与学习率调度。不能在单张显卡上简单把批量大幅缩小、其他设置不动,然后将效果差完全归因于理论无效。小批量教学实验可以验证机制,但需要明确其训练预算与原文大规模结果不同。

评价表示必须使用新的协议

线性探测冻结编码器,只训练一个线性分类层,用来检查表示是否便于分离目标类别。微调则更新部分或全部编码器,利用更多下游适应能力。两者回答不同问题,不能混成一张不标注监督方式的排名表。Figure 1 的主结果主要讨论线性评价,低标签实验又使用不同协议。

Table 6 的 76.5 顶一准确率属于加宽四倍的残差网络,不是普通宽度的 ResNet-50;普通宽度对应 69.3。模型宽度、训练轮数与批量都应与数字一起记录。若只摘出最高值说“一个简单五十层网络达到这个结果”,就隐藏了重要的计算条件。

Table 1 的增强消融使用相应的较短训练配置,因此其数值不能直接与长训练主结果相减。实验表的作用是比较同一配置内的设计选择,而不是拼出一个跨设置的累计提升。Figure 9 对批量与训练时长的分析也说明,某些条件可以通过更长训练部分补偿,但并非所有规模差异都可忽略。

Table 3 检查表示对变换信息的保留,例如旋转预测在编码器表示中明显高于在投影表示中。这支持投影头隔离部分训练目标需求的解释。不过,预测到某种变换信息不等于这些信息一定有利于情绪任务;应继续通过你自己的下游对照确认。

局限、迁移与研究判断

作者在附录讨论迁移结果与统计检验,并指出其检验没有完整覆盖训练随机性的影响。附录中普通宽度模型微调在多个任务上仍不如监督预训练,不能把宽模型或某些任务的优势概括为所有下游任务普遍获胜。保留不利结果,才能正确判断方法的适用范围。

独立判断还包括假负例和增强不变性风险。两张不同人的同类情绪图像在预训练中可能互为负例,模型会被鼓励区分它们;若区分依据恰好是身份或背景,未必有利于情绪泛化。原始方法没有直接使用情绪类别定义正例,所以不能假定预训练目标与最终情绪分类目标完全一致。

细粒度方向可以从增强强度与局部区域开始:比较全脸弱增强、包含关键区域的裁剪以及过强裁剪,观察哪类细微表情受损。跨场景方向可以检查模型对光照、背景和设备变化的不变性是否有益。每个增强都对应一个假设,而不是为了增加实验数量随意组合。

如果你使用现成预训练模型,首先完成冻结特征与监督预训练特征的同协议比较,再决定是否进行自监督重训。大规模预训练成本很高,初学者更容易通过清楚的数据划分、增强审查和错误分析得到可靠结论。一个规模小但机制可解释的实验,比一个配置不明的大训练更适合作为研究起点。

官方仓库同时服务多个版本,必须记录实际配置,尤其是投影层数、所选表示层、训练阶段和权重来源。本文引用的核心损失代码可核对归一化与正负关系,但并不将仓库当前所有默认值都等同于二零二零年论文。未执行原始训练,不宣称已经复现其最终 ImageNet 指标。

公式逐步读:变量、运算与适用范围

教学整理:两个独立视图

$$\widetilde x_i=t(x),\quad \widetilde x_j=t^{\prime}(x),\quad t,t^{\prime}\sim\mathcal T$$

两次变换独立采样,来源图像相同。增强集合 T 定义要求模型忽略哪些变化。

原文未编号定义:表示与投影

$$h_i=f(\widetilde x_i),\quad z_i=g(h_i)$$

h 用于下游评价,z 用于对比训练。原文主要使用非线性两层投影头,不能与仓库后续版本默认层数混淆。

原文式 (1):NT-Xent

$$\ell_{i,j}=-\log\frac{\exp(\operatorname{sim}(z_i,z_j)/\tau)}{\sum_{k=1}^{2N}\mathbf1_{k\ne i}\exp(\operatorname{sim}(z_i,z_k)/\tau)}$$

分母排除自身但保留正例,二 N 减二个剩余视图为负例。温度 τ 与归一化共同控制比较尺度。

Algorithm 1 的教学合写:双向平均

$$L=\frac1{2N}\sum_{k=1}^{N}\left[\ell_{2k-1,2k}+\ell_{2k,2k-1}\right]$$

每对两个方向都参与,不能只保留一半锚点而不说明。代码采用方向损失相加时需要核对固定尺度差异。

教学整理:线性评价

$$\widehat y=\operatorname{softmax}(Wh+b),\quad f\ \text{保持冻结}$$

只更新 W 与 b,验证的是表示的线性可分性。这不是原文新增编号公式,而是对评价协议的显式表示。

实验读数:先固定协议,再比较数值

原文 Table 6:ImageNet 线性评价,模型宽度不同
编码器宽度Top-1Top-5
ResNet-50 标准宽度69.389.0
ResNet-50 两倍宽度74.292.0
ResNet-50 四倍宽度76.593.2
原文 Table 5:温度、归一化与下游结果,百分比
设置对比任务准确率线性评价
归一化,温度 0.0590.559.7
归一化,温度 0.187.864.4
归一化,温度 0.568.260.7
归一化,温度 1.059.158.0
无归一化,温度 10092.157.0

计算流程图

flowchart LR
A[Original image] --> B[Random view one]
A --> C[Random view two]
B --> D[Shared encoder f]
C --> D
D --> E[Representation h]
E --> F[Projection g and normalization]
F --> G[Batch contrastive loss]
E --> H[Frozen linear evaluation]

沿图逐条检查箭头:每个箭头传递的是张量或监督信号,并不代表额外的数据集;训练目标旁的分支在部署时未必保留。建议先在纸上填入批大小、序列长度、通道数,再阅读下面的源码。一个模块即使名字相同,只要输入轴、掩码或输出使用方式改变,也不能直接视作同一个实验。

论文方法与固定版本源码对照

objective.py:75–86

  logits_aa = tf.matmul(hidden1, hidden1_large, transpose_b=True) / temperature
  logits_aa = logits_aa - masks * LARGE_NUM
  logits_bb = tf.matmul(hidden2, hidden2_large, transpose_b=True) / temperature
  logits_bb = logits_bb - masks * LARGE_NUM
  logits_ab = tf.matmul(hidden1, hidden2_large, transpose_b=True) / temperature
  logits_ba = tf.matmul(hidden2, hidden1_large, transpose_b=True) / temperature

  loss_a = tf.losses.softmax_cross_entropy(
      labels, tf.concat([logits_ab, logits_aa], 1), weights=weights)
  loss_b = tf.losses.softmax_cross_entropy(
      labels, tf.concat([logits_ba, logits_bb], 1), weights=weights)
  loss = loss_a + loss_b

同视图分支的自相似项被大数掩码去除,跨视图分支含正确配对;两个方向分别计算交叉熵再相加。相加与论文双向平均相差固定尺度,不能只凭损失值大小判断实现优劣。

model_util.py:154–166

    elif FLAGS.proj_head_mode == 'nonlinear':
      for j in range(FLAGS.num_proj_layers):
        if j != FLAGS.num_proj_layers - 1:
          # for the middle layers, use bias and relu for the output.
          dim, bias_relu = mid_dim, True
        else:
          # for the final layer, neither bias nor relu is used.
          dim, bias_relu = FLAGS.proj_out_dim, False
        hiddens = linear_layer(
            hiddens, is_training, dim,
            use_bias=bias_relu, use_bn=True, name='nl_%d'%j)
        hiddens = tf.nn.relu(hiddens) if bias_relu else hiddens
        hiddens_list.append(hiddens)

非线性投影头按配置创建多个层;当前仓库可包含 SimCLRv2 配置,run.py 中默认投影层数为三。原始论文的两层设置需要显式选择并记录。

代码核查固定在提交 383d4143fd8cf7879ae10f1046a9baeb753ff438。这里展示的是公开仓库的实际文件,不把重新写的教学代码冒充作者实现。仓库后续可能包含新版本、工程兼容选项和不同默认参数;本文只将已核实的语句对应到论文机制。下载权重成功、模型能够前向传播、复现论文最终指标是三个不同的验收层级。

从读懂到能够独立实现:可执行学习任务

第一步,为二十张代表性情绪图片各生成两种增强视图,保存网格并逐一检查眼部、嘴部与整体姿态是否还可辨认。验收:列出至少三种可能破坏标签含义的增强情况,给出保留或减弱增强的理由,而不是仅凭训练速度决定参数。

第二步,用三张原图构造六个归一化向量,手工写出六乘六相似度矩阵。验收:每个锚点恰有一个正例、四个负例,自身不进入分母;能分别计算两个方向并与向量化代码核对。

第三步,固定向量只改变温度,观察概率分布与损失。验收:说明排序通常不因共同正缩放改变,而梯度权重会变化;不要把预训练配对准确率提高直接写成下游表示改善。

第四步,在小数据上比较编码器表示 h 与投影表示 z 的冻结线性评价。验收:使用相同训练划分、正则化选择与测试集,明确维度不同带来的分类器参数变化,并保留不支持预期的结果。

第五步,仅选择一个跨场景因素,例如光照变化,比较两套增强策略。验收:分别报告源域与目标域的宏平均 F1 与各类召回,记录增强样本及随机种子;确认趋势后再扩大训练,不需要一开始追求原文大批量指标。

建立可检查的实验记录

开始第一轮实验前,建立四份小文件:数据清单记录样本编号、来源、标签与划分;配置文件记录预处理、随机种子、模型名称和冻结范围;结果表记录验证指标、选中轮次与最后测试指标;错误清单保存预测错误的样本编号及观察理由。这些文件比一张最高准确率截图更能说明你真正控制了实验条件,也能让后续细粒度或跨场景拓展沿用同一条证据链。

对视频、语音或多模态情绪数据,必须优先检查主体、会话和视频来源是否跨集合重复。同一原始视频切出的多个片段高度相关,随机按片段划分可能让模型记住说话人、背景或录制设备。跨场景问题至少要明确源域训练集、源域验证集和目标域测试集;若使用目标域标签选择提示词或超参数,就不应再把它描述为完全未见目标域的泛化结果。

为避免把实现错误误认为研究发现,先运行一个极小批次,打印输入输出形状、数值范围、有效长度以及损失是否有限。随后在少量训练样本上尝试拟合,验证模型确实能够更新指定参数。如果极小训练集都学不会,优先检查标签编码、掩码方向、归一化、学习率和冻结设置;此时直接扩大数据量通常只会延长排查时间,而不能证明模型本身不适合任务。

消融实验一次只改变一个关键因素,其他预处理、划分、优化预算和选择规则保持一致。第一轮以发现实现问题为目标,只用一个种子;确认代码与趋势合理之后,再增加多个种子并保留每次独立结果。均值用于概括趋势,标准差用于展示训练波动,但都不能替代对样本泄漏和评价口径的检查。不同论文中的最优数字不能在协议不明时直接相减。

解释实验失败时,先区分三层原因:实现层是否正确地执行了计算;优化层是否在给定预算内学到了信号;数据层是否提供了任务需要的信息。比如文本缺少反讽语调、静态图像看不到表情变化、音频包含录音噪声,这些问题不能仅靠增加网络深度解决。把失败样本分组后再提出修改,每项修改应能对应一个可观察的问题和一个预先规定的验证指标。

学习笔记采用“论文本身说了什么—源码实际做了什么—我在本地验证了什么”三栏记录。第一栏附页码或图表编号,第二栏附固定提交与行号,第三栏附命令、环境和输出。本文已完成原文及源码核对,未宣称在你的机器上重训原论文。下面的练习属于待执行计划;只有真正运行并保存结果后,才能把相应项目改为“已完成”。

短引语与阅读定位

原文短语 A Simple Framework(标题):简单指框架组成,不意味着完整训练预算很小。

原文短语 nonlinear transformation(摘要):投影头让对比空间与下游表示空间有所分工。

原文短语 composition of data augmentations(摘要):增强组合决定了自监督任务要求保留的稳定信息。

参考资料与核验边界

论文摘要与版本信息;完整论文 PDF;作者公开仓库固定版本。公式中标注“教学整理”的表达用于显式说明原文的计算步骤,不声称具有原文公式编号。所有实验数字均指原论文报告结果,不是本次新训练得到的结果。英文短引语合计不超过二十五个词。

自己的解释与验收记录

写出一条输入到输出的链路、一个关键公式的含义,以及你完成的最小检查。笔记仅保存在当前浏览器,可从主站「我的学习笔记」导出。