4.9 视觉自监督学习SimCLR、BYOL与MAE

1.为什么自监督:图那么多,标签那么贵

说起来,前面5.1 节我们聊过预训练这件事,那条思路是先在海量数据上把模型养大,再拿到下游任务上去微调。可视觉这边一直有个老问题,标注太贵了。检测里给一张图画框、标类别,一张图往往要花上几分钟的人工,要标到上百万张图,开销是相当惊人的。我记得看过一本书里讲,某家大厂为了训一个检测模型,光是标注费就花了小几百万,这还不算后续返工的成本。

可网上的图呢,到处都是,而且几乎都是无标注的。把这么一大堆便宜货白白浪费掉,未免太可惜了。于是自监督学习这条思路就冒了出来,它要做的事情说白了很简单,让模型从海量无标注图像里自己学一个还不错的表示,之后再拿这个表示去配各种下游任务。

这里我先把表示这个词讲清楚。一张图本身是成千上万个像素,模型把它压成一串数值 zzzz 就叫这张图的表示,也叫特征向量。这串数要是学得好,猫的图和猫的图在表示空间里就该挨得近,猫的图和狗的图就该远一些。下游任务拿这串数去做分类、检测,就比直接啃像素轻松多了。

自监督的关键,是人为造一个监督信号出来。既然没有人工标签,那就从数据本身里挖一个。下面要讲的三种方法,SimCLR、BYOL和MAE,差别其实就在造监督信号这件事上各走各的路。说穿了,这三家各显神通,但目的都是一个,让模型学到一串能用的 zz

2.SimCLR:同一张图的两个模样

我们先讲对比学习里最有代表性的SimCLR。它的核心想法特别好懂,让模型认出同一张图的不同样子是同一个东西。

具体怎么做呢,拿一张图 xxxx 就是原图,对它做两次不同的数据增强,比如一次随机裁剪再加点颜色抖动,另一次也随机裁剪但裁的位置和颜色扰动不同,这样得到两个新图 x~1\tilde{x}_1x~2\tilde{x}_2x~\tilde{x} 读作x波浪,表示增强后的视图。这两个视图虽然长得不一样,但都来自同一张原图 xx,我们管它们叫正样本对。

SimCLR的训练流程大致这么几步。先用一个编码器 fθ()f_\theta(\cdot)x~1\tilde{x}_1x~2\tilde{x}_2 各自压成表示,记作 h1h_1h2h_2fθf_\theta 是带参数 θ\theta 的编码网络,θ\theta 就是网络里那些权重,括号里的点表示输入。然后再接一个小一些的投影头 gθ()g_\theta(\cdot),把 h1h_1h2h_2 再映射成 z1z_1z2z_2,这个 zz 才是真正参与损失计算的那一串数。投影头这一步看着多余,其实论文里实测发现加上它效果会明显好,所以才留着。

损失函数用的是InfoNCE。InfoNCE这个名字里NCE出自一种叫噪声对比估计的老方法,Info提醒我们它和信息论里的互信息有那么点关系。它的形式长这样:

L=logexp(sim(z1,z2)/τ)k=12N1[k1]exp(sim(z1,zk)/τ)\mathcal{L} = -\log \frac{\exp(\text{sim}(z_1, z_2)/\tau)}{\sum_{k=1}^{2N} \mathbb{1}_{[k \neq 1]} \exp(\text{sim}(z_1, z_k)/\tau)}

我一个个符号解释一下。 sim(u,v)\text{sim}(u, v) 是两个向量的余弦相似度,衡量两个向量方向有多接近,取值在 1-111 之间。 τ\tau 是温度系数,是个超参数,它控制分布的尖锐程度, τ\tau 越小,模型越在意那个最难的负样本。 NN 是批量大小,一个批量里有 NN 张图,两张增强视图加起来就是 2N2N 个视图。 exp\exp 是指数函数。 1[k1]\mathbb{1}_{[k \neq 1]} 是指示函数,kk 不等于 11 时取 11,等于 11 时取 00,意思是把 z1z_1 自己排除掉,不和自己做相似度。 log\log 是自然对数。 分母那一长串,就是把批量里所有其他视图都当作负样本,全部加起来。 整体再添个负号,是因为我们要最小化损失,但希望分子那项越大越好。

这个损失要做的事情,直观上就是让正样本对 z1z_1z2z_2 挨得近,同时把批量里其他图生成的视图都推开。打个比方,有点像班里分组游戏,老师让同一个同学的两张不同照片分到一组,再把别的同学的照片尽量推远,模型学着学着,就懂得哪些特征是同一个人共有的。小张之前跟我聊,说他第一次读这篇论文最直观的感受,就是这不就是把找不同反过来训成找相同嘛。

