aoi学院

Aisaka's Blog, School of Aoi, Aisaka University

论文阅读-MoCo论文逐段精读-Momentum Contrast for Unsupervised Visual Representation Learning

原文

MoCo 论文链接:https://arxiv.org/abs/1911.05722

这次论文精读李沐博士继续邀请了亚马逊计算机视觉专家朱毅博士来精读 **Momentum Contrast(MoCo)**,强烈推荐大家去看本次的论文精读视频。朱毅博士和上次一样讲解地非常详细,几乎是逐词逐句地讲解,在讲解时把 MoCo 相关领域的研究也都介绍了,听完之后收获满满。

MoCo 获得了 CVPR2020 最佳论文提名,是视觉领域使用对比学习的一个里程碑工作。对比学习目前也是机器学习领域最炙手可热(?)的一个研究方向,由于其简单、有用、强大,以一己之力盘活了从2017年开始就卷的非常厉害的计算机视觉领域。MoCo 是一个无监督表征学习的工作,其不仅在分类任务,在检测、分割和人体关键点检测任务上都逼近或超越了有监督学习模型MoCo 的出现证明我们可能并不需要大量标注好的数据去预训练。下图中 Yann LeCun 将机器学习比作一块蛋糕,强化学习是蛋糕上的樱桃、有监督学习是蛋糕上的奶油、无监督学习才是那块大蛋糕,才是问题的本质,目前很多的大模型都是通过自监督学习得到的。


对比学习介绍

在开始精读论文之前,朱毅博士首先介绍了什么是对比学习。如下图所示,有三张图片,图1、2为同一个人不同的表情,图3为dog,在训练时不会为这三种图片去标注。将三种图片输入到模型中,模型会得到三张图片各自特征。由于图1、2为同一个人、对比学习就是让特征 f₁ 、 f₂ 比较接近,而特征 f₃ 与另外两个特征在特征空间相距较远,这就是对比学习需要达到的目的。

虽然在对比学习中并不需要为图片进行标注,但是仍然需要知道哪些图片是相似的,哪些图片是不相似的,在计算机视觉中通常使用代理任务来完成。举一个具体的例子 instance discrimination,假设有 n 张图片,选取一张图片 xᵢ,经过裁剪和数据增强后得到两张新的图片 xᵢ¹ 和 xᵢ²,则这两张图片和原来的图片就是相似的,也被称为正样本,其余图片即 j ≠ i,则为负样本。对比学习的灵活之处就在于正负样本的划分,例如同一张图片不同视角可看作为正样本,视频中同一段视频任意两帧可以看为正样本,RGB和深度图也可看作为正样本等等。正是由于其灵活性,对比学习的应用才如此之广。


标题、摘要、引言、结论

先是论文标题,论文标题的意思是:使用动量对比去做无监督视觉表征学习,MoCo 就来自于论文前两个单词前两个字母。简单介绍什么是动量动量在数学上就是加权移动平均。例如 yₜ = m × yₜ₋₁ + (1 − m) × xₜ,yₜ₋₁ 为上一时刻的输出,xₜ 为当前输入,m 为动量参数;当 m 很大时,yₜ 就取决于上一时刻输出,其更新就很缓慢;当 m 很小时,yₜ 就取决于当前时刻输入。

作者团队来自于FAIR,就不过多介绍了,五个人谷歌学术引用数达到了50万+。


下面是论文摘要,摘要写的很简洁,总共只有7句话。

  • 第1句话直接介绍主题,我们提出了 MoCo 用于无监督视觉表征学习。第2句话意思是我们把对比学习看作是字典查询,我们建立了一个动态字典,使用到了队列移动平均编码器
  • 第3句话意思是使用队列和移动平均编码器,我们可以建立一个很大且一致的字典,有助于对比无监督学习。
  • 第4-6句话是模型效果,MoCoImageNet 分类上取得了很有竞争力的结果,其中 linear protocol 的意思是说将主干网冻结,只训练分类头。更重要的,将 MoCo 学到的特征迁移到下流任务时,在7个检测和分割任务上,MoCo 都超过它的有监督预训练对手,counterpart 的意思是有监督和无监督训练都使用同一个网络,例如ResNet-50。
  • 最后一句话的意思是,在许多视觉任务上,无监督和有监督特征学习之间的鸿沟被大幅度的填上了。

