Press "Enter" to skip to content

深度了解自监督学习,就看这篇解读 !Hinton团队力作:SimCLR系列

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

作者丨科技猛兽

 

本文目录

 

1 原理分析 (ICML 2020)

 

1.1 数据增强

 

1.2 通过Encoder获取图片表征

 

1.3 预测头

 

1.4 相似图片输出更接近

 

1.5 对下游任务Fine-tune

 

2 SimCLR v2原理分析 (NIPS 2020)

 

2.1 SimCLR v2 10分钟简介:SimCLR v2 和 SimCLR 相比做了哪些改进?

 

2.2 SimCLR v2 实验设置

 

科技猛兽:Self-Supervised Learning系列解读 (目录)

 

https://zhuanlan.zhihu.com/p/381354026

 

Self-Supervised Learning ,又称为自监督学习,我们知道一般机器学习分为有监督学习,无监督学习和强化学习。 而 Self-Supervised Learning 是无监督学习里面的一种,主要是希望能够学习到一种 通用的特征表达 用于 下游任务 (Downstream Tasks) 。 其主要的方式就是通过自己监督自己。 作为代表作的 kaiming 的 MoCo 引发一波热议, Yann Lecun也在 AAAI 上讲 Self-Supervised Learning 是未来的大势所趋。 所以在这个系列中,我会系统地解读 Self-Supervised Learning 的经典工作。

 

总结下 Self-Supervised Learning 的方法,用 4 个英文单词概括一下就是:

 

Unsupervised Pre-train, Supervised Fine-tune.

 

这段话先放在这里,可能你现在还不一定完全理解,后面还会再次提到它。

 

在预训练阶段我们使用 无标签的数据集 (unlabeled data) ,因为有标签的数据集它 很贵啊 ,打标签得要多少人工劳力去标注,那成本是相当高的,所以这玩意太贵。相反,无标签的数据集网上随便到处爬,它 便宜 。在训练模型参数的时候,我们不追求把这个参数用带标签数据从 初始化的一张白纸 给一步训练到位,原因就是数据集太贵。于是 Self-Supervised Learning 就想先把参数从 一张白纸 训练到 初步成型 ,再从 初步成型 训练到 完全成型 。注意这是2个阶段。所以预训练模型的时候,就是模型参数从 一张白纸 到 初步成型 的这个过程,还是用无标签数据集。等我把模型参数训练个八九不离十,这时候再根据你 下游任务 (Downstream Tasks) 的不同去用带标签的数据集把参数训练到 完全成型 ,那这时用的数据集量就不用太多了,因为参数经过了第1阶段就已经训练得差不多了。

 

第1个阶段不涉及任何下游任务,就是拿着一堆无标签的数据去预训练,没有特定的任务,这个话用官方语言表达叫做: in a task-agnostic way 。第2个阶段涉及下游任务,就是拿着一堆带标签的数据去在下游任务上 Fine-tune,这个话用官方语言表达叫做: in a task-specific way (这俩英文很重要啊,会不断出现) 。

 

以上这些话就是 Self-Supervised Learning 的核心思想,如下图所示,后面还会再次提到它。

Self-Supervised Learning经典工作的分类如下图1所示。在上篇文章中主要介绍了 Self-Supervised Learning 在 NLP 领域 的经典工作:BERT模型的原理及其变体GPT, MASS, BART, ELECTRA等等,这些方法都是属于 Prediction 类别的。本文主要介绍Self-Supervised Learning 在 CV 领域 的经典工作之一:SimCLR和SimCLR v2,它们都是属于 Contrastive 类别的。

 

那 Prediction 类别和 Constractive 类别有什幺不同呢?

 

Prediction类别比如说BERT,是会用一堆没有label的句子去训练BERT做填空题 (详见上篇文章):给一个句子随机盖住 (mask掉) 一个token,输入这个BERT,期望它输出盖住的部分,使用这种办法让BERT无监督地学习到 结合上下文做Embedding的能力 ,学习的过程是一种Prediction的行为。 Contrastive 类别方法并不要求模型能够重建原始输入,而是希望模型能够在特征空间上对不同的输入进行分辨,这也会在SimCLR的训练过程中体现。

图1:Self-Supervised Learning 经典工作的分类

1 SimCLR 原理分析

 

论文名称:A Simple Framework for Contrastive Learning of Visual Representations

 

论文地址:

 

https://arxiv.org/pdf/2002.05709.pdf

 