这里有个细节得提一下,SimCLR特别吃批量大小。批量越大,负样本越多,对比的效果就越好,原论文里批量开到了4096,普通实验室的显卡根本扛不住。这也是它后来被一些不用负样本的方法慢慢盖过风头的原因之一。

3.BYOL:没有负样本也行

SimCLR那么依赖负样本,工程上挺折腾的。于是有人就想,能不能干脆不要负样本呢。BYOL就是这么冒出来的,它给出一个挺让人意外的答案,能。

BYOL里有两个网络,一个叫在线网络,一个叫目标网络。在线网络和SimCLR那套很像,有编码器、投影头,还多了一个预测器 qθq_\thetaqθq_\theta 把在线网络的输出再做一次变换。目标网络只保留编码器和投影头,比在线网络少一个预测器,结构上少一截,参数也不靠梯度更新,而是把在线网络的参数慢慢地拷过来,用一个动量系数 τm\tau_m 控制这个拷贝的速度:

θtargetτmθtarget+(1τm)θonline\theta_{\text{target}} \leftarrow \tau_m \theta_{\text{target}} + (1 - \tau_m) \theta_{\text{online}}

τm\tau_m 是一个很接近 11 的数,比如 0.990.99,所以目标网络更新得特别慢,像个走路慢悠悠的老先生。θtarget\theta_{\text{target}}θonline\theta_{\text{online}} 分别是目标网络和在线网络的参数,\leftarrow 表示把右边的值赋给左边。

训练时,对一张原图 xx 做两次增强得到 x~1\tilde{x}_1x~2\tilde{x}_2。在线网络拿 x~1\tilde{x}_1 走一遍,得到预测 qθ(gθ(fθ(x~1)))q_\theta(g_\theta(f_\theta(\tilde{x}_1))),目标网络拿 x~2\tilde{x}_2 走一遍,得到目标输出 gθtarget(fθtarget(x~2))g_{\theta_{\text{target}}}(f_{\theta_{\text{target}}}(\tilde{x}_2))。然后把这两边做余弦相似度,作为损失去最小化,让在线网络的预测去贴目标网络的输出。要注意目标网络是不回传梯度的,这叫stop-gradient,损失只通过在线网络那边反传。

最让人觉得玄妙的地方就在这,没有负样本去把它推开,模型凭什么不会塌缩到一个常数解呢。所谓塌缩,就是所有图都输出同一个表示,损失照样为零,但什么也没学到。这个问题当年讨论了很久。后来大家比较一致的看法是,stop-gradient加上那个慢更新的目标网络,组合在一起形成了一种隐式的约束,让模型不得不保留信息。说起来有点像打太极,一只手推、另一只手顺势带,看着没使劲,其实劲都在里头。我之前看过一部讲木匠手艺的纪录片,老师傅带徒弟时总说手要稳、节奏要慢,BYOL的目标网络就有点这个味道。

BYOL的好处很明显,不用挑负样本,批量大小也可以开得小一些,对显卡友好得多。代价是实现细节比较敏感,stop-gradient放错位置模型就立刻塌缩,得照着论文复现,不能凭感觉乱改。

4.MAE:遮住一大半,让它自己补

第三种思路跟前两种又不一样,它走的是生成路线,叫MAE(Masked Autoencoder,掩码自编码器)。这个思路其实在NLP里早就有了,BERT就是把句子里的词随机遮掉一些让模型去猜。MAE把类似的想法搬到了视觉这边。

MAE的做法非常直接。拿一张图,先切成一个个小块,patch,就像把一张照片剪成许多小方块。然后随机遮掉很大一部分,比如遮掉 75%75\%,只留 25%25\% 给模型看。模型(通常用ViT)只处理这剩下的可见小块,最后再用一个轻量的解码器去重建被遮住那部分的原始像素。损失就是重建像素和真实像素之间的均方误差,记作 LMSE\mathcal{L}_{\text{MSE}}LMSE\mathcal{L}_{\text{MSE}} 是均方误差损失的常用记法,意思是重建像素和真实像素之差的平方取平均。

