1 写在前面
CLIP由于其强大的泛化性能,简单的代码逻辑,受到了广泛的关注。目前CLIP也被应用到各个其他场景中,在这篇文章中,我们就来盘点一下,怎么把CLIP这个图文预训练的模型拓展到具有时序信息的视频任务中。
本文主要分为两个部分,第一个部分是介绍一下CLIP的原理和流程,第二部分为介绍,目前基于CLIP的视频模型!
2 回顾CLIP
CLIP的motivation主要有三点:
1)当前的CV数据集标注劳动密集,成本高昂;
2)当前的模型只能胜任一个任务,迁移到新任务上非常困难;
3)当前模型泛化能力较差,很难在新的数据上达到比较好的效果。
为了解决上面提出了问题,作者在文章中提出了两个解决方案:
1)互联网上较容易搜集到大量成对的文本和图像,对于任何一个图像文本对而言,文本其实可以认为是图像的标签。也就是说,互联网上天然就存在已经标注好的CV数据集,这解决了“motivation”中的第1个问题。
2)互联网上存在的这些已经标注好的CV数据集数量不仅大而且差异也大,当我们在这样的数据集上训练一个表达能力足够强的模型时,这个模型就能具备较强的泛化能力,较容易迁移到其他新任务上,这缓解了motivation”中的第2和第3个问题。
CLIP的模型结构非常简单,如上图所示:
收集到的文本-图像对,分别经过Text-Encoder和Image-Encoder,然后通过点积计算一个batch中文本和图像两两之间的相似度,得到一个batch size x batch size的相似度矩阵,对角线上的相似度值就是正样本的相似度值,因此在训练过程中优化目标就是让正样本的相似度值尽可能大。
在进行图片分类任务的推理时,模型首先需要将类别标签转换成和预训练时候一样的句子,因此这里用到了prompt操作,获得类别相应的句子。最后计算输入图片和每个类别对应句子的相似度,相似度最高的句子对应的类别的就是预测的类别。
CLIP的伪代码也非常简单:
1)首先文本和图像分别经过image和text的encoder,这个encoder可以resnet、也可以是transformer,得到文本和图像的embedding。
2)然后用线性层分别将图像和文本embedding映射到相同的语义空间中。
3)接着对图像和文本的embedding求相似度,得到bs x bs的相似度矩阵。
4)最后只需要在这个矩阵行方向和列方向分别计算cross entropy损失,得到最终的损失函数。
CLIP的目标是将文本和图片映射到相同的语义空间,因此只需要简单的点积,就可以计算文本和图片的相似度。从实验结果和最近的引用工作中可以看出,CLIP也确实达到了这一效果。目前也出现了一系列工作,将CLIP运用到视频任务之中。
3 基于CLIP的视频模型
论文:https://arxiv.org/pdf/2109.08472.pdf
代码:https://github.com/sallymmx/ActionCLIP
第一篇用CLIP做视频动作识别任务的文章。
视频动作识别的本质就是一个分类任务,判断一段视频属于预定义的哪个类别。所以这个任务的pipeline就如红框所示,首先用Video Encoder来提取视频的特征,并映射为logits向量,然后将其与one-hot形式的ground truth label进行对比,用cross entropy进行学习优化。
这样做的一个缺点是,将所有的类别都映射成了one-hot向量,完全没有考虑每个类别的文本语义信息。因此每次增加动作类别时都需要重新训练模型,很难进行简单的增量学习,也很难达到比较好的zero-shot和few-shot的性能。
因此,作者把这个分类当作一个检索任务,流程和CLIP做分类任务差不多。用Video Encoder和Text Encoder分别提取视频和文本的特征,然后将视频和文本特征进行点积,得到相似度矩阵。最后与ground truth矩阵进行对比,进行优化。
与CLIP不同的是,CLIP的预训练分类任务文本和图片是一一对应,而这里一个batch中,可能会出现多个label文本和同一个视频匹配,一个label文本也可能会和多个视频匹配,因此,作者没有用cross entropy损失函数来优化,而是采用了比较相似度矩阵和Ground Truth的相似度矩阵的KL散度进行优化。
ActionCLIP的OverView如上图所示。首先class label先进行Prompt操作得到一个完整的句子,然后将其输入到Text Encoder中,这部分就是CLIP的Text Encoder,得到文本表示。
对于视频分支,首先从视频中采样一些视频帧,然后对其进行patch embedding,并加入时间和空间的位置编码,接着将这些patch embedding输入到Video Encoder中,Video Encoder中包含两个部分。
一个是In-network Prompt,这个部分就是CLIP的Image Encoder,CLIP的Image Encoder用来得到每个帧的特征;然后将输出的特征输入到Post-network Prompt。Post-network Prompt用来将CLIP Encoder得到的图片特征聚合为视频表示。
简单的说,ActionCLIP做的工作就是将采用Textual Prompt和Visual Prompt,将CLIP的知识迁移到视频-动作识别
论文:https://arxiv.org/pdf/2110.06615.pdf
第二篇文章是用CLIP来做Video Captioning的。
这篇文章的做法也比较简单。将Captioning的过程分成了两步,第一步基于下游的video caption数据集,进行视频文本检索的预训练任务。预训练的流程和刚刚讲的ActionCLIP类似,就是一个视频-文本匹配的任务,这一步的作用是为了获得一个能将下游视频数据映射到文本共享语义空间的Video Encoder。
第二步就是用刚刚预训练得到的Video Encoder提取视频的特征,然后基于一个一层的Video Encoder和三层Transformer Decoder,来获得最终的caption。
论文:https://arxiv.org/pdf/2104.08860.pdf
第三篇是用CLIP来做视频-文本检索的文章
整个思路和上面提到的文章类似,用CLIP的Text Encoder提取文本特征,用CLIP的Visual Encoder提取帧的特征,然后将帧聚合之后的特征和文本特征求相似度,基于相似度采用和CLIP相同的方式进行优化。
对于patch embedding的方式,作者提出两种方式,一种是和CLIP的2D的embedding方式,embedding的时候不考虑时间维度上的信息;
第二种是3D的embedding,embedding的时候考虑了时间维度的信息,在一个立方体内的信息特征投影。实验表明,2D的embedding方式会比3D的方式会更好一些。
对于相似度计算的模块,作者采用了三种方式,当然也和前面的ActionCLIP提到的方式大同小异;第一种是直接将不同的帧的特征进行mean pooling得到视频特征,然后基于点积求相似度;
第二种是将得到的帧特征在过一个Transformer或者LSTM,然后将输出的特征求平均得到视频表示,然后基于点积求相似度,这种方式能够进行帧之间的交互;
第三种方式是将文本token和帧token都输入到一个Transformer中,进行帧与帧和帧与文本之间的交互,最后用2个线性层获得最终的相似度。
论文:https://arxiv.org/pdf/2112.04478.pdf
这篇文章用CLIP解决了三个问题,分别为动作识别、视频-文本检索和动作定位。
动作识别和视频-文本检索的流程和之前的ActionCLIP和CLIP4Clip基本都一样。对于动作定位,作者首先用了一个预训练的proposal detector来提取出可能包含动作的视频proposal,然后将这些proposal和prompt之后的动作类别进行相似度对比,相似度最高的proposal就是最终定位的结果。