对比学习系列论文MoCo v1(一):MoCo v1的预览

0.对比学习的提出过程

可能大家不太熟知对比学习的提出过程。

0.1最早的时期

一开始的无监督学习的情况就是自己和自己十分相似,这个东西有一个致命的问题。就是网络什么都不学直接输出。这显然不是我们想看到的。

解决早期问题
  • 增加一个数据的增广,显然这样模型就不能直接拷贝了。
  • 增加dropout,这个其实也能减少原来内容的直接传递,这里的情况是:
    因为如果输出当中的aj很大程度来自原来的ak的时候,这时候aj在dropout随机丢弃这个和随机不丢弃这个的时候,输出结果将会有很大差异。所以说这个dropout还是十分有用的。

0.2后来出现的问题

就是如果我们使用上面的方法阻拦了直接拷贝的发生,这会新的问题就出现了,所有的输入,模型全部都输出一个固定的特征向量。这样某个确定图片的输出显然是高度相似的(完全一样),这显然也不是我们想看到的。

解决这个问题

所以对比学习就出现了,不仅要自己和自己相似,还要和别人不一样。

0.3评价标准的问题

之前的很长一段时间如何评价物件学习这种预训练的效果一直很有争议,知道2016年的一篇论文提出了使用线性层来完成任务的方法。

评价方法具体是
  • 1.首先我们应该理解这个对比学习预训练到底是完成什么内容,其实就是得到了一个高效提取特征的方式,所以我们验证对比学习的过程,其实就是验证这些特征提取的好不好的过程。
  • 2.为了验证这些特征的好坏,我们只需要将原来得到的特征提取的过程fix,之后直接接一个全连接层,让全连接的输出直接是最终的结果。这个过程其实我们只是在训练这个全连接层,全连接训练越简单训练效果越好也就越说明原来的特征提取的好,反之则是提取的不好。

1.对比学习到底都在干啥?

1.1最原始的对比学习是什么?

为了顺利的入门对比学习我们得先看懂下面的图片:
在这里插入图片描述首先(a):理解一下这里的xq和xk,这两个东西其实是来自于一张图片,只是做了一些数据增强(我理解数据增强应该是不训练的)。之后再使用不同的encoder之后得到q和k之后计算两个的相似度,让两者相似度升高,这个其实是有一个对抗的思想在里面。

1.2之后做的工作有哪些?

其次(b):理解一下就是不对抗了,直接key的一侧不进行更新了。
最后(c):MoCo在做什么工作,这里其实没有表示出MoCo关于queue的工作,主要体现Momentum的工作,就是我们也更新key的encoder,但是我们的更新来自于query的encoder的更新,让其让两个ecoder做相同方向的更新,但是key的更新是query的更新乘上0.001进行的。

1.3这个东西训练了一个字典吗?

我们看一下是不是这么一个情况,我们训练的时候实际上使一个query去一窝keys里面找到自己对应的那个东西,这个不就是一个字典吗?
**其实并不是,**我们实际上在训练的过程中是在优化一个字典。但是我们最后其实并不是要用这个字典,我们只是借助这个字典帮助我们训练有效的信息提取方式,之后借助这个训练的成果,再接上其他的分类器达到我们真正的目的。

2.为什么要使用queue?

2.1为什么增加负例?

我觉得增加负例的原因大约是让文章中的query可以和更多的keys区分开。我们训练的目的一定要搞清楚,我们是通过让query和现在字典里的optimistic keys相似同时和negative keys不相似,来推知,其和所有世界上存在的negative keys都不一样,所以negative keys越多越好。
举个例子:你的和你眼前的三个人擅长的内容不一样,那么你马上就说自己和世界上的所有人擅长的内容不一样显然不太好。你需要更多的人来进行比较,你如果和中国13亿人的擅长内容都不一样,那么你可能擅长的真的不太一样。

2.2以前什么在限制字典中负例的个数?