这里有两个细节特别值得说。一是为什么遮这么多。前两年大家觉得遮个 15%15\% 就够了,可MAE作者发现,视觉里图像的像素冗余度太高了,遮 15%15\% 模型靠周围像素插值就能蒙混过关,学不到什么。要遮到 75%75\% 这种极端比例,模型才会真正去理解整张图的全局结构。二是ViT(Vision Transformer,视觉Transformer)这种结构特别适合干这个,因为它本来就是按小块来处理的,遮掉一些小块对它来说特别自然。卷积网络就没这么方便,因为卷积的卷积核是个连在一起的小窗口,处理大量零散的可见小块会很别扭。

打个比方,MAE有点像让小张看一幅国画,把画的大半都用纸盖住,只露出零星几笔墨,让他猜整幅画的样子。要蒙住一大半才难,他才肯动脑子去想整体构图。只蒙一小块,他顺手就照着旁边的颜色填上了,根本不用过脑子。有个我挺喜欢的足球运动员叫梅西,他在场上经常只能看到球门的一角、对方后卫的一只手,但脑子里已经把整条进球路线补出来了,这种从局部推整体的能力,恰好是MAE想要模型学会的。

MAE的好处是简单、高效。因为它只对那 25%25\% 的可见小块做编码,编码阶段的计算量大幅下降,训练比前两种方法快不少。这一点对工程来说格外讨喜。

5.学到的表示能搬到哪儿

最后我们说说,费这么大劲自监督训出来的表示,到底能派什么用场。

答案是下游迁移。模型在自监督阶段学好之后,那个编码器 fθf_\theta 就是一个相当通用的特征提取器。把它接到下游任务上,比如目标检测、语义分割,只需要再喂一小部分有标注的数据做微调,就能拿到很不错的成绩。这正好接上5.1 节我们讲过的预训练范式,自监督把怎么造预训练数据这件事从靠人工标变成了靠数据本身,从根上把成本降了下来。

说起来,这条线其实是视觉走向基础模型的重要一步。再往大了讲,后来把图像和文本一起做的CLIP,把对比学习的思路用到了图文对上,让模型同时理解图和文字。MAE这种思路也被用到了各种视觉大模型预训练里。这些工作合在一起,才有了今天大家嘴里常说的视觉基础模型。1.4 节我们讲概率信息论时提到过,从数据里估计分布本身就含着一种理解,自监督学习恰好把这句话落到了工程上。

这一篇我们走了三家,SimCLR靠对比、BYOL靠预测、MAE靠重建,路子不一样,目的地都差不多,让模型自己从海量无标注图像里把世界看明白。下一章见。

练习

Q1. SimCLR、BYOL、MAE 这三家做自监督的思路分别是什么?它们造监督信号的方式有什么不同?

SimCLR 走对比路线:对同一张图做两次增强得到正样本对,用 InfoNCE 损失让正样本对的表示挨近、把批量里其他图的视图推开,靠"找相同"学表示。BYOL 走预测路线:有在线网络和目标网络,让在线网络的预测去贴目标网络的输出,靠 stop-gradient 和慢更新的目标网络形成隐式约束,不需要负样本。MAE 走生成路线:把图切成小块、随机遮掉一大半(如 75%),让模型(通常用 ViT)只看可见小块去重建被遮像素,靠"补全"学表示。三家各显神通,目的都是让模型从无标注图里学一串能用的表示。

Q2. MAE 为什么要把图遮掉高达 75%,而不是像 BERT 那样只遮 15%?

因为图像的像素冗余度太高了。只遮 15% 模型靠周围像素插值就能蒙混过关,学不到什么;要遮到 75% 这种极端比例,模型才会真正去理解整张图的全局结构、被迫动脑子补全。这也是 ViT 特别适合干这活的原因——它本来就按小块处理,遮掉一些小块很自然;卷积网络的卷积核是连在一起的小窗口,处理大量零散可见小块会很别扭。

Q3. BYOL 没有负样本,模型凭什么不会塌缩成所有图都输出同一个表示?SimCLR 又为什么特别吃批量大小?

BYOL 靠 stop-gradient(目标网络不回传梯度)加上那个用动量系数 τm\tau_m 慢更新(如 0.99)的目标网络,两者组合形成一种隐式约束,让模型不得不保留信息,不至于塌缩。但实现细节敏感,stop-gradient 放错位置就立刻塌缩。SimCLR 特别吃批量大小是因为它的对比效果依赖负样本:批量越大负样本越多,对比越有效,原论文批量开到 4096,普通实验室显卡根本扛不住,这也是它后来被不用负样本的方法慢慢盖过风头的原因之一。

相关标签
深度学习计算机视觉自监督SimCLR