SimCLR是Hinton团队在 Self-Supervised Learning 领域的一个系列的经典工作。先来通过图2直观地感受下它的性能:SimCLR (4×) 这个模型可以在 ImageNet 上面达到 76.5% 的 Top 1 Accuracy, 比当时的 SOTA 模型高了7个点 。如果把这个预训练模型用 1%的ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,SimCLR 就可以再达到 85.5% 的 Top 5 Accuracy,也就是再涨10个点。

图2:SimCLR性能

那根据上一篇文章BERT的描述,我们说 Self-Supervised Learning 的目的一般是使用大量的无 label 的资料去Pre-train一个模型,这幺做的原因是无 label 的资料获取比较容易,且数量一般相当庞大,我们希望先用这些廉价的资料获得一个预训练的模型,接着根据下游任务的不同在不同的有 label 数据集上进行 Fine-tune 即可 。

 

作为 Self-Supervised Learning 的工作之一,SimCLR 自然也遵循这样的思想。我们回忆一下之前 BERT 会用一堆没有label的句子去训练BERT做填空题 (详见上篇文章):给一个句子随机盖住 (mask掉) 一个token,输入这个BERT,期望它输出盖住的部分。这就是BERT进行自监督学习的做法,那幺在 SimCLR 里面是如何做的呢?一个核心的词汇叫做: Contrastive 。

 

这个词翻译成中文是 对比 的意思,它的实质就是: 试图教机器区分相似和不相似的事物 。

图3:对比学习试图教机器区分相似和不相似的事物

这个话是什幺意思呢?比如说现在我们有任意的 4 张 images,如下图4所示。前两张都是dog 这个类别,后两张是其他类别,以第1张图为例,我们就希望 它与第2张图的相似性越高越好,而与第3,第4张图的相似性越低越好 。

 

但是以上做法 其实都是很理想的情形 ,因为:

 

 

我们只有大堆images,没有任何标签,不知道哪些是 dog 这个类的,哪些是其他类的。

 

没办法找出哪些图片应该去 Maximize Similarity,哪些应该去 Minimize Similarity。

 

图4:试图教机器区分相似和不相似的事物

所以,SimCLR是怎幺解决这个问题的呢?它的framework如下图5所示:

 

假设现在有 1张 任意的图片 ,叫做Original Image,先对它做数据增强,得到2张增强以后的图片 。注意数据增强的方式有以下3种:

 

随机裁剪之后再resize成原来的大小 (Random cropping followed by resize back to the original size)。

 

随机色彩失真 (Random color distortions)。

 

随机高斯模糊 (Random Gaussian Deblur)。

 

接下来把增强后的图片输入到Encoder里面,注意这2个Encoder是共享参数的,得到representation ,再把 继续通过 Projection head 得到 representation ,这里的2个 Projection head 依旧是共享参数的,且其具体的结构表达式是:

 

接下来的目标就是最大化同一张图片得到的。

图5:SimCLR框架

以上是对SinCLR框架的较为笼统的叙述,下面具体地看每一步的做法:

 

回到起点,一开始我们有的training corpus就是一大堆 unlabeled images,如下图6所示。

图6:我们有的training corpus

 

1.1 数据增强

 

比如batch size的大小是,实际使用的batch size是8192,为了方便我们假设 。

图7:Batch Size=2

注意数据增强的方式有以下3种:

 

随机裁剪之后再resize成原来的大小 (Random cropping followed by resize back to the original size)。代码:

 

torchvision:transforms:RandomResizedCrop


随机色彩失真 (Random color distortions)。代码:

 

from torchvision import transforms
def get_color_distortion(s=1.0):
# s is the strength of color distortion.
    color_jitter = transforms.ColorJitter(0.8*s, 0.8*s, 0.8*s, 0.2*s)
    rnd_color_jitter = transforms.RandomApply([color_jitter], p=0.8)
    rnd_gray = transforms.RandomGrayscale(p=0.2)
    color_distort = transforms.Compose([
    rnd_color_jitter,
    rnd_gray])


    return color_distort


随机高斯模糊 (Random Gaussian Deblur)。

 

random (crop + flip + color jitter + grayscale)



图8:对Input Image进行数据增强

对每张图片我们得到2个不同的数据增强结果,所以1个Batch 一共有 4 个 Image。

图9:对1个Batch的数据做增强,每个图片得到2个结果

 

1.2 通过Encoder获取图片表征

 

第一步得到的2张图片会通过Encoder获取图片的表征,如下图10所示。所用的编码器是通用的,可以用其他架构代替。下面显示的2个编码器共享权重,我们得到向量 。

图10:通过Encoder获取图片表征

本文使用了 ResNet-50 作为 Encoder ,输出是 2048 维的向量 。

 

1.3 预测头

 