显然是mni_batch限制了字典大小,进而限制了负例的个数。

2.2.1为什么一定要用batch进行更新?

我们每计算一次batch就会清空梯度使用的是.zero_grad(),这个到底有什么用?我们先理解一下这个batch在torch里面的作用,

  • batch是我们一个批处理的计算,是并行利用硬件设计的。
  • 另外但是其实深层次还有一个问题,我们现在考虑一个epoch的情况,如果我们不使用batch进行计算,那么我们就是跑一次完整的数据只更新一次,那么如果这次更新偏了,那么这个epoch就是反效果。而如果我们使用batch进行更新,虽然每次batch可能有对的也有错的,但是只要是大部分没有问题最后这个epoch的效果就是好的。

总结起来,必须使用mni_batch。
所以想扩大字典的大小就得打破batch_size的限制

2.3所以作者提出了将几个batch联合起来形成一个queue。

3.queue计算梯度的过程中有什么麻烦?

下面我将介绍不能直接使用torch的训练优化器的原因

3.1torch.autograd底层实现

这里谈一个问题,torch的autograd中分成叶节点和非叶节点,默认回传一次就会将非叶节点的梯度删除来减少内存消耗,叶节点的当然不删除,因为还得给optimizer用呢。

这个有些对torch底层不太熟的读者可能觉得很陌生。其实,你在写训练脚本的时候,调用两次backward马上就会有感觉了,会告诉你grad不存在的错误,这就是第一次回传之后删除了非叶节点的梯度的原因。

3.2结合这个看下queue字典有什么问题?

这里的queue当中的keys很多都是之前的key encoder产生的,这里有很多读者可能已经猜到了,queue中那些不是本次产生的,这里很多读者可能已经知道了,上次的grad已经被删掉了,不能再用了,所以实现不了。
**还真不是这个原因。**其实我们马上就可以调用torch.nn.Module
下的parameters()取出来所有参数的迭代器,之后使用retain_grad() 设置为保留梯度就完事了。只是麻烦而已,不是不能实现。

所以作者到底为什么说不行呢?其实是因为如果所有都保留梯度,你的内存受不住,这个时候就是挑战你的V100性能极限的时候了。就算你的内存承受的住,**计算也会很慢,**因为这个queue理论上应该不具有长度限制,也就是需要算的东西无限。

3.3 inplace?

我们看一下这个参数更新,其实是对原有内容的inplace。
(会不会因为inplace导致恢复梯度出现问题,我试验一下来补充)

4.我们无法对queue计算梯度,有什么影响?

4.1直接导致keys ecoder无法更新

你不计算梯度怎么更新啊?

4.2所以怎么解决

我们想要更新keys ecoder就必须计算正queue的梯度,所以keys encoder更新就有问题了,就得借助文章中的动量更新,将query encoder的更新一部分作用在key encoder ,也是论文最大的创新点。MoCo中的M(Momentum)。

5.对比学习到底为什么好?

5.1充分利用正例的问题

这里其实我们就算是有了对比(负例的支持)我们其实也还是在正例内部做事情,所以其实最关键的还是一个增广,在simCLR当中就说过类似的事情总结起来大约两件事:

  • 1.不同的增广对最终回归的效果的影响并不一样。
  • 2.不同的增广出来的结果的相似度也不同,也不相同的增广,最后出来的结果越好,不相同的结果可能能学到更多的内容。

6.对比学习论文中的其他小问题

6.1什么是 Representation learning?

我们在对比学习系列论文阅读的过程中,我们常常可以看到表示学习这个词。这个我们就得挖一下对比学习到底是干什么,其实就是在提取一个特征张量。这个Representation learning指的就是这个过程。
另外,一般这东西常常被用来和Predictive Learning进行对比。预测学习其实就是最后得到一个分类数据,例如有九个分类,最后的预测结果就直接得到就直接得到一个是九个分类的概率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CUHK-SZ-relu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值