下面是论文引言部分,总共有6段。

  • 第1段说无监督学习在自然语言处理任务中取得了很大的成功,但是在计算机视觉中,仍然是有监督预训练占统治定位。原因可能是各自信号空间的不同。语言任务有着离散的信号空间(单词、词根、词缀等);但是计算机视觉,原始信号往往是连续、高维的,在构建字典时会有很多问题。
  • 第2段说最近的无监督学习研究都使用了对比学习。这些方法可以看作是构建动态字典。使用编码器网络将图像或图像块表示成 key。无监督学习训练编码器时是这样进行字典查询:一个编码后的 query 应该和它匹配的 key 相似,而和其它 key 不相似。这样一个学习就变成了最小化对比损失的问题。
  • 第3段说我们想构建这样的一个字典:(1)大(2)在训练时保持一致。大的字典可以让我们采样到想要的连续、高维视觉空间;字典中的 key 应该尽可能使用相同或相似的编码器来表示,这样它们和 quary 的比较才能一致。如何让字典又大又一致,作者在后面会详细介绍。

第4段说我们提出了 MoCo 模型,如下图所示,通过比较 querykey 地相似性来训练编码器。我们用队列来存储字典数据,当前时刻数据编码后新的特征入队,最老的数据特征出队,这样字典大小和mini-batch大小就解耦了,就能保证构建一个大的字典;同时使用动量去更新编码器参数,能保证字典中的特征尽可能地一致。使用数学公式表达的话就是:θₖ = mθₖ₋₁ + (1 − m)θq。

第5段介绍了代理任务,作者使用个体判别作为代理任务,即同一张图片不同视角的 querykey 看作是相似的。在 ImageNet 数据线性分类问题上 MoCo 显示出了很有竞争力的结果。第6段作者说无监督学习最主要的目的是将预训练好的特征迁移到下游任务中。在7个检测和分割任务上,MoCo 都有着很好的效果。无论是百万张图片还是10亿张图片,MoCo 都工作地很好。意味着无监督学习和有监督学习之间的差距越来越小了,在许多应用中逐渐可以替代有监督预训练模型。


下面是结论和讨论部分,结论就1句话,我们的无监督学习方法在许多计算机视觉数据和任务上都有着很好的结果。MoCo 从百万数据到十亿数据性能提升是有的,但是很小,可能是这些大规模数据未充分利用,希望有更高级的代理任务来提高模型性能;有可能将 MoCo 调整到像 masked auto-encoding 这样的代理任务上(最近作者就提出了大火的 MAE)。最后作者希望 MoCo 能在其它对比学习研究中有帮助。


相关工作

下面是论文相关工作部分,无监督学习通常包含两方面:代理任务损失函数。代理任务通常不是大家实际感兴趣的任务 (如检测、分类、分割),而是为了学习一个好的数据特征表示;损失函数可以和代理任务分开研究,MoCo 关注的就是损失函数研究。

损失函数是为了衡量模型的预测输出和固定目标之间的差异,如通过 L1、L2 损失重构像素或通过交叉熵对输入进行分类。对比学习的损失测量的是样本对在特征空间的相似性,在训练过程中,目标通常是不固定的。对抗学习的损失衡量的是概率分布的差异,经常用在无监督数据生成。

各种各样的代理任务被提出来,如重构整张图、重构某个 patch、给图片绘上颜色。不同的代理任务可以和对比学习损失函数结合使用,如 CPC、CMC


