其实第二阶段里讲的 SwAV 就已经有不用负样本的对比学习这个趋势了,它可以算是一个承上启下的工作,因为它也没有用负样本,它用的是聚类中心,但它毕竟还是有一个明确的对比的对象
接下来要讲的 BYOL 和 SimSiam 其实就是正样本自己在玩,已经没有负样本或者聚类中心这样明确的一个对比的东西去做对比了
《Boostrap Your Own Latent:A New approach to Self-Supervised Learning》
BYOL 其实就是这句话的头几个字母
- Bootstrap 就是说如果已经有什么东西了,然后在它之上进行改造
- latent 就是特征的意思(latent、hidden、feature、embedding 其实都是特征的意思,就是各种花里胡哨的用法而已)
BYOL 的意思就是自己跟自己学,左脚踩右脚就上天了,所以说是一篇很有意思的论文
为什么作者很有自信说是 a new approach to self supervised learning,因为它完全没有用任何形式的负样本
为什么不用负样本就这么新奇、这么吸引人注意?
- 因为在对比学习中,负样本是一个约束,如果在算目标函数的时候只有正样本,其实目的就只有一个,那就是让所有相似的物体的特征也尽可能的相似,那这个时候就有一个很明显的捷径:如果一个模型不论给它什么输入,它都返回同样的输出,这样的话,它出来的所有的特征都是一模一样的,那拿这个去算对比学习的 loss 就都是零,意思就是模型直接就躺平了,它直接用这个捷径解就能完美解决问题 loss 永远是 0 模型根本都不用学
- 只有加上负样本这个约束,就是说不光相似的物体要有相似的特征,然后不相似的物体也要有不相似的特征。这样模型才有动力去继续学,因为如果输出的所有特征都一样,那负样本的 loss 就无穷大,所以它必须想办法让正样本和负样本的 loss 都往下降,达到一个最优解
- 所以说,负样本在对比学习里是个必须的东西,它能防止模型学到捷径,很多论文里也管这个叫 model collapse 或者 learning collapse,就是模型坍塌或者学习坍塌,说白了就是什么也没学到,负样本就是为了限制这种情况的发生
- 但 BYOL 之所以神奇就是它没有用负样本,正样本自己跟自己学最后在 ImageNet 上也达到了 74.3 的 top-1 准确率,也是相当高了
因为 BYOL 是 20 年 6 月份出来的,跟 SwAV 是同期的工作,所以它不用跟 SwAV 去比,那在这之前 74.3 就是最高的
BYOL 为什么能够做到不需要负样本?
下图是模型总览图
BYOL的前向过程:
- 一个 mini-batch 的输入 x 经过两次数据增强以后,就得到了 v 和 v’,然后图片通过编码器得到特征
- 上面这一支通过的编码器叫 fθ,下面这个通过的编码器呢叫 fε,两个编码器使用是同样的网络架构,但是它们的参数不同
- fθ 是随着梯度更新而更新的,而这个 fε 跟 MoCo 一样是用 moving average 的形式去更新的,其实就是使用了动量编码器
- 这里得到的特征,如果是 res 50 的话就是 2048 维的一个特征
- 接下来跟 SimCLR 一样用了一个 projection head,这里叫 projector,就是通过 gθ 这个函数得到 zθ 的特征,zθ 在这里是 256 维,比之前的 128 大了一点,发现这个效果好一点
- 同样地,gε 其实跟 gθ 是一样的网络结构,但是参数不一样,也是通过动量的方式去更新的
- 之前对比学习的方法,当得到这两个特征 zθ 和 zε 以后,就像 SimCLR 一样需要让它们尽可能接近,需要达到 maximum agreement,但是 BYOL 没有这么做,它又加了新一层的一个叫 predictor 的东西 qθ,qθ 跟 gθ 的网络结构是完全一样的,也是一个 mlp,然后就得到了一个新的特征 q(zθ),为了让这个预测跟下面的 zε 尽可能一致,就把原来的匹配问题换成了现在的预测问题
- 这个跟 SwAV 也有点像,因为 SwAV 也是把配对问题换成了预测问题,但是 SwAV 还是借助了一个聚类中心来帮助做这个预测任务的,但是 BYOL 真的是什么都没有,就是自己去预测自己,然后这个模型就学起来了
- sg 就是 stop gradient,这里是没有梯度的,跟 MoCo 就很像,上面一支相当于是个 query 编码器,下面一支相当于是 key 的编码器,key 的编码器都是 query 编码器的动量更新,但不一样的是它的代理任务不一样,它相当于是用自己一个视角的特征去预测另外一个视角的特征,通过这种预测型的任务完成模型的训练
这就是 BYOL 的训练过程,看起来相当简单,而且作者说跟别的工作一样,当训练完成以后只有这个编码器留下了,剩下所有的东西都被拿掉了,最后 yθ,也就是这个 2048 维的特征去做下游任务
- 它训练网络的时候用的目标函数直接用的是 mean square erro(mse los)
因为现在是两个向量,一个是预测的 qθ(zθ),一个是 target zε,现在是想让它们尽可能的接近,所以算一个 mse loss 就可以了 - 这个跟之前对比学习用的那些目标函数全都不一样,所以说 BYOL 虽然看起来有 SimCLR 的影子,也有 MoCo 的影子,比如说 SimCLR 的 projection head、MoCo 的动量编码器,但是它用的目标函数不一样,而且也没有用负样本,就用这种自己预测自己的方式学到了很好的特征表示
- 所以说在它放到 arxiv 之后,reddit、twitter、知乎全都引起了剧烈的讨论,因为大家都觉得很不可思议,不用负样本,模型的学习怎么能不坍塌,其实作者也觉得很神奇,所以它后面也提供了一些解释,但是它的解释比较中规中矩没有什么意思
《understanding self-supervised and contrasive learning with “Boostrap Your Own Latent”(BYOL)》
“如何去理解 BYOL”
这篇博客的作者其实也是看到 BYOL 之后觉得非常有意思,所以就尝试复现了一下,结果在复现的时候遗漏了一个小细节,从而导致它的模型训练不动,出现了这个模型坍塌的现象
作者觉得毕竟这是在 DeepMind 的工作,可信度还是非常高的,应该不是论文的问题,肯定是它们自己复现的问题,所以自己就去仔细检查了
- 检查结果发现确实是遗漏了一个很小的细节,这个细节跟 batch norm 有关
在讲这个发现之前,先来看一下 batch norm 带来了什么麻烦,因为之前没有好好说 projection head 里面具体的结构,所以先来复习一下
下图所示是 SimCLR 的结构图
SimCLR 就是说一个图片进了编码器以后就得到了这个 embedding,就是特征 y(2048 维),然后把它扔给 gθ,就是一个 projection head,也就是图中右侧的 mlp
- 这个 mlp 由一个全连接层、一个 batch norm、一个 ReLU 激活函数、一个全连接层、一个 batch norm 的结构组成
- 第一个全连接层的维度是 2048 * 2048
- 第二个全连接层的维度是 2048 * 128,就把维度降下去了,这个 128 的特征就是最后用来做对比学习的特征
- 注意:这里面有两个 batch norm 操作
接下来再看一下 MoCo v2(MoCo v1 没有用 projection head),MoCo v2 的模型结构如下图所示
- MoCo v2确实是用了projection head,就是 gθ,但是它的 gθ 里面是没有 batch norm 的,就是直接全连接层、ReLU然后又全连接层
- 第一个全连接层还是 2048 * 2048
- 第二个全连接层还是 128
再来看 BYOL,模型结构如下图所示
- gθ、gε 都是 projection head
- qθ 是 prediction head
这三个东西用的都是同样的结构,如图右侧紫色的 mlp 结构所示,这个结构里面是全连接层 + batch norm + ReLU + 全连接层 ,第二个全连接层后面没有 batch norm,但是第一个后面是有 batch norm,也就是因为这点小小的差别造成了这个发现
为什么呢?因为像 MoCo v2 的代码写的实在是太好了,而且又是基于 pytorch,所以这篇博客的作者就是借鉴 MoCo v2 来复现的 BYOL ,但是因为 MoCo v2 里 projection head 没有 batch norm,所以他们在复现 BYOL 的时候,这里也没有用 batch norm,所以它的 mlp 就是全连接层 + relu + 全连接层,然后模型的学习就坍塌了,然后这篇博客的作者就觉得实在是太奇怪了,所以赶紧又做了一些额外的实验,如下表所示
- 第二列指的是 projector 里到底用不用 batch norm,还是是用别的归一化方式
- 第三列指的是 prediction 里到底用不用 batch norm,还是是用别的归一化方式
- 目标函数:对于对比学习的方式来说用的是交叉熵函数,对于 BYOL 来说都用的是 L2,也就是 MSE loss
- performance 性能其实是在一个 STL-10 的数据集上做的,不是 ImageNet,但是衡量标准还是准确度
上表做了哪些实验
- 最后一行 random 是说有一个随机初始化的残差网络,然后拿这个残差网络去抽特征,然后在这个特征上训练一个全连接层,最后的结果是 28.8,这个就是随机结果,就是根本没有学习的结果
- 第二行表示如果做的是正确的 BYOL,就是说在 projection head 和 prediction head 里头都用了 batch norm,最后的结果是 57.7,这个就是最高,也就是正确的结果
- 但其实刚开始做的实验做的是倒数第三行(no normalization),就是没有归一化,既没有在 projection head 的里头用 batch norm,也没有在 predictor 用 batch norm,最后的结果只有 28.3,跟随机的结果一模一样,也就是说模型坍塌了什么都没有学到
- 然后作者就尝试了几种变体,做了消融实验:要么在 projection head 里用 batch norm,不在 prediction 里用,要么就是在 projection 里不用,在 prediction 里用,最后发现,只要哪块放一个 batch norm,最后的结果就还行,就算 48 有点低,但至少说明模型在学习没有坍塌
- 作者这时候就强烈怀疑,肯定是 batch norm 惹的事了,正常的想法很自然,下一步就说换一个归一化式行不行,就换成 layer norm,作者就在 projection head 和 prediction head 里面都用了 layer norm,然后发现性能确实就又掉下去了,又变成 29.4,就跟随机一样了,也就是说模型又坍塌了,又什么都没学到
- 所以,作者最后总结说 BYOL 训练的时候不坍塌,肯定是跟 batch norm 有一点关系
- 那有什么关系呢?作者说现在有一个简单的结论: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 的作者很快就找到了另外一种方式去解释这个现象,迅速写了一篇论文(BYOL works even without batch statistics)来做回应,它的题目上来就说 BYOL 即使在没有 batch norm 的时候照样能工作,而且它甚至把这个 even 斜体了,真的就是用来回应上面提到的那篇博客。因为 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 提供的一个隐式的这个对比学习的项,就是说大家不要被那篇博客带跑偏了,赶紧来 follow BYOL 这个套路,这个套路没问题,别再去管负样本的事了
其实这篇论文也只有4页,因为它就是用来回应那个博客,也没想着说真的发论文,目的达到了就行
《Exploring Simple Siamese Representation Learning》
就是 simple Siamese network,其实在 BYOL 放到 arxiv 上之后,就已经有很多研究者在做对对比学习的分析性工作了,因为大家发现,对比学习的成功好像是被很多很小的点堆起来的性能,比如说我们一路走来可以看到用了新的 projection head、训练的时间更长、用了更多的数据增强或者用动量编码器、用更大的 batch size,总之好像都缺一不可,对比学习的性能好像是一点一点被这么堆上去的
这样就不是很好,不方便分析,因为有太多点了,所以不知道从哪分析起,也不知道每个点到底带来了哪些贡献,所以凯明团队又再次出手,把整个过程化繁为简了一下,最后提出了 SimSiam
这个结构有多简单,就是说不需要用负样本(因为它基本上是跟 BYOL 是非常像的,所以说它不需要负样本)、不需要大的 batch size,不需要动量编码器,然后即使在这种情况下,这个 SimSiam 不仅不模型坍塌,而且还能取得很好的结果
具体的模型总览图如下图所示
- 之所以叫 siamese network(孪生网络)是因为一般会有两个编码器,这两个编码器一般网络结构是一样的,而且一般是要共享参数的,所以才叫孪生网络
- 整体架构是跟 BYOL 非常一样的:一个图片变成 x1、x2,然后经过过两个编码器,有一个 predictor,其实 predictor 出来的就是要去预测另外一个编码器出来的特征
- 这里跟 BYOL 唯一的不一样就是它没有用动量编码器
如果我们简单看一下伪代码,如下图所示,就会发现是真的简单,整个前向过程其实就这么几行
- D 函数就是怎么去算 loss,算的是一个 negative cosine similarities loss,说白了就是一个 MSE loss
- 至于前向过程也跟上图中的一样,得到两个视角 x1、x2 以后,先过编码器去得到特征 z1、z2,然后再通过 predictor 得到 p1、p2 的预测,因为有两个预测,所以这里也是一个对称性的 loss,就是说,既可以做从 p1 预测 z2,也可以做用 p2 预测 z1 的任务,但因为加了两次,所以说这里也要除以 2
- l 就是最后的 loss
- 梯度回传更新网络
作者还做了很多实验,比如说 batch size 对模型训练的影响、还有 batch norm 对模型训练的影响,而这些都跟 BYOL 非常像,这里就不一一展开了,最后作者得到一个结论:之所以 SimSiam 能够成功训练,不会有模型坍塌,主要是因为有 stop gradient 这个操作的存在
作者还提出了一个假设,而且在第五节里做了一个 hypothesis:因为有了 stop gradient 这个操作的存在,所以 SimSiam 这个结构是可以把它想象成一个EM的算法
- EM 算法真是无所不在,感觉很多事情最后都可以归结到 EM 算法去解释,都有点量子力学那个意思
这里作者的意思是说因为有了 stop gradient 这个操作之后,这一个训练过程或者说这一套模型参数其实就被人为劈成了两份,就相当于在解决两个子问题一样,模型的更新其实也是在交替进行的,作者接下来又做了一些推导,写的非常好,推荐大家可以去看一下,其实到最后应该可以把它理解成是一个 k-means 这个聚类问题
- k-means其实就是分两步走的,每次先要把所有的点分配给一些聚类中心,一旦分配好了以后,再去更新这个聚类中心,然后再周而复始地去做这个操作
从这个角度来说 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 这么高了(其实之前也有做过很多实验,发现动量编码器真的是很好用,也非常能提点的一个东西,所以可能这也是为什么 BYOL 能够训练的这么好)
- 当然作者在 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 当基线模型,因为真的是训练快、训练的稳,而且下游任务迁移的好
当然还有一篇论文叫 Barlow Twins,是 Yann LeCun 组的一篇论文,因为宣传的很厉害,所以说很多人也都知道,那篇论文就是把目标函数给换掉了,它既不是在做对比也不是在做预测,它是生成了一个关联矩阵叫 cross correlation matrix,然后它希望这个矩阵能跟一个 identity matrix(就是对角线是 1,其它部分都是 0 的矩阵)尽量相似,其实说白了也是一样的意思,就是它希望正样本相似性尽量都逼近于 1,然后跟别的样本尽量的不相似,相似性尽可能是 0,所以说就是换了个目标函数,其它的网络结构、训练方式都大同小异,而且他们放 arxiv 的时间也比较晚,已经是 21 年的 3 月份了,这个时候对于 cv 来说,早都已经是 Vision Transformer 的时代了,所以很快呢就被淹没了