Encoder 得到的2个representation再通过Prediction head ()进一步提特征,预测头是一个2层的MLP,将2048维的向量 进一步映射到128维隐空间中,得到新的representation 。

图11:预测头

 

1.4 相似图片输出更接近

 

到这一步以后对于每个Batch,我们得到了如下图12所示的Representation。

图12:最终得到的Representation

首先定义Representation之间的相似度:使用余弦相似度Cosine Similarity:

Cosine Similarity把计算两张 Augmented Images的相似度转化成了计算两个Projected Representation 的相似度,定义为:

 

式中,是可调节的Temperature 参数。它能够scale 输入并扩展余弦相似度 [-1, 1] 这个范围。

 

使用上述公式计算batch里面的每个Augmented Images的成对余弦相似度。如下图13所示,在理想情况下,狗的增强图像之间的相似度会很高,而狗和鲸鱼图像之间的相似度会较低。

图13:Augmented Images的余弦相似度

现在我们有了衡量相似度的办法,但是这还不够,要最终转化成一个能够优化的 Loss Function 才可以。

 

SimCLR用了一种叫做 NT-Xent loss ( Normalized Temperature-Scaled Cross-Entropy Loss )的对比学习损失函数。

 

我们先拿出Batch里面的第1个Pair:

图14:依次拿出Batch里面的每个Pair

使用 softmax 函数来获得这两个图像相似的概率:

图15:使用 softmax 函数来获得这两个图像相似的概率

这种 softmax 计算等价于获得第2张增强的狗的图像与该对中的第1张狗的图像最相似的概率。在这里,分母中的其余的项都是其他图片的增强之后的图片,也是negative samples。

 

所以我们希望上面的softmax的结果尽量大,所以损失函数取了softmax的负对数:

图16:损失函数取softmax的负对数

再对同一对图片交换位置以后计算损失:

图17:同一对图片交换位置以后计算损失

最后,计算每个Batch里面的所有Pair的损失之和取平均:

图18:每个Batch里面的所有Pair的损失之和取平均

 

1.5 对下游任务Fine-tune

 

至此我们通过对比学习,巧妙地在没有任何标签的情况下训练好了 SimCLR 模型,使得其Encoder的输出可以像正常有监督训练的模型一样表示图片的Representation信息。所以接下来就是利用这些 Representation的时候了,也就是在下游任务上Fine-tune。一旦 SimCLR 模型在对比学习任务上得到训练,它就可以用于迁移学习,如 ImageNet 分类,如下图19所示。此时在下游任务上 Fine-tune 模型时需要labeled data,但是数据量可以很小了。

图19:对下游任务Fine-tune

性能:

 

SimCLR (4×) 这个模型可以在 ImageNet 上面达到 76.5% 的 Top 1 Accuracy, 比当时的 SOTA 模型高了7个点 。如果把这个预训练模型用 1%的ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,SimCLR 就可以再达到 85.5% 的 Top 5 Accuracy,也就是再涨10个点。

 

FAQ1:这个 76.5% 和 85.5% 是怎幺得到的呢?

 

答1:76.5% 是通过Linear Evaluation得到的。

 

按照上面的方式进行完Pre-train之后,Encoder部分和Projection head部分的权重也就确定了。那幺这个时候我们去掉Projection head的部分,在Encoder输出的之后再添加一个 线性分类器 (Linear Classifier) ,它其实就是一个FC层。那幺我们使用全部的 ImageNet 去训练这个 Linear Classifier ,具体方法是把预训练部分,即 之前的权重frozen住,只训练线性分类器的参数,那幺 Test Accuracy 就作为 a proxy for representation quality,就是76.5%。

 

85.5% 是通过Fine-tuning得到的。

 

按照上面的方式进行完Pre-train之后,Encoder部分和Projection head部分的权重也就确定了。那幺这个时候我们去掉Projection head的部分,在Encoder输出的之后再添加一个 线性分类器 (Linear Classifier) ,它其实就是一个FC层。那幺我们使用 1%的ImageNet 的标签 去训练整个网络 ,不固定 Encoder 的权重了。那幺最后的 Test Accuracy 就是85.5%。

 

Linear Evaluation 和 Fine-tuning的精度的关系如下图20所示:当Linear Evaluation 的精度达到76.5% Top1 Accuracy时,Fine-tuning的精度达到了50多,因为Fine-tuning 只使用了1%的标签,而Linear Evaluation 使用了100%的标签。

图20:Linear Evaluation 和 Fine-tuning的精度的关系

FAQ2:Projection head 一定要使用非线性层吗?

 