MoCo方法、实验

下面是论文方法部分,对比学习以及最新它的一些最新进展,都可以看作成是训练一个编码器,从而去做一个字典查询的任务。假设有一个编码好的查询 q,以及一系列已经编码好的样本,也就是 {undefined k₀、k₁、k₂}等,这些可以看作是字典中的 key

这里存在一个假设:在字典中只有一个 key 是跟 query 匹配的,两个互为正样本对,这个 key 叫做 key positive(k₊)。定义好了正样本和负样本,接下来就需要一个对比学习的目标函数,这个对比学习的目标函数最好能满足以下要求:(1)当 q 和唯一的正样本 k₊ 相似的时候,它的loss值应该比较低;(2)当 q 和其他所有的 key 都不相似的时候,这个loss的值也应该比较低。通过点积计算相似性,我们使用 InfoNCE 当作对比学习损失函数,形式为:

公式中的 τ 是一个温度超参数,是一个标量,如果忽略掉它,就会发现,其实这个 InfoNCE 损失就是交叉熵损失,唯一的区别就在于在交叉熵损失中k指代的是数据集里类别的多少,但是在对比学习的 InfoNCE 损失中,k 指的是负样本的数量

通常来说,查询 q 是一个输入 x_q 通过一个编码器 f_q 得到的,同理所有的 k 的表示也都是输入 xᵏ 通过一个编码器 fₖ 得到,输入和模型具体的实现是由具体的代理任务决定。既可以是图片,也可以是图片块,或者是含有上下文的一系列的图片块;对于模型,q 的编码器和 key 的编码器既可以是一样的、也可以是部分共享的,还可以是不一样的。


