Momentum Contrast for Unsupervised Visual Representation Learning

先用SimCLR的架构简单介绍一下对比学习的流程:
在这里插入图片描述

原始图像original image进入数据增强模块T ,转换成两张图Xi和Xj,这两张图经过encoder形成表征向量,然后经过MLP(当成全连接层)变成新的向量Zi和Zj,之后算余弦相似度,这个相似度越大越好,这样Xi和Xj就互为正样本,比如说这张猫生成了X1和X2,再来一张狗的图生成X3和X4,那X1和X2互为正样本,X1和X3、X4互为负样本,X2和X3、X4互为负样本,就是图片只跟他成对生成出来的互为正样本,跟其他图片生成出来的都互为负样本。(正样本希望相似度越来越高,负样本希望相似度越来越低)
对比学习提供的是特征提取的能力,在图像当中怎么去提取特征,因为它会确定相同点是什么,不同点是什么,根据相同点和不同点考虑从图像当中提取更细节的特征。

为什么用encoder输出的特征做下游任务,而不是用MLP加工后的特征zi和zj去做下游任务?

因为encoder后的特征是属于原生的特征,还没有经过MLP的加工,会有更强的泛化能力,MLP加工后的特征是专门来做相似度对比的,最后在下游任务中使用的是encoder。

需不需要负样本?

如果没有负样本,那模型直接生成两个相同的表征,余弦相似度肯定会最高,这种被叫做模型坍塌,就是模型不去学习了,找到了得到最优效果的捷径。所以说需要有负样本,那肯定负样本越多,去匹配到这个正样本的难度越高,所以对比学习的一个batch一般都很大。

Moco:用动量对比学习方法做无监督的表征学习

对比学习本质:学特征,让类似的在特征空间中拉近,不类似的在特征空间中远离。

动量:是一种加权移动平均,表达式是yt=m*yt-1+(1-m)*xt ,其中m是动量超参数,yt是上一个时刻的输出,yt是这一时刻想要改变的输出,xt是当前时刻的输入。本意就是不让当前时刻的输出完全依赖于当前时刻的输入。m是一个介于0和1之间的数,所以m接近1时,yt基本就是跟yt-1是差不多的,由xt造成的对yt的影响就会很小。
在这里插入图片描述
图中是Moco的基本流程,与SimCLR类似,X1经过不同的变换形成X11和X12,二者互为正样本,以X11为基准点,那X12就是它的正样本,X2、X3、…Xn这些都是X11的负样本,注意X2、X3、…Xn要与X12用同一个编码器,因为如果要是用的编码器不同,那最后模型可能找到就是谁跟X11用的同一个编码器,因为同一个编码器的表征结果可能更接近,模型也就找到了一条捷径,不会再去区分正负样本,从而模型坍塌。f11是X11的表征结果,其余的f同理。
在这里插入图片描述
这是Moco中给的图,Xquery对应X11,encoder对应Encoder11,q对应f11,x0key对应f12,x1key对应f2,momentum encoder对应Encoder12,k0 k1 k2分别对应特征,queue代表用的队列存储k0 k1 k2,然后计算相似度求loss。
定义这个正负样本的过程在Moco中称为代理任务,也就是用什么规则定义正负样本,上面的这种代理任务形式称为Instance discrimination,每个样本都当成了一个独立的类别,除了上面这种方式,还可以给原图上色当正样本,或者用原图的不同视角图片当正样本。
Moco把对比学习看成了从字典中匹配的过程,这个字典不是那种数据类型字典,就是为了体现一种查找配对的思想,所以用的字典这个词。把k0 k1 k2这些看成一个字典,找哪一个是跟q一对儿,也就是正样本。
Moco中认为对比学习中有两个改进点,一个是代理任务,一个就是损失函数。不同的代理任务可以搭配不同的损失函数。在论文中采用的是InfoNCE这个损失函数,形式如下:
在这里插入图片描述
形式上看就是个交叉熵,τ是个介于0到1的数,通过除以这个小数可以放大结果之间的差距,让正样本更近,负样本更远。
算这个损失有两个问题,一个是Instance discrimination是一个样本当一个类别,那ImageNet就会形成100多万个类别,另一个问题是样本量过大复杂度很高。
对第一个问题,Moco直接是把类别简化,只分是正还是负,这样就把多分类简化成了二分类,对第二个问题,采用估计的方法,只取一部分负样本,用这部分负样本当总体样本的结果。
采用估计的方法肯定是负样本取的数量越多,越接近总体样本。所以要求字典具有的第一个特性就是要大,第二个特性就是这些key要具有一致性,也就是编码的时候momentum encoder不能有较大变化。

怎么让字典大?

利用队列存储字典,字典的大小可以设置的很大,每一个batch的大小相对于字典来说可以很小,这样每次输出一个batch的结果就放到字典里,最开始进字典的那个batch的结果抛弃,因为是很早的时间步之前的结果,所以抛弃了影响也不大。显存限制的是batch的大小,通过这种方式就可以把batch大小和字典大小分离开。
用队列让字典变的非常大,但是造成的结果就是没法对队列里的所有元素进行梯度回传了(每次只对一个batch的负样本计算key,队列里其他的key都是过去之前的时刻编码器计算的值,所以不能整个队列都梯度回传),也就是编码器无法通过反向传播更新参数。
所以不用反向传播更新,momentum encoder的参数直接复制encoder的参数,通过这种方式更新。但是每次encoder的参数都会有较大变化,这样去生成key的时候也会有较大变化,也就失去了一致性。

怎么保持一致性?

通过复制来更新参数,让momentum encoder产生的key失去了一致性,所以引入动量,m取的很大,比如0.999,那复制过来的参数在乘(1-m)后就会对momentum encoder产生的影响很小了,也就是momentum encoder基本跟上一个batch的参数差不多,变化不大,从而保持了key的一致性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡沫不是茶香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值