答2:不一定。作者尝试了3种不同的 Projection head 的办法,分别是:Non-Linear, Linear 层和 Identity mapping,结果如下图21所示。发现还是把Projection head设置成非线性层 Non-Linear 比较好。Non-Linear 比 Linear 层要涨3%的Top 1 Accuracy,比 Identity mapping 层要涨10%的Top 1 Accuracy。

 

而且,作者的另一个发现是 Projection head 前面的 hidden layer 相比于 Projection head后面的 hidden layer 更好。那这个更好是什幺意思呢?

 

就是假设我们把 Projection head 前面的 hidden layer作为图片的representation的话,那幺经过线性分类层得到的模型性能是好的。如果把Projection head 后面的 hidden layer作为图片的representation的话,那幺经过线性分类层得到的模型性能不好,如下图22所示,是对 或者 分别训练一个额外的MLP, 或者 的hidden dimension 都是2048,性能如图22。

图21:不同的 Projection head 的办法的结果

图22:Projection head 前面的 hidden layer 相比于 Projection head后面的 hidden layer 更好

FAQ3:NT-Xent loss (Normalized Temperature-Scaled Cross-Entropy Loss)的对比学习损失函数如何代码实现?

 

答3:

 

import tensorflow as tf
import numpy as np


def contrastive_loss(out,out_aug,batch_size=128,hidden_norm=False,temperature=1.0):
    if hidden_norm:
        out=tf.nn.l2_normalize(out,-1)
        out_aug=tf.nn.l2_normalize(out_aug,-1)
    INF = np.inf
    labels = tf.one_hot(tf.range(batch_size), batch_size * 2) #[batch_size,2*batch_size]
    masks = tf.one_hot(tf.range(batch_size), batch_size) #[batch_size,batch_size]
    logits_aa = tf.matmul(out, out, transpose_b=True) / temperature #[batch_size,batch_size]
    logits_bb = tf.matmul(out_aug, out_aug, transpose_b=True) / temperature #[batch_size,batch_size]
    logits_aa = logits_aa - masks * INF # remove the same samples in out
    logits_bb = logits_bb - masks * INF # remove the same samples in out_aug
    logits_ab = tf.matmul(out, out_aug, transpose_b=True) / temperature
    logits_ba = tf.matmul(out_aug, out, transpose_b=True) / temperature
    loss_a = tf.losses.softmax_cross_entropy(
        labels, tf.concat([logits_ab, logits_aa], 1))
    loss_b = tf.losses.softmax_cross_entropy(
        labels, tf.concat([logits_ba, logits_bb], 1))
    loss=loss_a+loss_b
    return loss,logits_ab


'''
假设batch_size=3, out 和 out_aug 分别代码 原始数据和增强数据的representation
out : [a1,a2,a3] 
out_aug : [b1,b2,b3] 


labels:
[batch_size,2*batch_size] batch_size=3 
1 0 0 0 0 0 
0 1 0 0 0 0 
0 0 1 0 0 0 


mask:
 [batch_size,batch_size]
1 0 0
0 1 0
0 0 1


logits_aa [batch_size,batch_size]
a1*a1, a1*a2, a1*a3 
a2*a1, a2*a2, a2*a3  
a3*a1, a3*a2, a3*a3 


logits_bb [batch_size,batch_size]
b1*b1, b1*b2, b1*b3 
b2*b1, b2*b2, b2*b3 
b3*b1, b3*b2, b3*b3 


logits_aa - INF*mask # delete same samples
-INF,  a1*a2,  a1*a3 
a2*a1, -INF,  a2*a3 
a3*a1, a3*a2,  -INF 


logits_bb - INF*mask  # delete same samples
-INF,  b1*b2, b1*b3 
b2*b1, -INF,  b2*b3 
b3*b1, b3*b2, -INF 


logits_ab [batch_size,batch_size]
a1*b1, a1*b2, a1*b3 
a2*b1, a2*b2, a2*b3 
a3*b1, a3*b2, a3*b3


logtis_ba [batch_size,batch_size]
b1*a1, b1*a2,  b1*a3 
b2*a1, b2*a2, b2*a3
b3*a1, b3*a2, b3*a3


concat[logits_ab,logits_aa]:
a1*b1, a1*b2, a1*b3,  -INF,  a1*a2, a1*a3 
a2*b1, a2*b2, a2*b3, a2*a1, -INF, a2*a3
a3*b1, a3*b2, a3*b3, a3*a1, a3*a2, -INF
only a1*b1, a2*b2, a3*b3  are positives


concat [logits_ab,logits_bb]:
b1*a1, b1*a2,  b1*a3, -INF,  b1*b2, b1*b3 
b2*a1, b2*a2, b2*a3, b2*b1, -INF, b2*b3
b3*a1, b3*a2, b3*a3, b3*b1, b3*b2, -INF
only b1*a1, b2*a2, b3*a3  are positives, so calculate the softmax_cross_entropy with labels


'''


