对比学习(Contrastive Learning)最近一年比较火,各路大神比如Hinton、Yann LeCun、Kaiming He及一流研究机构比如Facebook、Google、DeepMind,都投入其中并快速提出各种改进模型:Moco系列、SimCLR系列、BYOL、SwAV……,各种方法相互借鉴,又各有创新,俨然一场机器学习领域的军备竞赛。对比学习属于无监督或者自监督学习,但是目前多个模型的效果已超过了有监督模型,这样的结果很令人振奋。

我想,NLP领域的Bert模型,对于这波图像领域的对比学习热潮,是具有启发和推动作用的。我们知道,Bert预训练模型,通过MLM任务的自监督学习,充分挖掘了模型从海量无标注文本中学习通用知识的能力。而图像领域的预训练,往往是有监督的,就是用ImageNet来进行预训练,但是在下游任务中Fine-tuning的效果,跟Bert在NLP下游任务中带来的性能提升,是没法比的。

“但是,既然NLP这样做(自监督,无需标注数据)成功了,图像领域难道就不能成功吗?”我相信,追寻这个问题的答案,应该是促使很多人,从图像领域的有监督预训练,向自监督预训练转向的重要心理支撑。目前看,虽然说不太容易,但也算曙光乍现,而这道曙光,正是对比学习。

有监督预训练的典型问题,我们知道,就是标注数据总是有限的,就算ImageNet已经很大,但是很难更大,那么它的天花板就摆在那,就是有限的数据总量。NLP领域目前的经验应该是:自监督预训练使用的数据量越大,模型越复杂,那么模型能够吸收的知识越多,对下游任务效果来说越好。这可能是自从Bert出现以来,一再被反复证明的真理,如果它不是唯一的真理,那也肯定是最大的真理。图像领域如果技术想要有质的提升,可能也必须得走这条路,就是:充分使用越来越大量的无标注数据,使用越来越复杂的模型,采用自监督预训练模式,来从中吸取图像本身的先验知识分布,在下游任务中通过Fine-tuning,来把预训练过程习得的知识,迁移给并提升下游任务的效果。

那对比学习是要干什么呢?从目标来说,对比学习就是要干NLP领域类似Bert预训练的事情,也即是上面那几句话。

对比学习是自监督学习的一种,也就是说,不依赖标注数据,要从无标注图像中自己学习知识。我们知道,自监督学习其实在图像领域里已经被探索了很久了。总体而言,图像领域里的自监督可以分为两种类型:生成式自监督学习,判别式自监督学习。VAE和GAN是生成式自监督学习的两类典型方法,即它要求模型重建图像或者图像的一部分,这类型的任务难度相对比较高,要求像素级的重构,中间的图像编码必须包含很多细节信息。对比学习则是典型的判别式自监督学习,相对生成式自监督学习,对比学习的任务难度要低一些。目前,对比学习貌似处于“无明确定义、有指导原则”的状态,它的指导原则是:通过自动构造相似实例和不相似实例,要求习得一个表示学习模型,通过这个模型,使得相似的实例在投影空间中比较接近,而不相似的实例在投影空间中距离比较远。而如何构造相似实例,以及不相似实例,如何构造能够遵循上述指导原则的表示学习模型结构,以及如何防止模型坍塌(Model Collapse),这几个点是其中的关键。

备注: mode collapse是GAN的相关研究中一个被广泛关注的问题,具体来说,给定了一个z,当z发生变化的时候,对应的G(z)没有变化,那么在这个局部,GAN就发生了mode collapse,也就是不能产生不断连续变化的样本。这个现象从几何上来看,就是对应的流型在这个局部点处,沿着不同的切向量方向不再有变化。换言之,所有切向量不再彼此相互独立–某些切向量要么消失,要么相互之间变得线性相关,从而导致流型的维度在局部出现缺陷(dimension deficient)。

目前出现的对比学习方法已有很多,如果从防止模型坍塌的不同方法角度,我们可大致把现有方法划分为:基于负例的对比学习方法、基于对比聚类的方法、基于不对称网络结构的方法,以及基于冗余消除损失函数的方法。除了介绍上述几种类型的对比学习模型外,本文后面内容,还会回答下述两个问题:目前存在诸多对比学习模型,到底哪些方法效果更好?目前的对比学习模型仍然存在哪些问题?

基于负例的对比学习:以SimCLR为例

我们首先以SimCLR为例来介绍一个比较“标准”的对比学习模型,其实,在SimCLR之前已经提出不少对比学习模型,比如Moco V1出现就比SimCLR早。我们之所以首先选择SimCLR来介绍,一方面是SimCLR的效果相对它提出之前的模型,效果好得比较明显;另外一方面SimCLR采取对称结构,整体相对简洁清晰,也比较容易说清楚。而且,它奠定的结构,已成为其它对比学习模型的标准构成部分,搞明白了SimCLR,再理解其它模型,相对而言会更容易一些。

前面说过,对比学习是自监督学习,我们没有标注数据,所以需要自己构造相似数据(正例)以及不相似数据(负例),那么SimCLR如何构造正例和负例呢?

正例构造方法如上图所示。对于某张图片,我们从可能的增强操作集合 [公式] 中,随机抽取两种: t1Tt_1 \sim Tt2Tt_2 \sim T ,分别作用在原始图像上,形成两张经过增强的新图像 x1,x2\langle x_1,x_2 \rangle,两者互为正例。训练时,Batch内任意其它图像,都可做为 x1x_1x2x_2 的负例。这样,对比学习希望习得某个表示模型,它能够将图片映射到某个投影空间,并在这个空间内拉近正例的距离,推远负例距离。也就是说,迫使表示模型能够忽略表面因素,学习图像的内在一致结构信息,即学会某些类型的不变性,比如遮挡不变性、旋转不变性、颜色不变性等。SimCLR证明了,如果能够同时融合多种图像增强操作,增加对比学习模型任务难度,对于对比学习效果有明显提升作用。

