Constrast Learnning
一. 概念简介
有一篇英文说得很好:
- queue
一个队列,用于存放负样本
- 使用立马拿出来,效率高
- 可以设置的非常大,数量大(对比学习需要大量负样本,这点最重要)
- MOCO使用了动态的方式(总数设置固定值,每次iteration传入一个batch的新特征,移除一个batch的老特征)
- keys
因为是对比学习,所以要记住特征的ID,在计算loss的时候同一个ID相似度最大,不同ID相似度最小
- memory bank
原始版本的queue-key系统,原始版本把全部的负样本都存储起来(这样做坏处是内存需求太大,而且梯度更新和存储的特征不匹配-一个epoch更新一次queue,中间的iteration都使用老的特征)。这个不是硬件中的表述,仅仅作为一个代号(刚开始我还以为是硬件的标识)。
- momentum
更新负样本的模型参数,这里得结合下面训练方式说明,正样本模型正常训练,假设正样本模型参数\(\theta^+\),负样本模型参数\(\theta^-\),负样本模型不参与训练,但更新为\(\theta^-=\theta^-+\alpha*\theta^+\) 和论文中的表述相同。
![](https://i-blog.csdnimg.cn/blog_migrate/edb492a48efa16368f771806c002b27f.png)
- 训练方式
- 模型可以是一个也可以是两个(比如MOCO是一个,End-to-End是两个),但是训练会使用两个共享(MOCO不共享)的模型进行
- 模型以A和B为例
- 接着上面的链接,从dataloader中读取一个batch的数据(假设B=10,会获得20或者30个数据,30的数据目前不清楚用途,这是以20为例)
- End-To-End模型
- 前向计算A模型获得\(A_{pos}\),这里假设模型A和模型B相同,那么仅需计算一次即可。其中正样本2个+负样本18个,计算loss即可。
- memory模型
- 每个epoch开始时,首先前向计算\(A_{pos}\)输入所有的样本,获得所有的特征存储到memory bank之中。
- 计算Batch样本\(A_{pos}\),负样本就是memory中的所有值(除去当前batch),很明显增大了负样本的数量
- 下一个iteration不改变memory bank数据,按照第二步往复计算
- 等到新的epoch开始重新计算memory bank
- 很明显的发现memory bank中的值和更新的梯度不匹配,用的都是老的数据
- MOCO模型
- 前向计算A模型获得\(A_{pos}\),计算B模型获得\(B_{neg}\)
- 将\(B_{neg}\)存储到queue内(如果满了就先pop然后再push)
- 计算\(A_{pos}\)和queue的loss,更新A模型的梯度
- 然后根据A模型的参数,通过动量更新B模型的参数(参见momentum)
- 往复此过程即可
- 很明显的发现queue的大小是可以设置的,不会出现大数据不能跑。对于queue和梯度更新滞后性解决了一部分,但未根本性的解决。
- 内存的存储和shuffle-BN
未仔细阅读源码
看了一下CLR、MOCO、MoCo_V2、CLR_V2在imagenet上的最终表现,感觉对比学习任重而道
![](https://i-blog.csdnimg.cn/blog_migrate/cb707119130ebdfae505dc3aebbdcc4f.png)