Crd233's Notebook
Home
Courses
Languages
Math
CG
CV
AI
Reading
其它
— order: 11 —
1
Momentum Contrast for Unsupervised Visual
Representation Learning
●
时间:
2019.11
1.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 solution
)
1.3
相关工作
●
跟有监督相比,两个主要不同点是代理任务
pretext tasks
和损失目标函数
loss functions, objective functions
○
损失函数
1.
判别式,比如分类
2.
生成式,比如重建整张图
3.
对比学习,目标是相似样本特征相近,并不固定,跟
encoder
输出相关
4.
对抗学习,衡量两个概率分布之间的差异
○
代理任务
1.
denoising auto-encoders
重建整张图
2.
context auto-encoders
重建某个
patch
3.
cross-channel auto-encoders (colorization)
给图片上色当自监督信号
4.
pseudo-labels
图片生成伪标签
a.
exemplar image
,
比如同一张图片做不同的数据增广后都属于同一个类
b.
patch ordering
九宫格方法:打乱了以后预测
patch
的顺序或随机选一个
patch
预测方位
c.
利用视频的顺序做
tracking
d.
做聚类的方法
clustering features
○
不同的代理任务可以和不同形式的对比学习目标函数配对使用,思考
MoCo, CPC, CMC
分别是怎么样的配对
●
另外,作者把相关工作归纳为动态字典法之后,总结说它们或多或少都受限于字典
大小
和
一致性
问题,如图
○
比如,同期的
SimCLR
就是第一种,正负样本对来自同一个
batch
,
因为
google
比较有钱才训练得起来;之前的
CPC, CMC
应该
也都是这种,后来的
CLIP
应该也是
PS
:
其实
MoCo
的
queue
结构也没有吹得那么好,单从效果不计成本地来看还是
large batchsize
比较厉害
(
money is all you
need)
,
后来
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
不工作的问题,同时降低了计算复杂度
ℒ
𝑞
=
−
log
exp
(
𝑞
⋅
𝑘
+
/
𝜏
)
∑
𝐾
𝑖
=
0
exp
(
𝑞
⋅
𝑘
𝑖
/
𝜏
)
○
具体代码中,由于正样本就是类别
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: temperature
1
f_k.params = f_q.params
▷
initialize
2
for x in loader:
▷
load a minibatch x with N samples
3
x_q = aug(x)
▷
a randomly augmented version
4
x_k = aug(x)
▷
another randomly augmented version
5
q = f_q.forward(x_q)
▷
queries: NxC
6
k = f_k.forward(x_k)
▷
keys: NxC
7
k = k.detach()
▷
no gradient to keys
8
# positive logits: Nx1
9
l_pos = bmm(q.view(N,1,C), k.view(N,C,1))
10
# negative logits: NxK
11
l_neg = mm(q.view(N,C), queue.view(C,K))
12
# logits: Nx(1+K)
13
logits = cat([l_pos, l_neg], dim=1)
14
# contrastive loss, Eqn.(1)
15
labels = zeros(N)
▷
positives are the 0-th
16
loss = CrossEntropyLoss(logits/t, labels)
17
# SGD update: query network
18
loss.backward()
19
update(f_q.params)
20
# momentum update: key network
21
f_k.params = m*f_k.params+(1-m)*f_q.params
22
# update dictionary
23
enqueue(queue, k)
▷
enqueue the current minibatch
24
dequeue(queue)
▷
dequeue the earliest minibatch
●
最后还讲了一个避免
BN
信息泄露的小
trick
,
不是很懂为什么会信息泄露?
1.5
结果和讨论
●
主要分成了两大部分进行了结果的展示
1.
Linear Classification Protocol
:
将训练好的模型
freeze
,
然后学最后一层线性层
○
对两个主要贡献做了消融实验
○
一个比较有意思的现象是
lr
设为了
3
0
,也启示我们对比学习和有监督学习的目标函数分布可能大不相同
○
在
7
个检测
or
分割的任务超越
ImageNet
有监督训练的结果,甚至有时大幅度超越
2.
迁移学习的效果
○
对
BN
和训练时长做了限制以得到公平的比较,感觉有点狂傲(用你的超参数打败你)
●
另外,如果把训练数据集换成
instagram
,
用更多数据、更大模型,性能会提升但性价比变低了
○
可能是因为大规模数据集没有完全被利用,可以尝试开发其它的代理任务
pretext task
,
比如
masked auto-encoding
(
也就是两年
后的
MAE
,
震撼)
●
总之就是效果碾压,就不细记了
1.6
总结