有了正例和负例,接下来需要做的是:构造一个表示学习系统,通过它将训练数据投影到某个表示空间内,并采取一定的方法,使得正例距离能够比较近,负例距离比较远。在这个对比学习的指导原则下,我们来看SimCLR是如何构造表示学习系统的。

上图展示了SimCLR模型的整体结构。它由对称的上下两个分枝(Branch)构成,搞搜索、NLP和推荐的同学对这种结构应该不陌生。对,它来了,它来了,双塔模型又来了,它就是我们俗称的双塔结构。不过图像领域不这么叫,一般叫Branch,所以我们下文遵循这种惯用叫法。

我们随机从无标训练数据中取N个构成一个Batch,对于Batch里的任意图像,根据上述方法构造正例,形成两个图像增强视图:Aug1和Aug2。Aug1 和Aug2各自包含N个增强数据,并分别经过上下两个分枝,对增强图像做非线性变换,这两个分枝就是SimCLR设计出的表示学习所需的投影函数,负责将图像数据投影到某个表示空间。

因为上下分枝是对称的,所以我们仅以增强视图Aug1所经过的上分枝来介绍投影过程。Aug1首先经过特征编码器Encoder(一般采用ResNet做为模型结构,这里以函数 fθ(x)f_{\theta}(x)代表),经CNN转换成对应的特征表示 hih_i。紧随其后,是另外一个非线性变换结构Projector(由[FC->BN->ReLU->FC]两层MLP构成,这里以函数 gθ()g_{\theta}(\cdot)代表),进一步将特征表示 hih_i 映射成另外一个空间里的向量 ziz_i。这样,增强图像经过 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 两次非线性变换,就将增强图像投影到了表示空间,下分枝的Aug2过程类似。这会引发一个问题:为什么这种投影操作,要做两次非线性变换,而不是直接在Encoder后,只经过一次变换即可呢?这个问题的答案,稍后我们会给出解释。

对于Batch内某张图像 xx 来说,在Aug1和Aug2里的对应的增强后图像分别是 xix_ixjx_j ,那么数据对xi,xj\langle x_i,x_j \rangle互为正例,而 xix_i 和Aug1及Aug2里除 xjx_j之外的其它任意2N-2个图像都互为负例。在经过gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 变换后,增强图像被投影到表示空间。在表示空间内,我们希望正例距离较近,负例距离较远。如果希望达成这一点,一般通过定义合适的损失函数来实现。在介绍损失函数前,我们首先需要一个度量函数,以判断两个向量在投影空间里的距离远近,一般采用相似性函数来作为距离度量标准。具体而言,相似性计算函数采取对表示向量L2正则后的点积或者表示向量间的Cosine相似性:

S(xi,xj)=ziTzjzi2zj2S(x_i,x_j) = \frac{z_i^Tz_j}{\Vert z_i \Vert_2 \Vert z_j \Vert_2}

至于为何对比学习的相似性计算一定要做L2正则,这有背后的道理,后文会讲述原因。损失函数很关键,SimCLR的损失函数采用InfoNCE Loss,某个例子对应的InfoNCE损失为:

Li=log(exp(S(zi,zi+)/τ)j=0Kexp(S(zi,zj)/τ))L_i = -log (\frac{exp(S(z_i,z_i^+) / \tau)}{\sum_{j=0}^K exp(S(z_i,z_j)/ \tau)})

其中, zi,zi+\langle z_i,z_i^+ \rangle代表两个正例相应的表示向量。从InfoNCE可以看出,这个函数的分子部分鼓励正例相似度越高越好,也就是在表示空间内距离越近越好;而分母部分,则鼓励任意负例之间的向量相似度越低越好,也就是距离越远越好。这样,在优化过程中,通过InfoNCE损失函数指引,就能训练模型,以达成我们期望的目标。

上面介绍了SimCLR的关键做法,本身这个过程,其实是标准的预训练模式;利用海量的无标注图像数据,根据对比学习指导原则,学习出好的Encoder模型以及它对应产生的特征表示。所谓好的Encoder,就是说输入图像,它能学会并抽取出关键特征,这个过程跟Bert模型通过MLM自监督预训练其实目的相同,只是做法有差异。学好Encoder后,可以在解决下游具体任务的时候,用学到的参数初始化Encoder中的ResNet模型,用下游任务标注数据来Fine-tuning模型参数,期待预训练阶段学到的知识对下游任务有迁移作用。由此可见,SimCLR看着有很多构件,比如Encoder、Projector、图像增强、InfoNCE损失函数,其实我们最后要的,只是Encoder,而其它所有构件以及损失函数,只是用于训练出高质量Encoder的辅助结构。目前所有对比学习模型都是如此,这点还请注意。

上面在介绍SimCLR时遗留了个问题:在将增强图像投影到表示空间过程中,我们做了两次非线性映射,分别是Encoder 和Projector,为什么要做两次投影变换呢?看上去貌似没有道理,这其实是个经验结果。Moco在做特征表示投影时只有基于ResNet 的Encoder,并未后跟Projector,其实这么做才是符合直觉的做法,而Projector是在后续的SimCLR模型中提出的。实验证明,加上这个Projector对于提升模型效果改进很明显,这从经验角度说明两次投影变换是必须的。