简单分析下代码最后会得到:

 

a1*b1, a1*b2, a1*b3,  -INF,  a1*a2, a1*a3


对它做softmax,这里的 a1*b1 就代表第1张图片的2个 Augmented Images 的 similarity,a1*b2 第1张图片的第1个 Augmented Images 和第2张图片的第2个Augmented Images 的similarity。

 

FAQ4:SimCLR 的性能与 Batch size 的大小和训练的长度有关吗?

 

答4:有关系。如下图23所示,作者发现当使用较小的 training epochs 时,大的 Batch size 的性能显着优于小的 Batch size 的性能。作者发现当使用较大的 training epochs 时,大的 Batch size 的性能和小的 Batch size 的性能越来越接近。这一点其实很好理解:在对比学习中,较大的 Batch size 提供更多的 negative examples,能促进收敛。更长的 training epochs 也提供了更多的 negative examples,改善结果。

图23:SimCLR 的性能与 Batch size 的大小的关系

2 SimCLR v2原理分析

 

论文名称:Big Self-Supervised Models are Strong Semi-Supervised Learners

 

论文地址:

 

https://arxiv.org/pdf/2006.10029.pdf

 

2.1 SimCLR v2 10分钟简介:SimCLR v2 和 SimCLR 相比做了哪些改进?

 

上一节我们介绍了 SimCLR 的原理,结合上篇文章介绍的 BERT 的原理 (再放一遍链接),我们

 

科技猛兽:Self-Supervised Learning 超详细解读 (一):大规模预训练模型BERT

 

https://zhuanlan.zhihu.com/p/378360224

 

可以总结下 Self-Supervised Learning 的方法,用4个英文单词概括一下就是:

 

Unsupervised Pre-train, Supervised Fine-tune.

 

在预训练阶段我们使用 无标签的数据集 (unlabeled data) ,因为有标签的数据集它 很贵啊 ,打标签得要多少人工劳力去标注,那成本是相当高的,所以这玩意太贵。相反,无标签的数据集网上随便到处爬,它 便宜 。在训练模型参数的时候,我们不追求把这个参数用带标签数据从 初始化的一张白纸 给一步训练到位,原因就是数据集太贵。于是 Self-Supervised Learning 就想先把参数从 一张白纸 训练到 初步成型 ,再从 初步成型 训练到 完全成型 。注意这是2个阶段。所以预训练模型的时候,就是模型参数从 一张白纸 到 初步成型 的这个过程,还是用无标签数据集。等我把模型参数训练个八九不离十,这时候再根据你 下游任务 (Downstream Tasks) 的不同去用带标签的数据集把参数训练到 完全成型 ,那这时用的数据集量就不用太多了,因为参数经过了第1阶段就已经训练得差不多了。

 

第1个阶段不涉及任何下游任务,就是拿着一堆无标签的数据去预训练,没有特定的任务,这个话用官方语言表达叫做:in a task-agnostic way。第2个阶段涉及下游任务,就是拿着一堆带标签的数据去在下游任务上Fine-tune,这个话用官方语言表达叫做:in a task-specific way。

 

Hinton老爷子这个组的第 1 个版本 SimCLR 好像2月份才刚发布不久,在 Hinton 老爷子的带领下,没过几个月立马升级到了 SimCLR v2。v2 相比 v1 将 SOTA 结果提升了大约 22 个点左右,这波操作真稳。

 

问:SimCLR v2 和 SimCLR 相比做了哪些改进?

 

答:SimCLR v2 的第 1 个发现是:

 

在使用无标签数据集做 Pre-train 的这一步中,模型的尺寸很重要,用 deep and wide 的模型可以帮助提升性能。

 

SimCLR v2 的第 2 个发现是:

 

使用无标签数据集做 Pre-train 完以后,现在要拿着有标签的数据集 Fine-tune 了。之后再把这个 deep and wide 的模型 蒸馏成一个更小的网络。

 

所以,SimCLR v2 的方法,用8个英文单词概括一下就是:

 

Unsupervised Pre-train, Supervised Fine-tune,Distillation Using Unlabeled Data.

 

所以 SimCLR v2 论文里面给出了3个论点:

 

对于半监督学习来讲, 在标签量极少的情况下,模型越大,获益就越多 。这很不符合直觉,常识是标签这幺少了,模型变大会过拟合。

 

即使模型越大能够学到越 general 的 representations,但是这是在不涉及下游任务的task-agnostic 的情况下。 一旦确定了下游任务,就不再需要大模型了,可以蒸馏成一个小模型。

 