下面介绍动量对比学习,对比学习是一种在高维的连续的输入信号上去构建字典的一种方式。高维和连续指的是图片,字典是动态的,之所以是动态的是因为这个字典中的 key 都是随机选取的,而且 key 的编码器在训练的过程中也是在不停的变化。如果想学一个好的特征,这个字典就必须拥有两个特性(,大的字典能够包含很多语义丰富的负样本,从而有助于学到更有判别性的特征;一致性主要是为了模型的训练方便)基于以上动机,作者就提出了动量对比学习。

  • 首先就是把一个字典用队列的形式表现出来。队列其实就是一种数据结构,一般被称作是一个fifo(先进先出)的数据结构。作者在这里是用一个队列去代表一个字典,也就是说整个队列就是一个字典,里面的元素就是放进去的 key。在模型训练的过程中,每一个 mini-batch 就会有新的一批 key 被送进来,同时也会有一批老的 key 移出去,所以用队列的好处是可以重复使用那些已经编码好的 key,而这些 key 是从之前的那些 mini-batch 中得到的。这样使用了队列之后,就可以把字典的大小和mini-batch的大小彻底剥离开了,就可以在模型的训练过程中使用一个比较标准的mini-batch size,一般是128或者是256,但是字典的大小可以变得非常大,它的大小非常灵活,而且可以当作一个超参数一样单独设置。同时在算对比学习目标函数的时候只是取一个近似,而不是在整个数据集上算loss,使用队列的数据结构,可以让维护这个字典的计算开销非常小。

  • 用队列的形式可以使这个字典变得很大,但是也因为使用了非常大的字典,也就是非常长的队列,导致没办法给队列中所有的元素进行梯度回传,也就是说,key 的编码器无法通过反向传播的方式去更新它的参数。如果想更新这个 key 的编码器,其实有一个非常简单的方法:就是每个训练迭代结束后,将更新好的 f_q 编码器参数直接复制过来给 fₖ 编码器就可以了。这个想法简单确实是简单,但是作者紧接着说这种方式的结果并不好,原因是一个快速改变的编码器降低了这个队列中所有 key 的特征的一致性。因此作者提出了动量更新的方法,如果将 key 编码器参数设为 θₖ,q 编码器的参数设为 θ_q,那 θₖ 就是以下面公式进行更新:

  • 上式中 m 是动量参数,它是一个0到1之间的数。q 的编码器 ,是通过梯度反向回传来更新模型参数,θₖ 除了刚开始是用 θ_q 初始化以外,后面的更新大部分主要是靠自己。如果动量参数 m 设的很大,那么 θₖ 更新就非常缓慢,所以作者接下来说,因为使用了这种动量更新的方式,虽然在队列里的 key 都是由不同的编码器产生得到的,但是因为这些编码器之间的区别极小,所以产生的 key 的一致性都很强。
  • 下面作者还介绍了 MoCo 和之前研究的对比。之前的对比学习研究都可以看作是字典查找,但是它们都或多或少受限于字典的大小字典的一致性问题,这里作者将之前的方法总结了一下,归纳成了两种结构。第一种就是比较直接的端到端学习,如下图所示编码器可以通过梯度回传来更新模型参数。由于模型的正负样本都是从同一个 mini-batch 里来的,也就是 x_q 和 xₖ 都是从同一个 batch 中来的,它做一次前向传播就能得到所有样本的特征,而且这些样本是高度一致的,因为都是来自一个编码器。听起来确实很美好,编码器能用反向回传学习,特征也高度一致了,但是它的局限性就在于字典的大小,因为在端到端的学习框架中,字典的大小和 mini-batch size 的大小是等价的,如果想要一个很大的字典,里面有成千上万个 key 的话,也就意味着 mini-batch size 的大小必须也是成千上万的,这个难度就比较高了。端到端学习的优点在于编码器是可以实时更新的,所以导致它字典里的那些 key 的一致性是非常高的,但是它的缺点在于因为它的字典大小(就是batch-size的大小),导致这个字典不能设置的过大,否则硬件内存吃不消。

  • memory bank 中其实就只有一个编码器,query 的编码器是可以通过梯度回传来进行更新学习。但是对于字典中的 key 是没有一个单独的编码器,memory bank 把整个数据集的特征都存到了一起,对于 ImageNet 来说,memory bank 中就有128万个特征(看上去好像很大,但是每一个特征只有128维,所以即使整个 memory bank 中有128万个 key ,最后也只需要600M的空间就能把所有的这些key存下来了)。一旦有了这个 memory bank,在每次模型做训练的时候,只需要从 memory bank 中随机抽样很多的 key 出来当作字典就可以了。这里也有一个问题:因为这里的特征都是在不同时刻的编码器得到的,而且这些编码器都是通过梯度回传来进行快速更新的,这也就意味着这里得到的特征都缺乏一致性

  • 显然,无论是端到端的学习还是 memory bank 的方法,都和作者说的一样,受限于字典大小特征一致性这两方面中的至少一个,所以为了解决之前这两种做法的局限性,作者就提出了 MoCoMoCo 采用队列的形式去实现字典,从而使得它不像端到端的学习一样受限于 batch-size 的大小,同时为了提高字典中特征的一致性,MoCo使用了动量编码器

到这里,其实 MoCo 的主要贡献旧已经讲完了,但是如果对对比学习不是很熟的人来说可能还是不太理解 MoCo 的前向过程到底是什么样子的,可惜的是这篇论文并没有提供一个很直观、形象的模型总览图,取而代之的是伪代码,写得相当简洁明了,理解和复现都比较容易。