SimCLR论文中,对于Projector和Encoder的编码差异进行了对比实验,结论是:Encoder后的特征表示,会有更多包含图像增强信息在内的细节特征,而这些细节信息经过Projector后,很多被过滤掉了。虽然为何需要两次非线性变换,目前只有实验结果,并未有理论解释。我个人猜测,可能是如下原因:我们知道,一般的特征抽取器,在做特征提取的时候,底层偏向抽取通用的低层特征,往往与任务无关,通用性强;接近比如分类任务的高层网络结构,更倾向编码任务相关的高阶特征信息。想来,Encoder和Projector也应该如此,也就是说,在接近任务的高层网络,也就是Projector,会编码更多跟对比学习任务相关的信息,低层就是Encoder,会编码更多跟任务无关的通用细节信息。对于下游任务,这种对比学习训练任务相关的特征,可能会带来负面影响。如果映射网络只包含Encoder的话,那么特征表示里会有很多预训练任务相关特征,会影响下游任务效果;而加上Projector,等于增加了网络层深,这些任务相关特征就聚集在Projector,此时Encoder则不再包含预训练任务相关特征,只包含更通用的细节特征。这是为何需要两次映射过程,我猜大致是这个原因,但也纯属无依据猜测,不保证正确性。

要说SimCLR最大的贡献,我个人觉得有两个:一个是证明了复合图像增强很重要;另外一个就是这个Projector结构。这两者结合,给对比学习系统带来很大的性能提升,将对比学习性能提升到或者超过了有监督模型,在此之后的对比学习模型,基本都采取了Encoder+Projector的两次映射结构,以及复合图像增强方法。

上面是以SimCLR为代表的典型负例对比学习系统的要点,在介绍其它对比学习模型之前,我们下面先更深入地理解对比学习工作机理,这样能更透彻了解其它对比学习系统。

秘境召唤:对比学习到底在干什么

前文有述,对比学习在做特征表示相似性计算时,要先对表示向量做L2正则,之后再做点积计算,或者直接采用Cosine相似性,为什么要这么做呢?现在很多研究表明,把特征表示gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 映射到单位超球面上,有很多好处。这里有两个关键,一个是单位长度,一个是超球面。首先,相比带有向量长度信息的点积,在去掉长度信息后的单位长度向量 gθ(fθ(x))/gθ(fθ(x))2g_{\theta}(f_{\theta}(x)) / \Vert g_{\theta}(f_{\theta}(x)) \Vert_2 上操作,能增加深度学习模型的训练稳定性。另外,当表示向量 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 被映射到超球面上,如果模型的表示能力足够好,能够把相似的例子(比如带有相同类标号的数据)在超球面上聚集到较近区域,那么很容易使用线性分类器把某类和其它类区分开(参考上图)。在对比学习模型里,对学习到的表示向量 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 进行L2正则,或者采用Cosine相似性,就等价于将表示向量 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 投影到了单位超球面上进行相互比较。很多对比学习模型相关实验也证明了:对表示向量进行L2正则能提升模型效果。这是为何一般要对表示向量进行L2正则操作的原因。

那么,好的对比学习系统,应该具备怎样的潜在能力呢?论文“Understanding Contrastive Representation Learning through Alignment and Uniformity on the Hypersphere”对这个问题进行了探讨。它提出了好的对比学习系统应该具备两个属性:Alignment和Uniformity(参考上图)。所谓“Alignment”,指的是相似的例子,也就是正例,映射到单位超球面后,应该有接近的特征,也即是说,在超球面上距离比较近;所谓“Uniformity”,指的是系统应该倾向在特征里保留尽可能多的信息,这等价于使得映射到单位超球面的特征,尽可能均匀地分布在球面上,分布得越均匀,意味着保留的信息越充分。乍一看不好理解“分布均匀和保留信息”两者之间的关联,其实道理很简单:分布均匀意味着两两有差异,也意味着各自保有独有信息,这代表信息保留充分。

Uniformity特性的极端反例,是所有数据映射到单位超球面同一个点上,这极度违背了Uniformity原则,因为这代表所有数据的信息都被丢掉了,体现为数据极度不均匀得分布到了超球面同一个点上。也就是说,所有数据经过特征表示映射过程 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 后,都收敛到了同一个常数解,一般将这种异常情况称为模型坍塌(Collapse)。如果对比学习的损失函数定义不好,非常容易出现模型坍塌的情形(参考上图)。

在这些背景信息下,我们再重新审视类似SimCLR结构的对比学习模型,看看它是在干什么。可以看到,对比学习模型结构里的上下两个分枝,首先会将正例对 xi,xi+\langle x_i,x_i^+ \rangle或者负例对 xi,xi\langle x_i,x_i^- \rangle ,通过两次非线性映射gθ(fθ(x))g_{\theta}(f_{\theta}(x)) ,将训练数据投影到单位超球面上。然后通过体现优化目标的InfoNCE损失函数,来调整这些映射到单位超球面上的点之间的拓扑结构关系,希望能将正例在超球面上距离拉近,负例在超球面上,相互之间推远。那么InfoNCE又是怎么达成这一点的呢?

Li=log(exp(S(zi,zi+)/τ)j=0Kexp(S(zi,zj)/τ))L_i = -log (\frac{exp(S(z_i,z_i^+) / \tau)}{\sum_{j=0}^K exp(S(z_i,z_j)/ \tau)})