Projection head 很重要,更深的 Projection head 可以学习到更好的representation,在下游任务做 Fine-tune 之后也更好。

 

这3个论点就是 SimCLR v2 的贡献。那 SimCLR v2 取得的效果如何呢?我们对标一下 SimCLR:

 

性能:

 

SimCLR (4×)这个模型可以在 ImageNet 上面达到 76.5% 的 Top 1 Accuracy, 比当时的 SOTA 模型高了7个点 。如果把这个预训练模型用 1%的ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,SimCLR 就可以再达到 85.5% 的 Top 5 Accuracy,也就是再涨10个点。

 

注意这个 76.5% 是通过 Linear Evaluation 得到的, Linear Evaluation 具体是咋做的请参考上面的 FAQ1 。这个 85.5% 是通过 Fine-tune 得到的, Fine-tune 具体是咋做的请参考上面的 FAQ1 。

 

SimCLR v2这个模型可以在 ImageNet 上面达到 79.8% 的 Top 1 Accuracy, 比当时的 SOTA 模型 SimCLR 高了 4.3 个点 。如果把这个预训练模型用 1%或10% 的 ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,SimCLR v2 就可以再达到 76.6%或80.9% 的 Top 1 Accuracy。如果再蒸馏一下,迁移到更小的ResNet-50 上面,SimCLR v2 小模型就可以再达到 73.9%或77.5% 的 Top 1 Accuracy。注意 ResNet-50 有监督学习的Accuracy是76.6%。所以 SimCLR v2 在很多时候超越了 有监督学习 。

 

SimCLR v2 具体步骤:

 

SimCLR v2的具体步骤如下图24所示,这个图是论文里面的图,我自己画了个更细节的图如图25所示。SimCLR v2的具体步骤可以分为以下3步:

 

 

Unsupervised Pre-train:使用 无标签数据 以一种 Task-agnostic 的方式 预训练 Encoder,得到比较 general 的 Representations。

 

Supervised Fine-tune:使用 有标签数据 以一种 Task-specific 的方式 Fine-tune Encoder。

 

Distillation Using Unlabeled Data:使用 无标签数据 以一种 Task-specific 的方式 蒸馏 Encoder,得到更小的Encoder。

 

图24:SimCLR v2的具体步骤

图25:SimCLR v2的具体步骤

1) Unsupervised Pre-train

 

SimCLR v2 的这一步和 SimCLR 是一模一样的,如图25所示,具体的步骤已经在上文的1.1 – 1.4讲解了,这里再简要概述一下:

 

首先对每张图片先做数据增强,每张图片我们得到2个不同的数据增强结果,假设Batch size大小为2,则1个Batch 一共有 4 个 Image。假设现在有 1张 任意的图片 ,叫做Original Image,先对它做数据增强,得到2张增强以后的图片 。注意数据增强的方式还是以下3种:

 

随机裁剪之后再resize成原来的大小 (Random cropping followed by resize back to the original size)。

 

随机色彩失真 (Random color distortions)。

 

随机高斯模糊 (Random Gaussian Deblur)。

 

接下来把增强后的图片输入到Encoder里面,注意这2个Encoder是共享参数的,得到representation ,再把 继续通过 Projection head (在 SimCLR v2 里面是3层的MLP) 得到 representation ,这里的2个 Projection head 依旧是共享参数的,且其具体的结构表达式是:

 

接下来的目标就是最大化同一张图片得到的。怎幺最大化呢?使用Cosine Similarity把计算两张 Augmented Images的相似度转化成了计算两个Projected Representation 的相似度,定义为:

 

式中,是可调节的Temperature 参数。它能够scale 输入并扩展余弦相似度[-1, 1]这个范围。现在我们有了衡量相似度的办法,但是这还不够,要最终转化成一个能够优化的 Loss Function 才可以。SimCLR用了一种叫做 NT-Xent loss ( Normalized Temperature-Scaled Cross-Entropy Loss )的对比学习损失函数。希望上面的softmax的结果尽量大,所以损失函数取了softmax的负对数:

 

最后,计算每个Batch里面的所有Pair的损失之和取平均:

 

去优化这个损失函数 即可。

 

SimCLR v2 也是按照上面的步骤,有哪些不同呢?

 

 

Encoder 变长变大:SimCLR v2 用了更大的ResNet架构,把原来的 ResNet-50 (4×) 拓展成了 ResNet-152 (3×) 和 selective kernels (SK),记为 ResNet-152 (3×+SK),变成这样以后,把这个预训练模型用 1%的 ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,获得了29个点的提升。

 