下面是论文实验部分,作者分别在 ImageNet-1KInstagram-1B 数据集上进行了模型训练,使用的主干网是 ResNet-50。首先是线性分类结果的展示,在完成了无监督学习的预训练之后,将模型的 backbone 冻住,只将它作为一个特征提取器,然后在上面训练一个全连接层去充当分类器,是在 ImageNet 验证集上测试,top-1 分类准确率。

  • 如左图所示,三种对比学习方法结果对比:黑色的线表示的是端到端的学习,它的结果只有三个点,因为受限于显卡内存,蓝色的线表示的是 memory bank 的形式,它可以用很大的字典,所以它可以随着字典增大一直训练,但是它的效果整体上要比端到端学习和 MoCo 的结果都要差一截。作者说这可能是因为特征的不一致性导致的。橙色的线表示 MoCoMoCo 确实可以有很大的字典,之所以停在65536这个数字,从图中可以看到,从16384到65536性能也已经比较饱和了,所以再大也可能不会带来更多的性能提升了。如果拿 MoCo 和端到端学习的方法做比较,可以发现它们的曲线在刚开始的时候的重合度还是比较高的,但是作者说,因为没有实验的支撑,不知道黑线是否能继续按照现有的趋势继续增长下去,有可能结果会更高,也有可能结果会更低,但是因为做不了实验,所以无从得知。

  • 如下图表格所示,动量使用一个相对较大的值(0.999或者0.9999)的时候性能是最好的,差不多都是59,这就说明了一个变化非常缓慢的编码器是对对比学习有好处的,因为它能够提供一个一致性的特征。但是当把动量逐渐变小,变到0.99或者是0.9的时候,性能的下降就比较明显了,尤其是当直接去掉动量,直接将 query 的编码器拿过来当 key 编码器用的时候,就会发现不光是性能下降的问题,整个模型甚至都不能收敛。

  • 右下图是和其它分类方法的比较,首先可以发现,对比学习的效果还是不错的,因为准确率要比没有使用对比学习得到得结果要好。作者还强调:在无监督学习中,模型的大小还是非常关键的(模型越大,一般效果就会越好),所以只是比较最后的准确率,而不去关注模型大小的话,就不太公平了,从图中可以看到 MoCo 既能在小模型上得到最好的效果,也能在大模型的比较中得到最好的结果。

无监督学习最重要的目标是学习到可迁移的特征,作者用视觉领域中最常见、应用最广的检测任务来做无监督的MoCo 预训练模型和 ImageNet 的有监督预训练模型之间的比较。表2种第一行使用的是随机初始化的模型再做微调,所以它是一个基线网络,分数比较低;第二行使用的是 有监督ImageNet 的预训练的模型做初始化然后再做微调,也就是一个比较强的基线结果;最后两行分别是 MoCoImageNet-1M 上和在 Instagram-1 上做无监督预训练当作模型的初始化,然后再做微调。可以看到大多数结果显示 MoCoImageNet-1M 上的预训练就已经超过了有监督的预训练模型。当换成更大的数据集的时候还会有进一步的提升。

接下来作者又再次比较了三种对比学习的检测结果,从表3可以看到 MoCo 和前面两种方式比起来确实是好了很多,而且最主要的是之前的两种方法都没有超越有监督预训练模型的结果,只有MoCo是真的超越了。

作者又在 COCO 数据上进行了对比。除了在设置a里面 MoCo 的模型稍显逊色,在剩下的三个设置下,MoCo 预训练的模型都比 ImageNet 有监督预训练模型得到的效果要好。


最后简单总结下,MoCo 在很多的视觉任务上,已经大幅度的把无监督和有监督之间的坑给填上了。MoCoInstagram 数据集中是要比 ImageNet 训练出来的模型要好的,而且是在所有任务上普遍表现的都很好,这说明了 MoCo 的可扩展性很好,也就是说如果有更多的数据,MoCo 有可能就能学到更好的模型,这和 NLP 中得到的结论是一样的,这也符合了无监督学习的终极目标。

MoCo 这篇论文以及它高效的实现,能让大多数人有机会用普通的GPU就能跑对比学习的实验、做研究。因为 MoCo 在各个视觉任务上取得了更好的性能,也激发了很多后续分析性的工作,去研究 MoCo 学出来的特征到底和有监督学出来的特征有什么不同,还能从别的什么方向去提高对比学习。