从上面列出的InfoNCE公式可以看出,分子 S(zi,zi+)S(z_i,z_i^+) 部分体现出“Alignment”属性,它鼓励正例在单位超球面的距离越近越好;而分母里的 S(zi,zj)S(z_i,z_j) 负例,则体现了“Uniformity”属性,它鼓励任意两对负例,在单位超球面上,两两距离越远越好,这种实例两两之间的推力,会尽量让特征均匀得分布在单位超球面上,保留了尽可能多的有用信息。InfoNCE其实是在Alignment和Uniformity之间寻找折中点,因为如果只有Alignment特性,很明显,模型会快速坍塌到常数解。可以说,所有在损失函数中采用负例的对比学习方法,都是靠负例的Uniformity特性,来防止模型坍塌的,这包括SimCLR系列及Moco系列等很多典型对比学习模型。

上图更形象地说明了这一点,只不过没有将数据画在单位超球面上,如果将上图右侧部分,想象成在单位超球面上的正例相互吸引,负例互斥,就是InfoNCE思想的形象表达。

如果你足够细心,会发现InfoNCE损失函数里,有个神秘的温度超参 τ\tau。那么,这个温度超参 τ\tau有什么作用呢?这其实是个好问题。目前很多实验表明,对比学习模型要想效果比较好,温度超参 τ\tau要设置一个比较小的数值,一般设置为0.1或者0.2。问题是:将这个超参设大或设小,它是如何影响模型优化过程的呢?目前的研究结果表明,InfoNCE是个能够感知负例难度的损失函数,而之所以能做到这点,主要依赖超参。

什么是有难度的负例?什么是容易的负例呢?我们知道,对比学习里,对于某个数据 xix_i,除了它的唯一的正例 xi+x_i^+外,所有其它数据都是负例。但是,这些负例,有些和 xix_i比较像,有些则差异比较大,比如假设 xix_i是张关于狗的图片,那么另外一张狗的图片,或者一张狼的图片,就是有难度的负例,而如果是一张关于人的或者树的图片,则比较好和 xix_i区分开,是容易例子。如果经过gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 将数据映射到单位超球面后,根据Alignment原则,一般来说,比较像的、有难度的负例在超球面上距离 xix_i 比较近,而比较容易区分的负例,则在超球面上距离 xix_i比较远。所以说,对于例子xix_i来说,在超球面上距离xix_i越近,则这个负例越难和 xix_i区分,距离 xix_i 越远,则这个负例越容易和 xix_i 区分。

总体而言,温度参数 τ\tau起到如下作用:温度参数会将模型更新的重点,聚焦到有难度的负例,并对它们做相应的惩罚,难度越大,也即是与 xix_i距离越近,则分配到的惩罚越多。所谓惩罚,就是在模型优化过程中,将这些负例从 xix_i身边推开,是一种斥力。也就是说,距离 xix_i越近的负例,温度超参会赋予更多的排斥力,将它从 xix_i推远。而如果温度超参数 τ\tau设置得越小,则InfoNCE分配惩罚项的范围越窄,更聚焦在距离 xix_i比较近的较小范围内的负例里。同时,这些被覆盖到的负例,因为数量减少了,所以,每个负例,会承担更大的斥力(参考上图左边子图)。极端情况下,假设温度系数趋近于0,那么InfoNCE基本退化为Triplet,也就是说,有效负例只会聚焦在距离 xix_i最近的一到两个最难的实例。从上述分析,可以看出:温度超参越小,则更倾向把超球面上的局部密集结构推开打散,使得超球面上的数据整体分布更均匀(参考上图右边子图)。

那么,是不是温度超参τ\tau设置的越小越好呢?因为这个数值越小,意味着超球面上的数据分布越均匀,越符合Uniformity原则。其实,并不是这样的。因为在对比学习这种场景下,对于某个数据 xix_i,只有一对正例 xi,xi+\langle x_i,x_i^+ \rangle,可能会发生如下的情形:距离xix_i比较近的所谓“负例”,其实本来应该是正例,比如xix_i是一张狗的照片,而 xix_i^-其实也是一张狗的照片。只是因为对比学习是无监督的,我们没有先验知识知晓这一点,所以也会把这张狗的照片当作负例。而如果温度超参越小,则可能越会倾向把这些本来是潜在正例的数据在超球面上推远,而这并不是我们想要看到的。要想容忍这种误判,理论上应该把温度超参设置大一些。所以,温度超参需要在鼓励Uniformity和容忍这种误判之间找到一个平衡点,而调节这个参数大小,其实就是在寻找这两者的平衡点。

上面比较形象地解释了对比学习的工作机理,接下来我们继续介绍不同的对比学习模型。我们继续接着负例方法讲,因为这个故事还没讲完。

基于负例的对比学习:Batch之外

在前文,我们介绍了典型的基于负例的对比学习模型SimCLR,它将Batch内数据做为负例。很多实验证明了:在基于负例的对比学习中,负例数量越多,对比学习模型效果越好(有了上一小结的介绍,我想问您这是为什么?根据现有知识储备,您应该能回答出,此问题答案在本文结尾处)。而算力受限原因,我们又不可能无限放大Batch Size,那么很自然的一个想法就是:我们选择负例的时候,不再局限于在Batch内寻找负例,而是在整个无标注训练数据集合内,随机选择任意大小的数据,来做为模型训练时的负例。这个想法比较符合直觉,看着也比较简单,但是实际做起来并不容易。

