CV领域的对比学习综述(下) -- 潘登同学的深度学习笔记
对比学习发展历程
发展历程大概可以分为四个阶段
1、百花齐放
- InstDisc(instance discrimination)
- CPC
- CMC
在这个阶段中,方法、模型、目标函数、代理任务都还没有统一,所以说是一个百花齐放的时代
2、CV双雄
- MoCo v1
- SimCLR v1
- MoCo v2
- SimCLR v2
- CPC、CMC的延伸工作
- SwAV
这个阶段发展非常迅速,上述工作有的间隔一两个月,有的间隔甚至不到一个月,ImageNet上的成绩基本上每个月都在被刷新
3、不用负样本
- BYOL以及它后续的一些改进
- 最后SimSiam将所有的方法都归纳总结了一下,融入到了SimSiam的框架中,基本上是用卷积神经网络做对比学习的一个总结性工作
4、transformer
- MoCo v3
- DINO
对于自监督学习来说,无论是对比学习还是最新的掩码学习,都是用Vision Transformer做的
不用负样本
其实第二阶段里讲的SwAV就已经有不用负样本的对比学习这个趋势了,它可以算是一个承上启下的工作,因为它也没有用负样本,它用的是聚类中心,但它毕竟还是有一个明确的对比的对象
BYOL
BYOL(Boostrap Your Own Latent:A New approach to Self-Supervised Learning)
- Bootstrp: 提升的意思
- Latent: 特征的意思
BYOL 的意思就是自己跟自己学,左脚踩右脚就上天了,所以说是一篇很有意思的论文
整体思路
为什么作者很有自信说是a new approach to self supervised learning,因为它完全没有用任何形式的负样本,那为什么不使用负样本就很新奇呢?
- 因为在对比学习中,负样本是一个约束,如果在算目标函数的时候只有正样本,其实目的就只有一个,那就是让所有相似的物体的特征也尽可能的相似,那这个时候就有一个很明显的捷径:如果一个模型不论给它什么输入,它都返回同样的输出,这样的话,它出来的所有的特征都是一模一样的,那拿这个去算对比学习的loss就都是零,意思就是模型直接就躺平了,它直接用这个捷径解就能完美解决问题loss永远是0模型根本都不用学
- 只有加上负样本这个约束,就是说不光相似的物体要有相似的特征,然后不相似的物体也要有不相似的特征。这样模型才有动力去继续学,因为如果输出的所有特征都一样,那负样本的loss就无穷大,所以它必须想办法让正样本和负样本的loss都往下降,达到一个最优解
- 所以说,负样本在对比学习里是个必须的东西,它能防止模型学到捷径,很多论文里也管这个叫model collapse或者learning collapse ,就是模型坍塌或者学习坍塌,说白了就是什么也没学到,负样本就是为了限制这种情况的发生
- 但BYOL之所以神奇就是它没有用负样本,正样本自己跟自己学最后在ImageNet上也达到了74.3的top-1准确率,也是相当高了
网络架构
BYOL的前向过程
- 一张图片经过两次数据增强,得到了$v$和$v'$,通过Encoder得到特征;两个编码器初始化一样,但是下面的编码器是采用动量更新的;
- 经过一个project head(就是全连接层),得到256维的特征向量;同样地全连接层初始化一样,但是下方的全连接层采用动量更新;
- 之前对比学习的方法,当得到这两个特征$z_θ$和$z_ε$以后,就像SimCLR一样需要让它们尽可能接近,需要达到maximum agreement,但是BYOL没有这么做,它又加了新一层的一个叫predictor的东西;$q_θ$,$q_θ$跟$g_θ$的网络结构是完全一样的,也是一个全连接层,然后就得到了一个新的特征$q(z_θ)$,为了让这个预测跟下面的$z_ε$尽可能一致,就把原来的匹配问题换成了现在的预测问题;
- 这个跟SwAV也有点像,因为SwAV也是把配对问题换成了预测问题,但是SwAV还是借助了一个聚类中心来帮助做这个预测任务的,但是BYOL真的是什么都没有,就是自己去预测自己,然后这个模型就学起来了;
- sg就是stop gradient,这里是没有梯度的,跟MoCo就很像,上面一支相当于是个query编码器,下面一支相当于是key的编码器,key的编码器都是query编码器的动量更新,但不一样的是它的代理任务不一样,它相当于是用自己一个视角的特征去预测另外一个视角的特征,通过这种预测型的任务完成模型的训练 ;
这就是 BYOL 的训练过程,看起来相当简单,而且作者说跟别的工作一样,当训练完成以后只有这个编码器留下了,剩下所有的东西都被拿掉了,最后yθ这个特征去做下游任务;
它训练网络的时候用的目标函数直接用的是mean square MSE loss)
- 因为现在是两个向量,一个是预测的$q_θ(z_θ)$,一个是target $z_ε$,现在是想让它们尽可能的接近,所以算一个MSE loss就可以了
- 这个跟之前对比学习用的那些目标函数全都不一样,所以说BYOL虽然看起来有SimCLR的影子,也有MoCo的影子,比如说SimCLR的projection head、MoCo的动量编码器,但是它用的目标函数不一样,而且也没有用负样本,就用这种自己预测自己的方式学到了很好的特征表示
- 所以说在它放到arxiv之后,reddit、twitter、知乎全都引起了剧烈的讨论,因为大家都觉得很不可思议,不用负样本,模型的学习怎么能不坍塌,其实作者也觉得很神奇,所以它后面也提供了一些解释,但是它的解释比较中规中矩没有什么意思,看一篇与BN层有关的解释;
BN层知道了副样本
这是一篇blog,understanding self-supervised and contrasive learning with "Boostrap Your Own Latent"(BYOL)
这篇博客的作者其实也是看到BYOL之后觉得非常有意思,所以就尝试复现了一下,结果在复现的时候遗漏了一个小细节,从而导致它的模型训练不动,出现了这个模型坍塌的现象
- 检查的时候发现一个小细节,这个细节与BN层有关;
先聊一下之前网络的MLP层
- SimCLR
MoCO v2
BYOL
为了证明确实是BN层导致的模型学习坍塌,blog作者做了一些额外的实验
如果只做LN,那么跟什么都不做其实没有区别;然后作者给出了一个比较合理的解释:
- batch norm这个操作是把一个batch里所有样本的特征拿过来算一下它们的均值方差,也就是running mean running variance,然后用整个batch算来的均值和方差做归一化,这也就意味着,当在算某个正样本的loss时,其实也看到了其它样本的特征,也就是说这里面是有信息泄露的,MoCo里有一个操作叫做 Shuffling BN ,也就是为了防止这种信息泄露的,博客的作者就说,因为有这种信息泄漏的存在,所以可以把这个batch里的其它样本想成是一种隐式的负样本;
- 换句话说,当有了batch norm的时候,BYOL其实并不光是正样本在自己跟自己学,它其实也在做对比,它做的对比任务就是说当前的正样本这个图片跟平均图片有什么差别,而这个平均图片就是batch norm产生的,还有之前很多图片的总结量,这就跟SwAV很像了,因为 SwAV 就是没有跟负样本去比,而是找了个聚类中心去比,而这里batch norm生成的平均图片,其实就相当是一种聚类中心的意思,也就这篇作者说的mode(众数),就是中值的意思;
所以说,这篇博客的作者认为batch norm是BYOL能够成功的关键,其实是做了一种隐式的对比学习,这个观点很快就被大家所接受了,因为听起来确实很合理,而且它后面做了很多实验,也全都验证了它的观点,batch norm确实至关重要,拿掉batch norm以后模型就是不好训练,对超参数的设置非常的敏感,稍有不慎它就啥也不学了。
但是BYOL的作者看到这个以后就急了就觉得说如果真是这样的话,如果真的要用这种方式去解释的话,BYOL的创新性就大大降低了,因为它还是没有逃脱出对比学习的范畴,它还是找了一个东西去做对比,所以赶紧做实验看看能不能找到另外一种解释,为什么BYOL 能够不模型坍塌。
BYOL回应blog
因为BYOL 的作者不想让大家觉得BYOL 的成功是依赖于 batch norm,然后BYOL 的作者做了一系列非常详细的实验看看问题到底出在哪,实验结果如下表所示
- 这个实验就是说在encoder编码器,就是Res50里到底用batch norm、layer norm,还是什么都不用,还有在projector里到底用batch norm、layer norm,还是什么都不用,或者说在predictor里到底用batch norm、layer norm,还是什么都不用
- 虽然就这么一个小小的表格,但其实里面的跑的实验是相当多的,做了一个非常完整的消融实验,而且这里还和SimCLR去比了,因为其实BYOL就是基于SimCLR做的,它跟SimCLR非常像
作者发现了这样几个现象
- batch norm确实是比较关键,因为只要是没有batch norm的地方,SimCLR都工作的很好,可能有一些性能下降,但是都还在学,BYOL全都没有再学了,模型坍塌了
- 通过这个完整的消融实验,作者还发现了几个特例,正是这些特例帮助作者找到了另外一个可以解释的理由:即使当projector有 bn的时候,BYOL 还是训练失败了,这个就不能解释batch norm很关键了,因为如果batch norm真的很关键,如果真的能在这个隐式负样本提供对比学习的话,训练就不应该失败
- 还有就是当编码器和project都没有用batch norm的时候,SimCLR也失败了,因为SimCLR没有predictor,所以说这里predictor就无所谓了,意思就是说当什么归一化都不用的时候,不光是BYOL,SimCLR 也不行,它即使用了负样本也训练不出来,所以这就再次证明了,batch norm不是提供了一个隐式的负样本,因为这里即使给它显式的负样本了,它还是训练不出来
- 所以这时BYOL 的作者和原来博客的作者后来就达成了一个比较一致的结论,就是说batch norm跟它原来的设计初衷一样,它主要的作用就是能帮助这个模型稳定训练,它能提高模型的训练稳健性,从而不会导致模型坍塌,BYOL的作者又把这个结论进一步延伸,然后给出来了一个可以解释的理由,如果一开始就能让模型初始化的比较好,后面的训练即使离开了batch norm也没有问题
- 于是作者就做了另外一个实验,就是用group norm和weight standardization,group norm就是一种归一化的方式,而weight standardization就是一种模型初始化的方式,这一套方法其实是vit的原班作者在他们之前的论文 BEiT 里提出来了,也就是现在很多人说的ResNet v2就是用这种方式做训练,然后换上这种初始化方式以后,BYOL 的作者发现又能训练74左右的top-1准确率了,跟原来论文里用batch norm的那个74.3的结果非常接近
- 所以作者最后再次强调说group norm或者weight standardization都没有计算批统计量,所以说这个版本的 BYOL,也就是说这个73.9的 BYOL 是没有跟mini batch里其它的样本做对比的,意思就是说没有隐式的对比,也就意味着说BYOL 还是一个全新的方式,它就是很厉害,就是能自己跟自己学,模型就能学的很好,不需要这种假设batch norm提供的一个隐式的这个对比学习的项,就是说大家不要被那篇博客带跑偏了;
SimSiam
SimSiam(Exploring Simple Siamese Representation Learning), kaiming He团队将对比学习的所有技巧总结了一下,形成一个框架叫SimSiam;
因为大家发现,对比学习的成功好像是被很多很小的点堆起来的性能,比如说我们一路走来可以看到用了新的projection head、训练的时间更长、用了更多的数据增强或者用动量编码器、用更大的 batch size,总之好像都缺一不可,对比学习的性能好像是一点一点被这么堆上去的;
这样就不是很好,不方便分析,因为有太多点了,所以不知道从哪分析起,也不知道每个点到底带来了哪些贡献,所以凯明团队又再次出手,把整个过程化繁为简了一下,最后提出了SimSiam;
整体架构
这个结构有多简单,就是说不需要用负样本(因为它基本上是跟 BYOL是非常像的,所以说它不需要负样本)、不需要大的batch size,不需要动量编码器,然后即使在这种情况下,这个SimSiam不仅不模型坍塌而且还能取得很好的结果;
- 之所以叫siamese network(孪生网络)是因为一般会有两个编码器,这两个编码器一般网络结构是一样的,而且一般是要共享参数的,所以才叫孪生网络
- 整体架构是跟BYOL 非常一样的:一个图片变成 x1、x2,然后经过过两个编码器,有一个predictor,其实predictor出来的就是要去预测另外一个编码器出来的特征
- 这里跟BYOL唯一的不一样就是它没有用动量编码器
前向过程
- D函数就是怎么去算loss,算的是一个 negative cosine similarities loss,说白了就是一个MSE losss
- 至于前向过程也跟上图中的一样,得到两个视角$x_1、x_2$以后,先过编码器去得到特征$z_1、z_2$,然后再通过predictor得到$p_1、p_2$的预测,因为有两个预测,所以这里也是一个对称性的loss,就是说,既可以做从$p_1$预测$z_2$,也可以做用$p_2$预测$z_1$的任务,但因为加了两次,所以说这里也要除以2
- l就是最后的loss
- 梯度回传更新网络
最后作者得到一个结论:之所以SimSiam能够成功训练,不会有模型坍塌,主要是因为有stop gradient这个操作的存在(因为这个网络中,Key的Encoder是被梯度截断的)
作者还提出了一个假设,而且在第五节里做了一个 hypothesis:因为有了stop gradient这个操作的存在,所以SimSiam这个结构是可以把它想象成 一个EM的算法;
从这个角度来说SimSiam又跟SwAV有点关系了,于是作者其实在最后还画了这么一张图如下图所示,这张图真的画的非常好,它把所有孪生网络的做法都归纳到在这里,然后做一下总结和对比
- SimCLR:SimCLR因为是端到端的学习,所以说两边都有梯度回传,但是它还是做的一个对比任务
- SwAV:做的也是一个对比任务,但它并没有跟负样本去比,而是跟聚类中心去比的,那聚类中心是通过SK算法得到的
- BYOL:BYOL就有一个新的贡献(就是predictor,图中已经单独画出来了),它就不是一个对比任务,变成一个预测任务了,要用左边去预测右边,同时还使用了动量编码器
- SimSiam: 整体跟BYOL非常像,左边其实就是一模一样,只不过右边没有用动量编码器,所以这个对比还是比较简洁明了的
实验结果
最后再看一下结果如下表所示,之前BYOL也没有看结果,鉴于SimSiam是一个总结性的工作,它跟之前里程碑式的工作都有对比,所以看这个表格就足够了
在 ImageNet 上linear classification的结果:这里比较的都是重量级工作,比如SimCLR、MoCo v2、BYOL
- 从batch size来说,只有MoCo v2和SimSiam是可以用256的,其它工作都要用更大的batch size,所以说凯明大佬的工作真的是好follow
- 前两项工作SimCLR和MoCo v2要用负样本,但是对于BYOL来说就完全没有用,SwAV用的是聚类中心
- 对于动量编码器来说,SimCLR没有用,SimCLR v2用了,但是v1没有用,MoCo v2和 BYOL用了,SwAV没有用
- 总的来说,SimSiam就是这些都没有用
看结果的话发现在训练100个epochs的时候,SimSiam的结果是最好的,所以说明它学的非常快,但是随着训练的推进慢慢就不行了,涨幅比较慢,到最后也是有71.3,但是这个时候BYOL已经有74.3这么高了(核心是动量编码器吧)
- 当然作者在SimSiam这篇论文里,它只是想说把这些trick全拿掉照样能训练,所以说它没有用动量编码器
- 再来看SwAV,SwAV只有71.8,这个应该是没有用multi crop的技术,所以这就跟之前讲SwAV的时候说的一样,就是如果不用multi crop,SwAV 就跟MoCo v2差不多,还不如MoCo v2,所以说只从分类来说,最强的方法就是BYOL;
在其他下游任务
前面几个做的是物体检测,最后做的是一个实例分割,就是cv人必做的两个下游任务
这里可以看到有一个比较有趣的现象,就是说针对下游任务的transfer来说,MoCo v2和SimSiam其实是表现最好的,BYOL和SwAV也不错,但是跟MoCo v2和SimSiam比还都差了一到两个点,差距还是比较明显,所以说直到现在,如果想去尝试一些idea,或者说尝试去做一些对比学习的工作时,还是会用MoCo v2当基线模型,因为真的是训练快、训练的稳,而且下游任务迁移的好;
Transformer
MoCo v3
moco v3这篇论文虽然题目说的是自监督的Vision Transformer ,但其实MoCo v3只是一种架构,所以说卷积神经网络也可以用,Vision Transformer也可以用;
事实上MoCo v3怎么从v1、v 2变到v3,作者只用了一页去讲,大部分的篇幅都在讲自监督的训练、ViT有多不稳定、发现了一个什么样的问题以及怎样用一个小小的改进就能让这个训练变得更稳定、效果也更好,这个写法就跟SimCLR v2有点像;
- MoCo v3其实就相当于是MoCo v2和SimSiam 的一个合体;
- 整体的框架来说,它还是有两个网络,一个是query编码器,一个是key编码器,而且key的编码器是动量编码器,最后的目标函数用的是对比学习的loss,所以说从这个角度讲,它是个MoCo v2;
- 但是如果仔细看细节就会发现,query编码器现在除了这个骨干网络之外,它还有projection head,还有prediction head,这个其实就是BYOL,或者说是SimSiam;
- 而且它现在这个目标函数也用的是一个对称项,就是说它既算query1到 key2的,也算这个从query2到 key1的,从这个角度讲它又是SimSiam;
所以说,MoCo v3就是MoCo v2和SimSiam一个很自然的一个延伸工作
因为Vision Transformer的出现,所以说作者就很想把卷积神经网络换掉换成 Vision Transformer ,看看结果到底会变得如何,是不是自监督学习加上Vision Transformer就能取得像nlp那边的成功,然后就迅速试了一下,把骨干网络从一个残差网络换成了ViT,下图展示的是一个vit自监督训练的一个训练曲线;
- 作者发现当batch size比较小的时候其实还好,这个曲线比较平滑,比如说图中的橘黄线和蓝线在当batch size比较小的时候就比较平滑,不会出什么问题,这个效果也还行
- 但是当batch size变大了以后,作者就发现这个曲线会莫名出现这种情况:训练的时候突然准确度就掉下来一下,再训练一段时间后又掉下来一下,虽然说它每次还能很快的恢复上去,但是恢复上去就不如原来的那个准确度高了,最后这个准确度也会差很多
- 按道理来说,一般大batch size会得到更好的结果,但是在这里大batch size反而得到了更差的结果,作者就觉得这是一个问题,这个问题得解决,如果能解决训练的这个问题,很有可能就能用更大的batch size去训练一个更大的Vision Transformer从而得到更好的结果
- 针对这个问题,MoCo v3 的作者就提出来一个小trick,他是怎么想到这个解决方式的呢?他观察了一下训练的时候每一层回传梯度的情况,这个是比较常见的操作,一般如果网络训练的不好,而且不知道为什么的时候,一般首先就是要去查一下梯度,然后作者就发现,当每次loss有这种大幅的震动导致这个准确度大幅下降的时候,梯度也会有一个波峰,而这个波峰其实是发生在第一层,就是在做patch projection时候(就是那个768x768的那层linear层)
- 其实就是一个可以训练的全连接层,能训练当然是好事,但是如果每次梯度都不正常,那还不如不训练,所以说作者就简单的尝试一下,如果不训练,直接冻住结果会怎样,所以就随机初始化了一个patch projection层,然后把它冻住,就是整个训练过程中都不变,结果发现问题就解决了,而且很神奇的是这个trick不光是对MoCo v3有用,它对BYOL也有用,如果用BYOL那套框架,把残差网络换成Vision Transformer,刚开始就把patch projection层冻住,一样能获得更平滑的训练曲线,获得更好的训练结果
在这篇论文之后也有很多研究者意识到了第一步tokenization阶段的重要性,所以也有很多后续的工作去改进
DINO
DINO这篇论文也说的是一种自监督训练Vision Transformer的方式,但这篇文章主要的卖点是:Vision Transformer在自监督训练的情况下会有一些非常有趣的特性,它把它效果最炸裂的这些图片放到了文章开头;
这个图的意思就是说一个完全不用任何标签信息训练出来的Vision Transformer ,如果把它的自注意力图拿出来进行可视化的话,会发现它能非常准确的抓住每个物体的轮廓,这个效果甚至能直接媲美对这物体做分割,比如说图中像牙刷还有长颈鹿,这些物体的边界抠的非常的精准,甚至比很多做无监督分割的工作都要做的好;
整体框架
其实它的方法倒不是说多新,跟之前的一系列对比学习的工作都非常的相似,就是换了个方式来讲故事,至于DINO这个名字,来自于它的题目self distillation with no labels,就是distillation和no labe;(self distillation自蒸馏)
- 对于 MoCo 来说,左边的网络叫做 query 编码器,右边叫做key编码器,对于BYOL 来说,左边叫做online network,右边叫做target network,DINO其实就是延续的BYOL,它只不过是换了个名字,把左边叫成student网络,右边叫成teacher网络
- 因为student要预测teacher,所以可以把teacher网络的输出想成是ground truth
- 至于具体的前向过程,跟BYOL或者跟SimSiam都是非常类似的,同样就是当有同一个图片的两个视角以后,用$x_1、x_2$通过编码器得到了两个特征,这个编码器自然也是有projection head、prediction head
- 为了避免模型坍塌,DINO做了另外一个额外的操作,叫做centering,这个操作就是把整个batch里的样本都算一个均值,然后减掉这个均值,其实就算是centering,这个就很像是 BYOL对于 batch norm 的讨论,因为batch norm也是对整个batch里的样本做了一个均值和方差
- 最后有一个stop gradient的操作然后用$p_1$去预测$p_2$
再看看伪代码
它真的跟 MoCo v 3实在是太像了,尤其是前像过程不就是一模一样吗,就只有目标函数稍微有点不一样,这里多了一个centering的操作,防止模型坍塌
第四阶段总结
MoCo v3和DINO这两篇工作,从方法和模型角度上来说,其实它们跟第三阶段基本是一模一样的,主要就是融合了Vision Transformer;