自监督学习是无监督学习中的一种,其主要特点
有三:1)不需要人工标记的标签;2)学习数据本身的特征;3)将学习好的模型用于下游任务。
自监督学习的优势
在于:1)自监督学习不需要大量人工标注的标签,节省人力和时间成本。很适用于医疗等现实领域。2)传统的监督学习用的是带标签的数据,因此模型学到的往往是局限性的内容;而自监督学习用的无标签的数据,模型更多的学到的是数据本身的特征,没有限制,也有更多可能性,因此自监督模型更容易迁移到别的任务。
当前自监督学习在自然语言处理方向中运用的非常广泛,但在计算机视觉领域中仍是监督学习占据主导地位,因为它们的信号空间不同,自然语言任务具有离散的信号空间(比如单词、子单词等),然而图像空间是一个连续的高维空间,需要更进一步的关注字典的构建。
自监督学习涉及内容
- 辅助任务(Pretext Task):辅助任务是可以认为是一种为达到特定训练任务而设计的间接任务,并不是真正的任务,只是用来学习更好的特征表示。pretext任务的好处是为了简化原任务的求解。主要的辅助任务包括:图像着色、图像修复等、图像补丁。
- 下游任务(Downstream Task):下游任务的作用之一是在得到自监督训练好的模型后,用带标签的数据进行有监督学习,来评价模型的正确率,因为数据的ground-truth仍是由人工标签来确定的,但是这些有监督训练会带有一定的约束,如少量的训练样本或较短的训练时间等。作用之二是转移自监督模型学到的特征,将其用于其他任务,只需要少量的学习(迁移学习)就可以在自监督模型基础上开展新的应用。
- 损失函数(Loss function)。通常使用的是infoNCE。
对比学习是自监督学习的其中一个类别(另一个为生成式方法),是通过将数据分别与正例样本和负例样本在特征空间进行对比,来学习样本的特征表示。对比学习主要的难点在于如何构造正负样本
。
相比较于生成式方法,对比学习不过分关注像素细节,而是更关注抽象的语义信息,因此也更易优化。目前在分类任务上,自监督学习已经接近监督学习的效果,同时在一些检测、分割的下游任务上甚至超越了监督学习作为 pre-train 的方法。
对比学习一般范式:
对比学习的目的就是,对于数据 x,要学得一个编码器 f ,使得与之相似的正样本 x+ 与 x 之间的距离越近,与不相似的负样本 x- 之间的距离越远。
那么怎么得到与之相似的正样本 x+ 呢,方法就是用数据增强,常见的方法有:裁剪(crop),反转(flip),高斯模糊(Gaussian Blur)等。而与之不相似的负样本 x- 就是指其他的数据。
0)q是query,表示查询;k是一个数据样本。
1)对N个原始数据图像进行图像增强,得到各自的xq和xk。
2)经过fq和fk两个编码器后(q=fq(xq),k=fk(xk)),得到特征表示q和k。
3)计算q与字典中的正例k+的正类logits,q与字典中的负利k-的负类logits,二者拼接,计算损失。
4)反向传播,更新fq。
5)根据动量更新公式,更新fk。
6)入队当前mini_batch的k,出队最来的mini_batch的k。
本篇文章专攻计算机视觉领域的自监督模型,考虑到图像空间的高位特性,因此自监督学习在计算机视觉中需要更关注字典的构建,字典应具备一下两个特点:
- 字典大
- 字典具有一致性
在传统的对比学习中,字典的大小就是mini_batch的大小,但这往往会因此GPU内存和算力的限制而不能太大。所以MoCo用队列
来储存字典。队列的更新方法是:当前的mini_batch完成编码后就入队,队列中最老的mini_batch出队,因此该字典总是所有数据的一个子集。这样,队列的大小就和mini_batch的大小解耦了,从而就可以实现一个大
队列。
动量更新使得字典变大,但同时也让反向传播更新编码器变得困难,因为梯度要传播到队列中所有的样本。因此MoCo提出,只梯度更新fq编码器,fk编码器复制fq的参数,而不进行梯度更新
。但是,仅仅简单的复制是远远不够的,这样做的实验结果很差,因为fq是查询队列,因此θq是不断更新的且更新速度很快,θk要更新需要复制θq,但这会导致正确率不高,因此改为采用动量更新
,让θk的更新更具有连续性。所以,fk编码器的更新还需要根据动量更新公式:
其中,θq是编码器fq的参数,θk是编码器fk的参数,m是动量参数,属于[0,1]。上面的公式中,只有θq是通过反向传播更新的。较大的m值,如0.999效果较好。
复制参数值 + 动量更新公式 使得MoCo的字典可以保持与查询q具有一致性
。
其主要问题是它使用当前batch_size作为字典的大小,受限于GPU,字典不会太大。尽管有人提出了可以使字典变大的方法,但由于需要特殊的网络设计,对于将网络迁移到下游任务并不友好。
该方法设立memory bak,字典由数据集中的所有样本的特征表示的子集组成,每个mini_batch的字典都是从memory bank随机抽取,因此它有一个很大的字典。尽管左边的编码器fq一直在更新,但由于字典很大,memory bank中的特征表示是很多之前步骤中的编码器的结果,这也就是说,字典的一致性很难保证。即使有人研究用动量去更新样本特征表示,但这样必须储存所有样本,内存效率不如MoCo高。
本文采用的损失函数是InfoNCE
,该损失函数是一个K+1路SoftMax分类器的对数损失:
其中,q是查询的特征表示,k+是一个正样本的特征表示,ki是K个负样本的特征表示。T是温度超参数,本文实验中被设置为0.07。
由于MoCo的重点不是设计一个新的辅助任务,因此他们采用的是实例识别任务
。当然,辅助任务可以是任意的。
在随机数据增强下,对同一张图像随机裁剪得到两个视图,这两个视图可以被成为正样本对。如果一个q和一个k来自同一样本图像,它们也为正样本对,否则为负样本对。对于每个mini_batch,编码后的q和相应的k形成了正样本对,负样本来自队列。
机器学习中假设数据是IID独立同分布的,未来达到这一假设,需要在网络中的每一层加上Batch Bormalization使得每一层的输入保持同分布。但在MoCo中,当编码器fq和fk都使用BN后,BN 会阻止模型学到更好的特征表示,因为网络会欺骗辅助任务,找到损失最小的方法,而不去学习更好的表示,何凯明团队推测这可能是由BN引起的,每个batch内的样本之间计算mean和std导致信息泄露,产生退化解。
于是,他们提出采用Shuffling BN。通过多GPU训练,分开计算BN,并且shuffle不同GPU上产生的BN信息来解决这个问题。对于fk,在将当前mini_batch加入GPU之前在mini_batch内打乱其样本顺序;对于fq,其mini_batch中的样本顺序并没有被改变。
编码器可以是任意的卷积神经网络
,fq和fk可以是完全相同的,也看可以是部分相同或不同的。本文用的是ResNet,其最后一个全连接层具有固定维数的输出——128维,这个输出由L2-范数进行归一化。
数据增强设置遵循的方法是:从一个随机调整大小的图像中提取224×224像素的裁剪,然后进行随机颜色抖动、随机水平翻转和随机灰度转换,用PyTorch实现。
ImageNet-1M:数据量一百万,该数据集在类分布上很平衡。
Instagram-1B:数据量十亿,该数据集未被整理好,且分布不平衡,更加接近真实世界的数据,用来证明MoCo的良好扩展性。
优化器:SGD,权重衰减率0.0001,SGD动量0.9。
对于ImageNet-1M:学习率0.03,8GPU,batch_size128。
对于Instagram-1B:学习率0.12,64GPU,batch_size1024。
通过消融实验,得出以下结论:
① k越大越好,也就是字典越大越好。
② 动量更新参数m应取值在0.99∼0.9999,表明一个缓慢进展的编码器是有益的。
选取的下游任务是PASCAL VOC和COCO。
由于无监督学习的特征分布和有监督学习到的特征分布是很不一样的,在将无监督预训练模型应用到下游任务时,不能每个任务的分类头都进行参数搜索,这样就失去了无监督学习的意义,解决方法是:归一化,然后整个模型进行参数微调。BN层用的是synchronized BN,即多卡训练时,把所有卡的信息都进行统计,计算总的running mean 和running variance,然后更新BN层,让特征归一化更彻底,模型训练更稳定。
[1] https://zhuanlan.zhihu.com/p/141172794?ivk_sa=1024320u
[2] https://zhuanlan.zhihu.com/p/132550481
[3] https://blog.csdn.net/weixin_42764932/article/details/112768710?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-2-112768710.pc_agg_new_rank&utm_term=%E5%AF%B9%E6%AF%94%E5%AD%A6%E4%B9%A0%E7%9A%84momentum&spm=1000.2123.3001.4430
[4] https://www.cnblogs.com/eilearn/p/9780696.html