导读
本文将系统回顾计算机视觉领域无监督学习的经典方法,涵盖 MoCo、SimCLR、BYOL、SimSiam、SwAV、MAE 和 IPT 等代表性工作。除了阐述每篇论文的核心创新点,还会结合实验复现中的实际心得,帮助读者更直观地把握该方向的发展脉络。
前言
在 CV 无监督学习领域探索一段时间后,我将重点关注的论文加以梳理,并分享一些实验过程中的体会。本文主要聚焦图像(CV)领域的无监督学习。
无监督学习的概念并不新颖——从早期的自编码器(auto-encoder),到通过图像变换进行预训练(如预测旋转角度、遮挡复原),再到如今的对比学习(SimCLR、MoCo)、特征重构(BYOL、SimSiam)、像素重构(MAE),甚至低层视觉任务的预训练(IPT),可以说图像无监督学习已取得长足进步,效果正逐步逼近有监督学习。
不过,客观而言,截至目前,无监督学习尚未真正超越有监督学习。一个实用的场景是:利用海量无标注数据完成无监督预训练,再在特定任务的小规模标注数据上微调——这条路线确实能带来显著提升。但如果预训练数据本身带有标注,直接采用有监督训练通常效果更优。实验中多次验证过:即便先进行无监督预训练再切换为有监督,或者将两个阶段联合训练,收益也极其有限。归根结底,数据规模与标注质量才是决定性因素。
当然,无论是单模态(CV、NLP)还是多模态,日益涌现的亿级预训练数据集确实催生了强大的基础模型。但整理如此量级的数据并在其上完成训练,资源消耗惊人。大多数研究人员仍会选择加载开源的模型参数,再进行预训练或微调。
对比学习
最初的无监督思路很朴素:重构像素、预测旋转角度等,但效果始终不理想。可以说,对比学习(SimCLR、MoCo)的出现是无监督学习的一次质的飞跃,这些经典论文的思路和结论至今对其他工作仍有重要借鉴价值,相关实验也值得逐一深入。
先简单梳理一下对比学习的核心逻辑。对于原始图像 x,经过两种不同的数据增强得到 x_i 和 x_j,特征提取器 encoder 提取出的特征应彼此接近。但如果只最大化同一图像两个特征的距离,模型很容易崩溃——所有特征都坍缩到同一个点,loss 直接归零。因此对比学习引入了负样本:让来自同一张图像的特征距离尽可能近,来自不同图像的特征距离尽可能远。学术表述即:最小化正样本距离,最大化负样本距离——这便是对比学习的损失函数。

稍微解释一下损失函数:每张图经过两种变换得到两个特征,对任意特征 q,总有一个特征 k+ 是它的正样本(来自同一原图),而同一个 batch 中其他图像的特征就是负样本。提高对比学习效果的关键,研究下来无非三点:足够大的 batch size、更有效的数据增强(让两个视图既能保留本质信息又尽可能不同),以及更强的 encoder 表达能力。下面重点介绍 MoCo 和 SimCLR 这两个最具代表性的工作。
MoCo: Momentum Contrast for Unsupervised Visual Representation Learning
MoCo 的核心贡献在于:在显存有限的情况下,如何高效增加负样本数量?它设计了一个巧妙的队列机制——训练中维护一个队列,将历史 batch 的特征(这些特征不计算梯度,因此显存开销极小)存入其中。这样新 batch 进行计算时,可以从队列中取出大量负样本参与优化。但问题随之而来:不同 batch 的模型参数在持续更新,队列里的特征来自旧版本,一致性会被破坏。作者因此提出了 momentum-encoder,结构与主 encoder 相同,但更新参数时以小步长从主 encoder 复制,自身不通过 loss 学习。这样它提取的特征无需梯度,占显存小,且参数变化极其缓慢,队列中的负样本特征保持一致,保证了对比学习的效果。

A Simple Framework for Contrastive Learning of Visual Representations
SimCLR 则走了另一条路:直接加大机器投入,将 batch size 提升至 4096,从而损失函数可直接计算。它重点研究了数据增强对特征表达的影响,做了大量消融实验,最终发现组合使用 随机裁剪 + 颜色失真 + 高斯模糊 的效果最佳。此外,SimCLR 在 encoder 后增加了一层 MLP,进一步提升了效果(说实话,原因至今尚未完全明确)。模型结构如下:

后来 MoCo 借鉴了 SimCLR 的数据增强和 MLP 结构,推出了 MoCo v2,效果大幅提升——可见 SimCLR 的实验结论确实非常扎实。
最早看到 MoCo 论文时,着实觉得这个思路精妙,而且指标完全可复现。在复现 SimCLR 时尝试了另一种方案:在有限显存下模拟大 batch——小 batch 先不带梯度推理保存结果,再带梯度推理计算 loss,但需要重复推理,训练时间成倍增加。
研读这些论文,最大的价值不只是直接套用方法,还能借鉴其中的局部思路。例如 SimCLR 的数据增强和 MLP 结构,堪称同类文章的标配;MoCo 通过 momentum-encoder 和队列在小 batch 下获得大量负样本的思路,在训练 CLIP(多模态对比学习)时就能派上用场——ALBEF 等文章也采用了类似思想(当然还有别的优化点才能发表论文)。
做目标检测时还发现了 DetCo,它将 MoCo 适配到检测领域,设计了多尺度对比和局部全局对比。实验下来,DetCo 在检测任务上确实优于 MoCo。视频领域也有 VideoMoCo,不过本人并未亲自尝试。
最后分享几个实战要点。第一,在业务数据上训练 MoCo 或 SimCLR 时,由于对比损失的特点,如果数据中相似图像占比过高,务必做去重。第二,多机多卡训练时,正样本在同一卡内计算,负样本来自不同机器,当使用 ResNet 等 CNN 结构时,BN 层会带来信息泄露——MoCo 采用 shuffle BN,SimCLR 采用 sync BN。
特征重构
前面提到,直接最大化两特征距离会导致模型坍塌。但有些文章直接进行特征重构却能做到不坍缩(原理上其实尚未完全搞清楚)。这里主要介绍 BYOL 和 SimSiam。
BYOL 是实际尝试中效果最好的一个,最大亮点是训练时不需要负样本,只用正样本。

BYOL 在 SimCLR 的 MLP 投影层之后又加了一个新的 MLP 预测层,用预测结果和另一个视图的投影特征直接计算 L2 loss。其中的 target encoder 就是 MoCo 的 momentum-encoder,参数从 online encoder 更新,不参与 loss 计算。可以说 BYOL 在 MoCo v2 的基础上直接去掉了负样本对比,只在正样本投影之后再做预测来重构特征。
SimSiam 更为简洁——在 BYOL 基础上进一步去掉 momentum-encoder,只用一个 encoder。作者发现,保证模型不塌缩的关键在于target 数据的梯度不反向传播。

BYOL 和 SimSiam 都亲自尝试过,开源代码也不复杂,论文效果能够复现。但为什么 target 网络 stop gradient 就能防止坍塌,至今仍带有一丝玄学色彩。
其他思路
以下几篇文章的思路也颇具启发性,一并介绍。
SwAV:它有意思的地方在于,虽然 loss 形式上类似对比学习,但不需要负样本。具体做法是:将其中一个增强结果的特征做聚类,得到一个 one-hot 编码(相当于给图像打了一个标签),然后让另一个增强结果的特征去分类(特征与聚类中心点乘)。另一个值得借鉴的点是数据增强引入了低分辨率小图:一张图增强后得到 8 个不同 view,其中 2 个高分辨率、6 个低分辨率。View1 用分布式 Sinkhorn 算法算出 q,再与其余 7 个 view 计算 loss;View2 同理。loss 表达式和模型结构如下:

MAE:凯明大神继 MoCo 系列后的又一力作。自从 BERT、GPT 在 NLP 领域大获成功,图像领域也涌现了许多 mask 重建工作,如 IGPT、BEiT。之前也跑过类似 IGPT 的代码,结果惨不忍睹。而 MAE 思路简单、效果惊人——能将简单想法做出爆炸效果,这才是硬实力。MAE 采用 ViT 架构,先将图划分成 patch,mask 也按 patch 进行。AutoEncoder 结构一如既往:encoder + decoder,结合 ViT 和 patch 划分,整个模型结构呼之欲出。

MAE 成功的关键有两个:第一,75% 的 mask 比例。图像信息极其冗余,如果像 BERT 那样只 mask 15%,重建任务太容易,模型从邻域像素就能抄过来。75% 迫使模型真正去理解语义。第二,非对称的 encoder-decoder 结构。训练目标是拿到好的 encoder,所以 encoder 要重一些(参数多),decoder 可以很轻量且只用来重建。同时,Mask token 只在 decoder 中参与计算,不进入 encoder,因此重参数的 encoder 只处理 25% 的图像数据,轻量的 decoder 却要处理 100% 的数据——但 decoder 参数少,整体大幅加速。
IPT:这篇文章与其他思路最大的不同在于,它更关注细粒度信息,负责降噪、去雨、超分等低级视觉任务。模型设计得很巧妙:为每个任务设计独立的 head 和 tail 模块,中间层是共享参数的 Transformer 结构。预训练时,人为对原始数据加噪声、缩小等,然后复原。这篇文章在低级视觉任务上很有启发意义。

总结
以上提到的方法大多数都亲测有效。不过做无监督有个挺真实的心塞点:随着业务上标注数据越来越多,无监督预训练带来的收益越来越小。所以实际应用时,通常在项目启动阶段(手头只有少量标注)会加入无监督预训练,然后随着数据回流和标注增多,有监督训练的效果会慢慢超过。另外,这么多方法试下来,在具体业务数据上的效果差距其实没那么大——而且无监督预训练本身也需要大量数据,epoch 也更长(资源消耗也不少)。最务实的做法还是先加载各家在 ImageNet 上预训练好的开源模型,没必要从零开始训练。
