— order: 11 —1 Momentum Contrast for Unsupervised VisualRepresentation Learning时间:2019.111.1 题目 & 摘要MoCo CVPR20 最佳论文提名,是 CV 领域对比学习里程碑的工作,以一己之力盘活了巨卷的 CV 领域如果把深度学习比作一块蛋糕,那么强化学习只能是蛋糕上的一颗樱桃,有监督学习是蛋糕上的糖霜,只有自监督学习才能算是整个蛋糕的主体什么是对比学习?对比学习是自监督的一种,可以看对比学习综述那篇文章(链接),简单来讲就是让相似样本的特征空间尽量接近而不相似的尽量远离。对比学习的框架最大的好处就在于正负样本定义规则的灵活性题目:动量对比学习的方法做无监督视觉特征学习本文的亮点在于,MoCo第一个)在主流的 CV 任务 (分类、检测、分割)中填补甚至超越无监督与有监督方法之间的鸿沟,并且容易迁移到下游任务MoCo 定义了一个动态 dictionary look-up 任务,它包含1.一个队列:队列中的样本无需全部梯度回传,可以放很多负样本,让字典变得很大2.一个移动平均的编码器:让字典的特征尽可能的保持一致MoCo 利用动量的特性,缓慢的更新一个编码器,从而让中间学习到的字典中的特征尽可能保持一致,一个又大又一致的字典有利于无监督对比学习的训练1.2 引言无监督在 CV 不成功的原因是什么?原始信号空间的不同NLP 原始信号是离散的,词、词根、词缀,容易构建 tokenized dictionaries 做无监督学习,容易建模且建好的模型也好优化CV 原始信号是连续的、高维的,不像单词具有浓缩好的、简洁的语义信息,不适合构建一个字典,难以建模CV 领域近期无监督对比学习的各种方法可以被统一归纳为动态字典法anchor 当做 query而各个正负样本作为字典的 key视图把字典建模得比较好使得 query 相似的 key 具有相似的特征 value从这个角度来看,动态字典应当具有 large + consistency 的特点1.large从连续高维空间做更多的采样。字典 key 越多,表示的视觉信息越丰富,匹配时更容易找到具有区分性的本质特征。否则模型可能学到 shortcut 而不能泛化2.consistent 字典里的 key 应该由相同的 or 相似的编码器生成。否则 query 很有可能去找同一个 encoder 生成的 key而不是寻找语义相似性(另一种形式的 shortcut solution1.3 相关工作跟有监督相比,两个主要不同点是代理任务 pretext tasks 和损失目标函数 loss functions, objective functions损失函数1.判别式,比如分类2.生成式,比如重建整张图3.对比学习,目标是相似样本特征相近,并不固定,跟 encoder 输出相关4.对抗学习,衡量两个概率分布之间的差异代理任务1.denoising auto-encoders 重建整张图2.context auto-encoders 重建某个 patch3.cross-channel auto-encoders (colorization) 给图片上色当自监督信号4.pseudo-labels 图片生成伪标签a.exemplar image比如同一张图片做不同的数据增广后都属于同一个类b.patch ordering 九宫格方法:打乱了以后预测 patch 的顺序或随机选一个 patch 预测方位c.利用视频的顺序做 trackingd.做聚类的方法 clustering features不同的代理任务可以和不同形式的对比学习目标函数配对使用,思考 MoCo, CPC, CMC 分别是怎么样的配对另外,作者把相关工作归纳为动态字典法之后,总结说它们或多或少都受限于字典大小一致性问题,如图比如,同期的 SimCLR 就是第一种,正负样本对来自同一个 batch因为 google 比较有钱才训练得起来;之前的 CPC, CMC 应该也都是这种,后来的 CLIP 应该也是PS其实 MoCo queue 结构也没有吹得那么好,单从效果不计成本地来看还是 large batchsize 比较厉害(money is all youneed)后来 MoCo-v3 也换回去了。而且 KaiMing 团队后来自己的 SimSiam 也摈弃了动量编码器。不过,它的影响依旧是深远的Inst Disc 是第二种,用 memory bank 的方式 off-line 地做字典,大小可以很大但一致性欠缺其实 memory bank 加上 momentum 就是 MoCo 的雏形了,不过 MoCo 的扩展性更好(memory bank 需要存整个数据集,而MoCo 只需要从中随机抽取)1.4 框架和方法queue剥离显卡内存对字典大小的限制,让字典大小(或者说 queue 的大小)和 batch size 分开,每次从中取出前 minibatch 个元素扔掉,从数据集中随机抽取 minibatch 个元素计算并入队。队列(字典)始终是整个数据集的子集,且大小为固定的超参数momentum encoder有点强化学习目标网络的思想,减缓每次更新的剧烈程度,使得模型变得平稳一致,尽可能使字典(queue)里的key 由跟 query 类似的 encoder 生成𝜃𝑘𝑚𝜃𝑘+(1𝑚)𝜃𝑞MoCo 的代理任务 pretext task 是什么?事实上,MoCo 是一种建立模型的方法,可以和很灵活地与多种代理任务使用,这里以instance discrimination 为例损失函数为 infoNCE(info noise contrastive estimation)负样本从整个数据集中选取部分进行估计,把一个超级多的𝑁分类问题变成data sample noise samples 1+𝐾个类别来解决 softmax 不工作的问题,同时降低了计算复杂度𝑞=logexp(𝑞𝑘+/𝜏)𝐾𝑖=0exp(𝑞𝑘𝑖/𝜏)具体代码中,由于正样本就是类别0,直接把 ground truth 设为全零然后做 cross entropy loss 就行了,很巧妙Algorithm 1: 伪代码# f_q, f_k: encoder networks for query and key# queue: dictionary as a queue of K keys (CxK)# m: momentum# t: temperature1f_k.params = f_q.params initialize2for x in loader: load a minibatch x with N samples3x_q = aug(x) a randomly augmented version4x_k = aug(x) another randomly augmented version5q = f_q.forward(x_q) queries: NxC6k = f_k.forward(x_k) keys: NxC7k = k.detach() no gradient to keys8# positive logits: Nx19l_pos = bmm(q.view(N,1,C), k.view(N,C,1))10# negative logits: NxK11l_neg = mm(q.view(N,C), queue.view(C,K))12# logits: Nx(1+K)13logits = cat([l_pos, l_neg], dim=1)14# contrastive loss, Eqn.(1)15labels = zeros(N) positives are the 0-th16loss = CrossEntropyLoss(logits/t, labels)17# SGD update: query network18loss.backward()19update(f_q.params)20# momentum update: key network21f_k.params = m*f_k.params+(1-m)*f_q.params22# update dictionary23enqueue(queue, k) enqueue the current minibatch24dequeue(queue) dequeue the earliest minibatch最后还讲了一个避免 BN 信息泄露的小 trick不是很懂为什么会信息泄露?1.5 结果和讨论主要分成了两大部分进行了结果的展示1.Linear Classification Protocol将训练好的模型 freeze然后学最后一层线性层对两个主要贡献做了消融实验一个比较有意思的现象是 lr 设为了30,也启示我们对比学习和有监督学习的目标函数分布可能大不相同7个检测 or 分割的任务超越 ImageNet 有监督训练的结果,甚至有时大幅度超越2.迁移学习的效果 BN 和训练时长做了限制以得到公平的比较,感觉有点狂傲(用你的超参数打败你)另外,如果把训练数据集换成 instagram用更多数据、更大模型,性能会提升但性价比变低了可能是因为大规模数据集没有完全被利用,可以尝试开发其它的代理任务 pretext task比如 masked auto-encoding也就是两年后的 MAE震撼)总之就是效果碾压,就不细记了1.6 总结