Projection head 变深:使用了更深的 。原来的结构如图5所示是2个FC层+一个激活函数构成。现在的 是3个FC层,并且在Fine-tune的时候要从第1层开始。变成这样以后,把这个预训练模型用 1%的 ImageNet的标签 给 Fine-tune 一下,借助这一点点的有监督信息,获得了14个点的提升。

 

加入了MoCo 的内存机制:因为 SimCLR 本身就能通过数据增强得到很多的负样本,所以说这步只获得了1个点的提升。

 

 

2) Supervised Fine-tune

 

在 SimCLR 中,Projection head 在预训练完以后会被扔掉,不做Fine-tune,只保留Encoder加一个FC层去做Fine-tune。

 

而在 SimCLR v2 中,Projection head 在预训练完以后不会被完全扔掉,而是扔掉一半,保留一半做Fine-tune。注意如果只保留一层,那就和 SimCLR 加一个FC层的做法实质上一样了。

 

3) Distillation Using Unlabeled Data

 

作者把 Fine-tune 之后的网络作为了 Teacher,去蒸馏一个更小的 Student 网络。

 

损失函数是:

 

式中

 

, 是可调节的Temperature 参数。它能够scale 输入并扩展余弦相似度[-1, 1]这个范围。 是输入图片 网络输出和 的相似度,这样 就代表了输入图片 网络输出和 的相似的概率值。我们希望 Teacher 的这个概率 和 Student 的这个概率 越接近越好,如下图26所示。

图26:Distillation Using Unlabeled Data

上式 1 是只使用蒸馏而不用任何label的情况,当我们也有一些label的时候,也可以在1式的基础上添加一项有监督的损失:

2.2 SimCLR v2 实验设置:

以上这3步就是 SimCLR v2的具体步骤了,接下来就是大量的实验了。下面是一些基本训练的设置:

 

Unsupervised Pre-train:

 

模型训练阶段使用 128 Cloud TPUs。

 

Batch size:4096,Global Batch Normalization。

 

预训练 800 epochs。

 

学习率在前40个 epochs线性上升到最大值 ,之后使用cosine decay schedule。

 

weight decay rate: 。

 

Projection head:3层的MLP。

 

Supervised Fine-tune:

 

Fine-tuning 阶段,也就是只使用1%或10%的数据时 Projection head 保留1层MLP,扔掉2层。

 

Batch size:1024,Global Batch Normalization。

 

学习率 不变 。对于标准 ResNet 值为 。对于更大的ResNet 值为 。

 

Fine-tune 60 epochs (1% label),30 epochs (10% label)。

 

Distillation Using Unlabeled Data:

 

Distillation 阶段有2种设置:一种是 Teacher 和 Student 模型一样大,取名 self-distillation ,另一种是 Student 模型相比 Teacher 更小,取名 big-to-small distillation。

 

Batch size:4096,Global Batch Normalization。

 

蒸馏 400 epochs。

 

学习率在前40个 epochs线性上升到最大值,之后使用cosine decay schedule。

 

weight decay rate:。

 

我们再回顾下 SimCLR v2 论文里面给出的3个论点:

 

对于半监督学习来讲, 在标签量极少的情况下,模型越大,获益就越多 。这很不符合直觉,常识是标签这幺少了,模型变大会过拟合。

 

下图27是一个大的汇总,就是在不同大小的模型下,有监督学习的性能和 Self-Supervised Learning 在 Linear Evaluation 和 Fine-tuning 两种情况下的性能。

图27:在不同大小的模型下,有监督学习的性能和 Self-Supervised Learning 在 Linear Evaluation 和 Fine-tuning 两种情况下的性能

对于有监督学习,最大的模型和最小的模型的性能相差仅4个点 (80.5-76.6),但是对于 Self-Supervised Learning Linear Evaluation 来讲,差距达到了8个点 (79.8-71.7),对于 Self-Supervised Learning Fine-tuning (1% label) 来讲,差距达到了17个点 (74.9-57.9)。而且ResNet-152 (3×+SK) 的性能没有比 ResNet-152 (2×+SK) 的性能好多少,说明width带来的提升达到了瓶颈。

 

下图28是个更直观的展示模型大小,label数量对性能影响的曲线图。我们发现 在标签量极少的情况下,模型越大,获益就越多 。说明大的模型是更加label-efficient的,对于有监督和自监督学习都是这样。

图28:大的模型是更加label-efficient的

Projection head 很重要,更深的 Projection head 可以学习到更好的representation,在下游任务做 Fine-tune 之后也更好。

 