这部分内容,我们选择Moco V2,来作为在整个训练集合内选择负例的典型做法。其实这个做法主要是Moco 提出的,Moco V2是吸收了SimCLR的Projector结构,以及更具难度的图像增强方法之后,针对Moco 的改进版本,但是效果比Moco 有明显的提升,所以我们以Moco V2来讲解。

Moco V2的模型结构如上图所示。其图像增强方法、Encoder结构、Projector结构、相似性计算方法以及InfoNCE损失函数,和SimCLR基本一致。最主要的特点和创新在两个分枝中的下分枝:SimCLR里上下两个分枝是对称的,两者可参数共享,而Moco V2的下分枝模型参数更新,则采用了动量更新(Momentum Update)机制。下面我们简单介绍下这种动量更新机制,这个机制目前已经在很多其它领域被广泛采用。

Moco V2的下分枝,也由序列的Encoder和Projector两次非线性映射构成,两个构件的模型结构和上分枝对应结构保持一致,但是自身独有一套参数。这套模型参数的更新,并不是通过常规的损失函数反向传播来进行梯度更新,而是采用如下的移动平均(Moving Average)机制进行更新:

ξ=mξ+(1m)ϑ\xi = m\xi +(1-m)\vartheta

其中,ϑ\vartheta 是上分枝对应结构的模型参数, ξ\xi 是下分枝对应结构的模型参数, mm 是权重调节系数。所谓“ ξ\xi 在移动平均更新”,意思是:模型训练开始的时候,随机初始化 ξ\xi ,当一个Batch计算完毕,上分枝模型参数ϑ\vartheta 经过反向传播梯度更新,参数发生变化。此时,使用上述公示来更新下分枝对应的参数ξ\xi,一般 mm 会取较大数值(0.9甚至0.99)。这意味着,相对上分枝参数,下分枝的参数变动缓慢而稳定,从随机数值一点一点朝着ϑ\vartheta 更新,“小步慢走”地向最优值进行迭代。

Moco V2维护了一个较大的负例队列,当对比学习需要在正例和负例之间进行对比计算时,就从这个负例队列里取K个,K数值可以根据需要调整大小,但是已经不局限于Batch Size的限制了。下分枝的动量更新模型结构有两个作用:一个是将第二组图像增强视图Aug2里的图像,映射到对应的表示空间编码 zjz_j ,为第一组图像增强视图Aug1提供正例;第二个作用是更新负例队列里数据的图像表示编码:一般会将最新Batch里Aug2对应的特征表示编码放入队列,而最老的那个Batch对应的图像编码出队,这样就可以不断更新负例队列内负例编码内容。

新问题来了;为什么负例队列里的图像编码,不用上分枝对应的最新的模型参数 ϑ\vartheta ,而是采用缓慢移动的 ξ\xi 来更新呢?实验表明,假设动量更新公式中的m取很小的数值,意味着更多依赖最新参数ϑ\vartheta 来更新负例队列的编码,对比学习模型效果会急剧下降。只有当m数值比较大,即下分枝的正例和负例参数缓慢而稳定的变动,才能提供较好的模型效果。这可能是因为缓慢更新的模型参数 ξ\xi ,给队列中来自不同Batch内的实例表征编码相对稳定而统一的改变,增加了表示空间的一致性。

上面以Moco-V2为代表,介绍了在全局数据范围里选择负例的典型做法。目前主流的基于负例的对比学习方法,主要是这两类:以SimCLR为代表的Batch内负例,以及以Moco为代表的全局选择负例方法。我们知道,SimCLR和Moco不断在做技术迭代,形成了系列版本,上图列出了它们各自最关键的技术特点及传承关系。目前也有很多实验表面,Encoder特征编码部分,模型越复杂,则模型效果越好。所以SimCLR-v3和Moco-V3都不约而同的选了这条技术改进路线:SimCLR-v3增加了Encoder的复杂度,采用了更深更宽的ResNet;而Moco-v3则直接用ViT这种Transformer模型替换掉了ResNet。

对比聚类:负例隐身术

另外一类对比学习方法,在模型训练过程中引入了聚类,这类方法以SwAV为代表,上图展示了SwAV的模型结构,其中的图像增强、Encoder以及Projector结构,与SimCLR基本保持一致。

SwAV也是上下分枝对称结构,我们以一个例子阐述其工作流程。对于Batch内某张图像 xx来说,假设其经过图像增强后,在Aug1和Aug2里的对应的增强后图像分别是 xix_ixjx_j,数据对 xi,xi+\langle x_i,x_i^+ \rangle互为正例。增强视图 xix_i 走上分枝,经过gθ(fθ(xi))g_{\theta}(f_{\theta}(x_i)) 投影到单位超球面中某点 ziz_i ,增强视图xjx_j走下分枝,经过gθ(fθ(xj))g_{\theta}(f_{\theta}(x_j)) 投影到单位超球面中某点zjz_j。之后,SwAV对Aug1和Aug2中的表示向量,根据Sinkhorn-Knopp算法,在线对Batch内数据进行聚类。假设走下分枝的xjx_j聚类到了 qjq_j 类,则SwAV要求表示学习模型根据 xix_i 预测 xjx_j 所在的类,也就是说,要将 ziz_i 分到第 qjq_j 类,具体损失函数采用 ziz_i 和Prototype中每个类中心向量的交叉熵:

Laug1(zi,qj)=kqjklog(pik)L_{aug1}(z_i,q_j) = -\sum_{k} q_j^k \cdot log(p_i^k)

