写点什么

EasyNLP 带你玩转 CLIP 图文检索

  • 2022 年 6 月 14 日
  • 本文字数:4597 字

    阅读完需:约 15 分钟

导读

随着自媒体的不断发展,多种模态数据例如图像、文本、语音、视频等不断增长,创造了互联网上丰富多彩的世界。为了准确建模用户的多模态内容,跨模态检索是跨模态理解的重要任务,采用一种模态的数据作为数据,检索另一种模态的数据。其中,图文检索是跨模态检索的一种主流任务,广泛应用于各种网络应用中,其难点在于跨模态的表示鸿沟(Representation Gap)。具体来说,文本和图像的数据处于不同的向量空间,无法直接去度量他们的相似性。OpenAI 提出了 CLIP(Contrastive Language-Image Pre-training)模型,在大规模图文数据集上进行了对比学习训练,在多个数据集上的准确度表明,CLIP 优于各种基于 ImageNet 的模型,也具有良好的零样本学习(Zero-shot Learning)能力。


EasyNLP 是阿里云机器学习 PAI 团队基于 PyTorch 开发的易用且丰富的中文 NLP 算法框架,支持常用的中文预训练模型和大模型落地技术,并且提供了从训练到部署的一站式 NLP 开发体验。EasyNLP 提供了简洁的接口供用户开发 NLP 模型,包括 NLP 应用 AppZoo 和预训练 ModelZoo,同时提供技术帮助用户高效的落地超大预训练模型到业务。由于跨模态理解需求的不断增加,EasyNLP 也将支持各种跨模态模型,特别是中文领域的跨模态模型,推向开源社区,希望能够服务更多的 NLP 和多模态算法开发者和研究者,也希望和社区一起推动 NLP /多模态技术的发展和模型落地。


本文简要介绍 CLIP 的技术解读,以及如何在 EasyNLP 框架中玩转 CLIP 模型。


CLIP 模型详解

CLIP 的模型结构相对比较简单,体现了“大道至简”的设计原则,其模型框架图如下图所示:


image


为了建立图像和文本的关联性,CLIP 首先分别构建了图像和文本的 Encoder,分别对图像和文本进行特征抽取。对于图像而言,CLIP 使用的 Backbone 可以是经典的 ResNet 系列模型,也可以是更先进的 Transfomer 类模型,例如 VIT 等;对于文本,CLIP 一般使用 BERT 类模型进行特征抽取,也包括 RoBERTa 等。在特征抽取之后,CLIP 分别对提取的向量进行 Normalization,从而可以直接进行内积相似度计算。在模型 Loss Function 层面,由于图像和文本向量都进行了 Normalization,我们直接使用相乘来计算余弦距离,使得同一图文对的结果趋近于 1,不同图文对的结果趋近于 0;并且使用对比学习损失 InfoNCE 进行损失计算。


当模型预训练结束后,我们可以直接使用 CLIP 进行图文的检索,因为 CLIP 已经将图文的表示映射到同一个向量空间。CLIP 的另一个优势在于可以进行 Zero-shot Classification。如下图所示,我们设计输入文本“A photo of a {object}.”,并且使用目标图像作为输出。如果文本“A photo of a dog.”于当前图像最匹配(余弦相似度最高),我们可以说明,当前图像的物体是“dog”。由此可见,预训练后的 CLIP 模型可以直接用于图像分类,而不需要额外的训练。


image


CLIP 模型的训练过程也可以直接参考原作者给出的伪代码实现:


image


EasyNLP 中 CLIP 模型的实现


在 EasyNLP 框架中,我们在模型层构建了 CLIP 模型的 Backbone,核心代码如下所示:

self.text_model = CLIPTextTransformer(text_config)self.vision_model = CLIPVisionTransformer(vision_config)
self.visual_projection = nn.Linear(self.vision_embed_dim, self.projection_dim, bias=False)self.text_projection = nn.Linear(self.text_embed_dim, self.projection_dim, bias=False
复制代码

其中,CLIPTextTransformer 和 CLIPVisionTransformer 分别是基于 BERT 和 VIT 的特征提取器。前向传播的过程也比较简洁:

vision_outputs = self.vision_model(...)text_outputs = self.text_model(...)
image_embeds = vision_outputs[1]image_embeds = self.visual_projection(image_embeds)image_embeds = image_embeds / image_embeds.norm(dim=-1, keepdim=True)
text_embeds = text_outputs[1]text_embeds = self.text_projection(text_embeds)text_embeds = text_embeds / text_embeds.norm(dim=-1, keepdim=True)
logit_scale = self.logit_scale.exp()logits_per_text = torch.matmul(text_embeds, image_embeds.t()) * logit_scaleloss = clip_loss(logits_per_text)
复制代码

此外,由于 CLIP 模型本身具备文本和图像的编码器,我们直接调用他们的前向推理函数就可以实现特征的提取。对于文本我们有:

text_outputs = self.text_model(...)pooled_output = text_outputs[1]text_features = self.text_projection(pooled_output)
复制代码

对图像的操作也与文本类似:

vision_outputs = self.vision_model(...)pooled_output = vision_outputs[1]image_features = self.visual_projection(pooled_output)
复制代码

此外,我们在多个公开数据集上验证了 EasyNLP 框架中 CLIP 模型在各种任务上的精度。以零样本学习为例,我们使用 EasyNLP 加载了开源的 openai/clip-vit-large-patch14 模型,对比了 Top-1 精度和 CLIP 官方论文的结果,如下所示:


我们的实验也说明,如果采用特定数据集的数据对 CLIP 进行进一步 Fine-tune,CLIP 能取得更好的效果。以 Fllickr30k 数据集为例,CLIP 模型在零样本学习和 Fine-tune 对比结果如下:


我们也在中文数据集上进行了预训练,并且评测了模型在 COCO-CN 和 Fllickr30k-CN 数据集上的效果。模型的设置与 WukongViT 对齐(详见参考文献),进行了复现,结果如下所示:


由上述结果可见,EasyNLP 框架训练的 CLIP 模型在下游任务的 Finetune 结果与 WukongViT 基本对齐。结果少量差异性的原因在于:1. MindSpore 与 PyTorch 的内部实现差异性(WukongViT 作者采用 MindSpore 实现)以及 2. 超参数和随机种子的选择。

为了方便用户的使用,EasyNLP 进一步提供了 AppZoo 层面的接口,使得用户可以在不实现任何代码的情况下调用 CLIP 模型,这一部分内容在下一节介绍。

CLIP 模型使用教程

以下简要介绍在 EasyNLP 框架使用 CLIP 模型。由于用户数据一般于 CLIP 预训练数据在分布上存在差距。我们提供 CLIP 模型的训练和向量提取功能


安装 EasyNLP

用户可以直接参考链接的说明安装 EasyNLP 算法框架。


数据准备

首先准备训练数据与验证数据,为 tsv 文件。这一文件包含以制表符\t 分隔的两列,第一列为文本,第二列为图片的 base64 编码。用于提取向量接入向量检索系统的输入文件为单列,仅包含文本或图片的 base64 编码。

为了方便开发者,我们也提供了转换图片到 base64 编码的示例代码:

import base64from io import BytesIOfrom PIL import Image
img = Image.open(fn)img_buffer = BytesIO()img.save(img_buffer, format=img.format)byte_data = img_buffer.getvalue()base64_str = base64.b64encode(byte_data) # bytes
复制代码

下列文件已经完成预处理,可用于测试:

# trainhttps://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_train_base64_part.tsv
# validhttps://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_valid_base64_part.tsv
# texthttps://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_test_base64_part_text.tsv
# imagehttps://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_test_base64_part_image.tsv
复制代码

模型训练和评测

我们采用以下命令对 CLIP 模型进行 fine-tune:

easynlp \  --mode train \  --worker_gpu=1 \  --tables=./MUGE_MR_train_base64_part.tsv,./MUGE_MR_valid_base64_part.tsv \  --input_schema=text:str:1,image:str:1 \  --first_sequence=text \  --second_sequence=image \  --checkpoint_dir=./clip_model/ \  --learning_rate=1e-4  \  --epoch_num=1  \  --random_seed=42 \  --logging_steps=100 \  --save_checkpoint_steps 200 \  --sequence_length=32 \  --micro_batch_size=32 \  --app_name=clip \  --save_all_checkpoints \  --user_defined_parameters='pretrain_model_name_or_path=clip_chinese_roberta_large_with_vit_large fix_vision=True mode=finetune'    
复制代码

训练完成后模型被保存到./clip_model/。训练结束后,我们可以对模型进行评估:

easynlp \  --mode evaluate \  --worker_gpu=1 \  --tables=./MUGE_MR_valid_base64_part.tsv \  --input_schema=text:str:1,image:str:1 \  --first_sequence=text \  --second_sequence=image \  --checkpoint_dir=./clip_model/ \  --random_seed=42 \  --logging_steps=100 \  --save_checkpoint_steps=500 \  --sequence_length=32 \  --micro_batch_size=32 \  --app_name=clip 
复制代码

文本或图片特征提取

模型训练完毕后,我们可以将其用于文本或图片的特征提取,示例如下:

  1. 提取文本特征

easynlp \      --mode predict \      --worker_gpu=1 \      --tables=./MUGE_MR_test_base64_part_text.tsv \      --input_schema=text:str:1 \      --output_schema=text_feat \      --outputs=./text_feat.tsv \      --first_sequence=text \      --checkpoint_dir=./clip_model/ \      --random_seed=42 \      --logging_steps=100 \      --save_checkpoint_steps=500 \      --sequence_length=32 \      --micro_batch_size=2 \      --app_name=clip 
复制代码
  1. 提取图片特征

easynlp \      --mode predict \      --worker_gpu=1 \      --tables=./MUGE_MR_test_base64_part_image.tsv \      --input_schema=image:str:1 \      --output_schema=image_feat \      --outputs=./image_feat.tsv \      --first_sequence=image \      --checkpoint_dir=./clip_model/ \      --random_seed=42 \      --logging_steps=100 \      --save_checkpoint_steps=500 \      --sequence_length=32 \      --micro_batch_size=2 \      --app_name=clip 
复制代码

提取出的特征存储在一个 tsv 文件中,每行对应输入中的一个文本或一个图片,维度之间采用制表符\t 分隔。


未来展望

在未来,我们计划在 EasyNLP 框架中公开以 PyTorch 实现的 CLIP 模型,覆盖各个常见中文领域,敬请期待。我们也将在 EasyNLP 框架中集成更多 SOTA 模型(特别是中文模型),来支持各种 NLP 和多模态任务。此外,阿里云机器学习 PAI 团队也在持续推进中文多模态模型的自研工作,欢迎用户持续关注我们,也欢迎加入我们的开源社区,共建中文 NLP 和多模态算法库!

Github 地址:https://github.com/alibaba/EasyNLP


Reference

  1. Alec Radford, Jong Wook Kim, Chris Hallacy, Aditya Ramesh, Gabriel Goh, Sandhini Agarwal Girish Sastry, Amanda Askell, Pamela Mishkin, Jack Clark, Gretchen Krueger. Ilya Sutskever. Learning transferable visual models from natural language supervision. arXiv

  2. Chengyu Wang, Minghui Qiu, Taolin Zhang, Tingting Liu, Lei Li, Jianing Wang, Ming Wang, Jun Huang, Wei Lin. EasyNLP: A Comprehensive and Easy-to-use Toolkit for Natural Language Processing. arXiv

  3. Jiaxi Gu, Xiaojun Meng, Guansong Lu, Lu Hou, Minzhe Niu, Xiaodan Liang, Lewei Yao, Runhui Huang, Wei Zhang, Xin Jiang, Chunjing Xu, Hang Xu. Wukong: 100 Million Large-scale Chinese Cross-modal Pre-training Dataset and A Foundation Framework. arXiv


阿里灵杰回顾

用户头像

还未添加个人签名 2020.10.15 加入

分享阿里云计算平台的大数据和AI方向的技术创新和趋势、实战案例、经验总结。

评论

发布
暂无评论
EasyNLP带你玩转CLIP图文检索_数据挖掘_阿里云大数据AI技术_InfoQ写作社区