李沐论文精读系列三:MoCo、对比学习综述(MoCov1/v2/v3、SimCLR v1/v2、DINO等)_moco论文-CSDN博客

  • MoCo这个词,来自于论文标题的前两个单词动量对比Momentum Contrast 这个式子表示:当前时刻的输出,不仅依赖于当前时刻的输入,还依赖于前一时刻的输出。m越大,当前时刻的输入 对结果​ 就越小。
  • MoCo利用了动量的这种特性,从而缓慢地更新一个编码器,让中间学习的字典中的特征尽可能地保持一致。
  • 本文是从另外一个角度来看对比学习,即把对比学习看作是一个字典查询任务。

在MoCo这篇论文当中,因为作者已经把所有的对比学习的方法归纳成为了一个动态字典的问题,所以很少使用anchor或者正负样本这些词,用的都是query和key。
作者认为,一个好的字典应该有两个特性:
字典足够大
字典越大,key越多,所能表示的视觉信息、视觉特征就越丰富 ,这样拿query去做对比学习的时候,才越能学到图片的特征。
反之,如果字典很小,模型很容易通过学习一些捷径来区分正负样本,这样在碰到大量的真实数据时,泛化就会特别差(我的理解是,字典中只有猫和狗,狗都是黑色,猫都是黄色。模型简单的判断图片中物体是否是黄色,来区分猫和狗,而不是真的学到了猫和狗的特征)
编码的特征尽量保持一致性
字典里的key都应该用相同或者说相似的编码器去编码得到,否则模型在查找query时,可以简单的通过找到和它使用相同或者相似编码器的key,而不是真的和它含有相同语义信息的key(变相引入两一个捷径)。
以前的对比学习,都至少被上述所说的两个方面中的一个所限制(要么一致性不好,要么字典不够大)。本文最大的贡献,就是使用队列以及动量编码器来进行对比学习,解决了这个问题。具体来说:

  • key(编码特征)并不需要梯度更新,而是通过更新编码器,新的编码器使输出的key更新。
  • queue :整个队列里面的元素都是字典,队首输入当前batch的编码特征,队尾弹出最旧的batch特征。每次移除的是最老的那些key,从一致性的角度来说 ,有利于对比学习。
    • 用队列的好处是可以重复使用那些已经编码好的key,而这些key是从之前的那些mini-batch中得到的。
    • 用队列结构,就可以把的mini_batch的大小和队列的大小直接分开了,所以最后这个队列的大小,也就是字典的大小可以设的非常大,因为它大部分的元素都不是每个iteration都需要更新的。
    • 在字典里计算loss而不是整个数据集上计算loss,使用队列的数据结构,可以让维护这个字典的计算开销非常小。
  • momentum encoder:
    • 如果只有当前batch的key是从当前的编码器得到特征,其它的key都是另外时刻的编码器输出的特征,这样就无法保证字典中key的一致性。所以作者又提出了动量编码器
    • 动量编码器,即编码器参数的更新方式就是。
    • 初始化的编码器来自于query的编码器,之后每次更新,只有1‰的参数会从query的编码器参数里拿过来更新,所以这个编码器参数更新的非常缓慢。从而保证了字典中所有的key都是由相似的编码器抽取得到的,尽最大可能地保持了他们的一致性。(直接更新编码器k的所有参数,会导致编码器更新过快,降低了这个队列中所有key的特征的一致性)
  • 动态字典:字典中的key都是随机取样的,而且key的编码器在训练的过程中也是在不停的改变。

  MoCo 的主要贡献就是把之前对比学习的一些方法都归纳总结成了一个字典查询的问题,并提出了队列存储和动量编码器。前者解决字典太大不好存储和训练的问题,后者解决了字典特征 不一致的问题;从而形成一个又大又一致的字典,能帮助模型更好的进行对比学习。