其中$ p_i^k = \frac{exp(\frac{z_ic_k}{\tau})}{\sum_k exp(\frac{z_ic_k}{\tau})} $, ckc_k为第k个聚类的类中心向量, τ\tau 为温度超参数。

因为是对称结构,同样的,SwAV要求模型根据 xjx_j预测 xix_i 所在的类,也就是说,要将 zjz_j 分到第 qiq_i类。所以,SwAV的总体损失函数是两个分枝损失之和:

LSwAV=Laug1(zi,qj)+Laug2(zj,qi)L_{SwAV} = L_{aug1}(z_i,q_j) + L_{aug2}(z_j,q_i)

这被称为Swapped Prediction。

SwAV也会面临模型坍塌的问题,具体表现形式为:Batch内所有实例都聚类到同一个类里。所以为了防止模型坍塌,SwAV对聚类增加了约束条件,要求Batch内实例比较均匀地聚类到不同的类别中。

这种对比聚类方法,看上去貌似只用了正例,未使用负例。但本质上,它与直接采用负例的对比学习模型,在防止模型坍塌方面作用机制是类似的,是一种隐形的负例。我们可以再仔细观察下它的损失函数,从中不难看出,在单位球面中,它要求某个投影点 ziz_i 向另外一个投影点 zjz_j 所属的聚类中心靠近,这体现了Alignment原则;而分母中的投影点 zjz_j 所不属于的那些类中心,则充当了负例,它要求投影点 ziz_i 在超球面上,和其它聚类中心越远越好,这体现了Uniformity属性,也是防止模型坍塌的关键。我们也可以换个角度,从聚类的角度来看SimCLR中的正例和负例,我们可以把SimCLR看成是:每两个正例组成了一个聚类中心。如果从这个角度看,其实SimCLR这种正负例方法,是种极端情况下的聚类模型。我们在上文说过,SimCLR这种模式,当温度超参设的比较小的时候,容易出现误判的负例,而聚类模型无疑在容忍负例误判方面,天然有很好的包容力,这也许是聚类方法效果好的原因之一。

DeepCluster是更早出现的采用两阶段聚类的自监督模型,SwAV论文中对DeepCluser进行了改造,形成了DeepCluser-V2模型。从概念上,可以简单将DeepCluser-V2理解为和SwAV整体结构类似的工作,只不过SwAV对每个Batch数据在线聚类,而DeepCluster-V2是每个Epoch做一次更大规模的聚类。目前来看,SwAV和DeepCluster-V2是效果最好的对比学习模型之一。

非对称结构:模型不坍塌之谜

上文有述,在常见的基于负例的对比学习方法中,负例有着举足轻重的作用,它起到了将投影到超球体平面的各个实例对应的表示向量相互推开,使得图像对应的表示向量在超球体表面分布均匀的作用,以此来避免表示学习方法模型坍塌问题。尽管对比聚类方法看似没有明确使用负例,但如果深究,会发现仍然是负例在避免模型坍塌方面起作用。

那么,问题来了:如果我们只使用正例,不使用负例来训练对比学习模型,这种思路是可行的吗?乍一看,这几乎是不可能的:假设只有正例,模型推动正例在表示空间内相互靠近。如果只有这一优化目标,很明显,理论上,模型会很快收敛到常数解,也就是所有数据会被映射到表示空间里同一个点上。就是说,很容易出现模型坍塌的结局。

但是,BYOL模型就是这么做的,关键是,它还做成功了,更关键的是,不仅做成功了,它还是目前效果最好的对比学习模型之一。那么,BYOL是怎么做到的呢?为什么它能够只用正例来训练对比学习模型,而不会出现模型崩塌的结局呢?

BYOL的模型结构如上图所示。对于Batch内任意图像,类似SimCRL采取随机图像增强,产生两组增强图像视图Aug1和Aug2,彼此互为正例,分别走上下两个模型分枝,上分枝被称为Online,下分枝被称为Target。Online分枝的Encoder和Projector和其它对比学习模型是一样的,但是,在Projector之后,新增了一个非线性变换模块Predictor,Predictor的结构和Projector类似([FC->BN->ReLU->FC]构成的MLP映射网络),产生表示向量 viv_i并对 viv_i做L2正则化,将向量映射到单位超球面上。Target分枝结构类似Moco V2对应下分枝的动量更新结构,即由自有参数的Encoder和Projector构成,且模型参数不参与梯度更新,采用Online分枝对应结构参数的Moving Average动量更新方式。以此方式,产生增强图像Aug2的向量 zjz_j,同样地,会对 zjz_j 做L2正则化操作,将表示向量映射到单位超球面上。但是,因为BYOL不用负例,所以并不需要维护Moco V2中的负例队列,下分枝只是对Aug2中的正例进行投影。

对于BYOL来说,它的优化目标要求Online部分的正例,在表示空间中向Target侧对应的正例靠近,也即拉近两组图像增强正例之间的距离,对应Loss 函数为:

Laug1=vivj22=22vi,zj/(vi2zj2)L_{aug1} = \Vert v_i - v_j \Vert_2^2 = 2-2 \cdot \langle v_i ,z_j \rangle / (\Vert v_i \Vert_2 \cdot \Vert z_j \Vert_2)

可见,经过改写, Laug1L_{aug1} 也是Cosine相似性的一个变体,它的最小值对应两个表示向量的Cosine最大值,也即优化目标是在单位超球面上,正例之间的距离越近越好。由于online和Target分枝是不对称的,所以BYOL会交换两批增强图像,要求Aug2的图像也走一遍Online网络,并向Aug1图像对应的Target分枝表示向量靠近。也就是说,BYOL的损失函数为:

Lbyol=Laug1+Laug2L_{byol} = L_{aug1}+L_{aug2}

我们知道,Moco V2在下分枝也采用了动量更新结构,如果我们把Moco V2的负例队列抛掉,并在它的上分枝加入类似BYOL的Predictor模块,则BYOL和Moco V2在结构上就保持一致。如果这么改动,两者的差异主要体现在损失函数带来的优化目标不一样:两者都试图将正例在表示空间拉近,但是Moco V2会在InfoNCE损失函数里用负例来防止模型坍塌,而BYOL对应的损失函数里,则没有对应的负例子项。

问题是:既然BYOL只用正例,它是如何防止模型坍塌的呢?背后的原因,目前仍然是未解之谜,不过对此也有些研究进展。BYOL的论文里首先指明了:之所以它没有坍塌到常数解,是由于online和Target两者结构的不对称造成的。具体而言,是动量更新的target结构和Online中的Predictor共同协作发生作用的。如果拿掉Predictor,或者把Target结构中的模型参数改成近乎实时和Online对应结构保持一致(就是说,每个Batch反向传播后,将Online部分最新的参数完全赋予给Target对应结构参数。或者理解为,动量更新公式中权重m取值为0),无论是哪种情况,模型都会发生坍塌。BYOL在论文里进一步实验,表明了最关键的因素在于新加入的Predictor结构:即使Target结构参数和Online部分保持一致,只要把Predictor部分的学习率调大,那么BYOL同样也不会坍塌。这说明Predictor的存在,是BYOL模型不坍塌的最关键因素,但是要配置大的学习率。此外,有其它研究[参考:Understanding self-supervised and contrastive learning with bootstrap your own latent (BYOL).]指出,Predictor中的BN在其中起到了主要原因,因为BN中采用的Batch内统计量,起到了类似负例的作用。但是很快,BYOL的作者在另外一篇文章里[参考:BYOL works even without batch statistics]对此进行了反驳,把Predictor中的BN替换成Group Norm+Weight standard,这样使得Predictor看不到Batch内的信息,同样可以达到采用BN类似的效果,这说明并非BN在起作用。

所以说,为何BYOL这种只用正例的对比学习模型不会发生期望中的模型坍塌,目前还未有定论,但是我们可以定位到主要由于Predictor结构的存在造成的。当然,说是模型结构的不对称带来的效果,原则上是没有问题的,因为这是一种相对粗略的说法。

SimSiam进一步对BYOL进行了简化,我们可以大致将SimSiam看作是:把BYOL的动量更新机制移除,下分枝的Encoder及Projector和上分枝对应构件参数共享版本的BYOL(参考上图),类似前面介绍BYOL里说的Predictor加大学习率的版本。但是,从后续文献的实验对比来看,SimSiam效果是不及BYOL的,这说明动量更新机制尽管可能不是防止模型坍塌的关键因素,但是对于提升对比学习模型效果是很重要的。

冗余消除损失:越简单越快乐

除了BYOL这种只使用正例的模型外,还有一类对比学习模型,以Barlow Twins为代表,也只使用了正例。Barlow Twins结构如上图所示,在图像增强、Encoder以及Projector这几处,和SimCLR模型基本保持一致。我们上面说过,BYOL是靠上下分枝的结构不对称,来阻止模型坍塌的。然而,Barlow Twins采取了上下分枝对称结构,且两者参数共享。它既没有使用负例,也没有使用不对称结构,主要靠替换了一个新的损失函数,可称之为“冗余消除损失函数”,来防止模型坍塌。

与常规的对比学习不同,在将增强图像经过 gθ(fθ(x))g_{\theta}(f_{\theta}(x)) 投影后,一般对表示向量做L2正则,去除表示向量的长度因素,将之投影到单位超球面上。Barlow Twins则不然,它在Batch维度,对Aug1和Aug2里的正例分别做了类似BN的正则。之后,顺着Batch维,对Aug1和Aug2两个正例表示矩阵做矩阵乘法,求出两者的互相关性矩阵(cross-correlation matrix),其损失函数定义在这个互相关矩阵 CC 上:

Lbt=i(1Cii)2+λi(ji)Cij2L_{bt} = \sum_i (1 - C_{ii})^2 + \lambda \sum_i \sum_{(j \neq i)} C_{ij}^2

损失函数 LbtL_{bt}第一个子项被称为“不变项”,第二个子项被称为“冗余消除项”。 CiiC_{ii}为互相关性矩阵 CC 的对角线元素, CijC_{ij} 为非对角线元素。可以看出,它的优化目标为希望互相关性矩阵 CC 的对角线元素为1,非对角线元素为0,也就是希望互相关性矩阵是个单位矩阵 II 。如果仔细分析,可以看出这个“不变项”,起到了把正例在表示空间相互拉近的作用,而“冗余消除项”,其实是希望Aug1和Aug2矩阵里的特征表示向量中,向量每个元素相互之间增强独立性,也就是尽可能消除表示向量里各个bit位之间的冗余信息表达,这个子项起到了类似负例的作用,避免模型坍塌。

从Barlow Twins我们可以看出,如果能够合理设置损失函数,那么光靠损失函数,也可以避免模型坍塌现象。

王者或青铜:经典对比学习模型效果比较