如下图29所示,(a) 图是2层,3层,4层的 Projection head 的Top 1 Acc,发现 Projection head 越深越好。(b) 图是在 Fine-tune 阶段使用不同数量的标签时,分别从第0层,第1层,第2层,第3层开始做 Fine-tune时的性能。从第0层开始就相当于是 SimCLR 的做法了。结果发现从 Projection head 的第1层开始做 Fine-tune 的效果是最佳的。

图29:更深的 Projection head 可以学习到更好的representation

另外还有一个发现是:当使用了很大的模型以后,更深的 Projection head 的作用变小了,因为更大的模型的 Projection head 也更宽了。

 

一旦确定了下游任务,就不再需要大模型了,可以蒸馏成一个小模型。

 

下图30是使用不同的损失的性能。

 

Label only指使用1%或10%的标签做监督学习,

 

Label+distillation loss (on labeled set)是指使用上式2作为损失函数,训练集只有有标签的数据。

 

Label+distillation loss (on labeled set)是指使用上式2作为损失函数,训练集既有有标签的数据也有无标签的数据。

 

Distillation loss指只使用上面1式作为损失函数,训练集既有有标签的数据也有无标签的数据。

 

可以发现只使用蒸馏损失,不使用任何标签就能获得不错的性能。

图30:使用不同的损失的性能

下图31的蓝色线代表只执行完上述前两步得到的Fine-tune之后的模型。

 

如果把它做 self-distillation ,就是把它作为 Teacher 并找一个和它结构一模一样的 Student 进行蒸馏,结果如橘红色线所示。

 

如果把 Student 蒸馏成更小的模型 big-to-small distillation,效果如绿线所示。

 

有监督学习如黑色线所示。

 

从结果可以发现蒸馏成更小的模型的效果是要由于 self-distillation 的,且在10%的标签数量下可以媲美有监督学习的性能。

图31:不同蒸馏方法与有监督学习的性能对比

最后作者对比了在ImageNet数据集上不同的 Self-Supervised Learning方法的性能对比,如下图32所示:

图32:ImageNet数据集上不同的 Self-Supervised Learning方法的性能对比

使用的 Teacher 模型都是 ResNet-152 (3×+SK) ,即 Fine-tune之后的模型是 ResNet-152 (3×+SK),如果第3步采用self-distillation的话,性能分别是76.6%和93.4%。如果第3步采用big-to-small distillation的话,性能分别是75.9%和93.0%。

 

下图33展示了 Linear Evaluation 和 Fine-tune 的性能对比。二者的区别在前文中已经数次强调,Linear Evaluation 指的是Encoder的参数固定住,在Encoder后面加一个FC层调节输出维度,且只训练最后的FC层参数,使用全部标签。Fine-tune 指的是在Encoder后面加一个FC层调节输出维度,训练Encoder的参数和FC层参数,使用1%或10%的标签。

 

可以看出二者之间总体上存在一种线性的相关关系。

 

如果是第1行,即从Projection head的第一层开始做 Fine-tune 或者 Linear Evaluation ,则相关关系较强。

 

如果是第2行,即直接去掉Projection head之后开始做 Fine-tune 或者 Linear Evaluation ,则相关关系较弱。

图33:Linear Evaluation 和 Fine-tune 的性能对比

总结

 

之前的使用自监督获得representations需要特定的算法。大牛上来就说之前的方法多数属于 生成方法或者判别方法。 告诉我们 contrastive learning 才是目前的宠儿。过去一年来,相继有CPC, CMC, MoCo 出来,想要解决的共同一个问题就是,如何提高softmax中negatives的数量。其中 CPC 用了patch based方法,CMC 用了一个memory buffer,MoCo 用了momentum update去keep一个negative sample queue。这篇文章告诉大家,只要机子够多,batch size够大,每个batch中除了positive以外的都当negatives就已经足够了。

 

本文亮点总结

 

1. Self-Supervised Learning 的目的一般是使用大量的无 label 的资料去Pre-train一个模型,这幺做的原因是无 label 的资料获取比较容易,且数量一般相当庞大,我们希望先用这些廉价的资料获得一个预训练的模型,接着根据下游任务的不同在不同的有 label 数据集上进行 Fine-tune 即可。

 

2. SimCLR v2 和 SimCLR 相比做了哪些改进?

 

答: 第 1 个发现是:在使用无标签数据集做 Pre-train 的这一步中,模型的尺寸很重要,用 deep and wide 的模型可以帮助提升性能。第 2 个发现是:使用无标签数据集做 Pre-train 完以后,现在要拿着有标签的数据集 Fine-tune 了。之后再把这个 deep and wide 的模型 蒸馏成一个更小的网络。

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注