最近两年对比学习比较火,新模型层出不穷。尽管每个新模型都会在论文中和其它模型进行比较,但是真实情况是,很多新模型在图像增强方法、训练任务与目标、超参数设置等都有细微差别,所以在各种影响模型效果因素相同或者相近的公平环境下进行效果对比,就显得很有必要。另外一点,目前绝大多数对比学习模型在做模型训练的时候,采用的是ImageNet数据集,在评测的时候,主要实验也是在ImageNet上做的,那么问题是:对比学习本质上是种自监督预训练模型,希望能够从ImageNet数据集上自监督地学到一些图像先验知识与结构。那么,这种从ImageNet数据集学到的知识,能否很好地迁移到其它数据集呢?这也是对比学习应该回答的一个问题,但是目前貌似并无统一公平的结论。

论文“How Well Do Self-Supervised Models Transfer?”对13个知名自监督模型,在40多种数据集上进行相对公平地对比测试,得出了一些很有价值的结论。

从Many-Shot分类的测试角度,这个考察的是自监督模型从ImageNet习得的知识,迁移到其它数据集合的能力。结果可参考上图,从图中数据,我们可以看出,DeepCluster-v2、SwAV、BYOL三个模型表现突出,而且基本都超过了监督学习模型的效果。除此外,SimCLR-v2的效果也比较好。这说明对于这些表现优秀的模型,确实能够很好地将某个数据集学习到的知识,迁移到其它数据集。

上图展示了Few-shot分类的测试效果,结论和Many-shot类似,也是BYOL、SwAV、DeepCluster-v2效果比较突出,但是大多数Few-shot分类任务,自监督模型效果不及有监督模型。

除了分类任务,它还测试了物体识别与实例分割等其它类型的任务,总体而言,在这些任务中,SimCLR-v2和BYOL模型相对效果比较突出。此处不一一列举,感兴趣同学可参考论文内容。

问题与方向:向何处去

最近一年,对比学习技术确实取得了很大的进展,在不少任务上超过了监督学习的效果。但是,从目前研究进展看,也存在一些问题。我们知道,自监督方法的一个潜在好处是;理论上随着无标注数据训练数据量的增大,那么自监督模型学习到的图像天然结构知识越丰富,应用在下游业务效果也应该越好。但是,从这一点上来看,目前的对比学习是有局限的,实验表明,当自监督数据量增加到非常大的时候,貌似并未能带来更多明显收益与效果。这说明目前的对比学习也好,自监督学习也好,仍然有很大的改进空间。

当然,因为对比学习比较火,已经被延伸应用到很多图像处理外的其它领域,比如NLP,多模态等,我们这里说的所谓问题,仅仅针对图像处理领域里对比学习基础模型本身而言的,无关其它应用领域。

训练数据偏置(Bias)问题

目前大多数对比学习采用的自监督训练数据,一般会用ImageNet,但是用ImageNet做为对比学习训练数据,有个问题: ImageNet这种精挑细选出来的用于分类的数据,往往一个图片仅包含单个类别的实例,这也好理解,本来就是用来分类的,如果一张图片包含多个不同类的实体,那分类标签没法打。但是这带来的问题是:这种数据还是太干净了,如果我们在网上随意挑选图片,大多数都在描述一个场景,情况比较复杂,可能一张图片包含多个不同类别的实例。而目前的对比学习方法,对于处理此类一张图包含多类别实体的图片,效果并不好,这就是所谓的训练数据偏置问题。我个人认为,这个问题还是比较严重的,因为要想真正做到自监督,对训练数据要求就要放低,这样才能快速扩充更多数据用来训练。CASTing Your Model:Learning to Localize Improves Self-Supervised Representations文章探讨了这个问题并提出了一些解决办法。

更好构建正例的方法

正确地做图像增强,构建好的有难度的正例,对于对比学习是十分关键的。这样我们可以让表示学习系统,学到更多种类的图像不变性,增强表示学习模型的表达能力。虽然目前有很多图像增强方法,但是目前研究(参考:Demystifying Contrastive Self-Supervised Learning:Invariances, Augmentations and Dataset Biases)表明,与监督学习相比,对比学习模型主要学习到的,更多是一种图像遮挡不变性和颜色不变性,对于其它的常见不变形,比如视角不变性、照明不变性等,对比学习模型的效果要明显弱于监督学习。所以,如何构造正例,使得对比学习模型能学习更多种类的空间不变性,也是非常关键的。

像素级学习能力

从目前对比学习模型的运行机制看,因为是判别模型,目标相对容易,表示学习系统能学到细粒度的特征信息,但是对于像素级特征,应该是表达能力不足的。而图像处理具体的子领域众多,除了常见的分类任务,很多任务比如Object Segmentation等,都需要在像素级进行操作,所以如何改造现有对比学习模型,使得它能够更好地帮助像素级下游任务,也是比较重要的。论文Dense Contrastive Learning for Self-Supervised Visual Pre-Training针对这个问题,提出了改进方法。

除了上述几个问题,其实还有很多可以列在这里的,比如只使用正例的对比学习模型,从原理上讲,到底为何模型能够不坍塌?再比如,目前很多探索,集中研究对比学习中的Hard负例问题。我们从上文讲解可知:对于负例对比学习方法,之所以负例越多模型效果越好,其实本质上,是因为越多负例,会包含更多的Hard负例,而这些Hard负例对于模型贡献较大,而easy负例,其实没多少贡献。但是,我们又知道,温度超参本身其实是可以聚焦在Hard负例上的。那么,Hard负例应该研究什么具体问题?这个需要仔细考虑。再比如,目前不少研究在考虑融合有监督模型和对比学习,试图兼具两者的优点,这个有多大意义?………诸如此类,很多问题与方向,不一而足,篇幅原因,到此为止。

原文: link