EasyNLP带你玩转CLIP图文检索

本文涉及的产品
交互式建模 PAI-DSW,每月250计算时 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
模型训练 PAI-DLC,100CU*H 3个月
简介: 本文简要介绍CLIP的技术解读,以及如何在EasyNLP框架中玩转CLIP模型。

作者:熊兮、章捷、岑鸣、临在

导读

随着自媒体的不断发展,多种模态数据例如图像、文本、语音、视频等不断增长,创造了互联网上丰富多彩的世界。为了准确建模用户的多模态内容,跨模态检索是跨模态理解的重要任务,采用一种模态的数据作为数据,检索另一种模态的数据。其中,图文检索是跨模态检索的一种主流任务,广泛应用于各种网络应用中,其难点在于跨模态的表示鸿沟(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的模型结构相对比较简单,体现了“大道至简”的设计原则,其模型框架图如下图所示:


为了建立图像和文本的关联性,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模型可以直接用于图像分类,而不需要额外的训练。


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

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_scale
loss = 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官方论文的结果,如下所示:


数据集

Top-1 Accuracy (复现结果)

CLIP 论文汇报结果

Food101

90.9

92.9

CIFAR100

78.6

77.9

EuroSAT

60.1

59.9

Oxford Pets

93.0

93.5

Fllickr30k-TR

85.3

88.0

Fllickr30k-IR

65.0

68.7


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


img2txt

(r1/r5/r10)

img2txt mean

txt2img

(r1/r5/r10)

txt2img mean

CLIP Fine-tune

91.0/99.0/99.7

95.57

76.38/94.06/97.28

89.24

CLIP Zero-shot

85.3/97.40/99.2

94.0

65.02/87.2/92.0

81.41


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


数据集

模型

img2txt mean

txt2img mean

COCO-CN

WukongViT

96.4

89.8

CLIP

96.1

88.4

Fllickr30k-CN

WukongViT

85.9

87.8

CLIP

86.0

86.1


由上述结果可见,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 base64
from io import BytesIO
from 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

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

# train
https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_train_base64_part.tsv
# valid
https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_valid_base64_part.tsv
# text
https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/CLIP/MUGE_MR_test_base64_part_text.tsv
# image
https://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


阿里灵杰回顾

相关实践学习
使用PAI+LLaMA Factory微调Qwen2-VL模型,搭建文旅领域知识问答机器人
使用PAI和LLaMA Factory框架,基于全参方法微调 Qwen2-VL模型,使其能够进行文旅领域知识问答,同时通过人工测试验证了微调的效果。
机器学习概览及常见算法
机器学习(Machine Learning, ML)是人工智能的核心,专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能,它是使计算机具有智能的根本途径,其应用遍及人工智能的各个领域。 本课程将带你入门机器学习,掌握机器学习的概念和常用的算法。
相关文章
|
算法
雪花算法id生成器
雪花算法id生成器
708 0
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的鲜花商城管理系统
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
271 2
|
JavaScript Java API
基于代理和单例模式的 electron 多窗口管理方案
基于代理和单例模式的 electron 多窗口管理方案
947 0
|
11月前
|
数据可视化 IDE 数据挖掘
Python助您洞察先机:2024年A股市场数据抓取与分析实战
【10月更文挑战第1天】随着2024年中国股市的强劲表现,投资者们对于如何高效获取并分析相关金融数据的需求日益增长。本文旨在介绍如何利用Python这一强大的编程语言来抓取最新的A股交易数据,并通过数据分析技术为个人投资决策提供支持。
1388 2
|
11月前
|
TensorFlow 算法框架/工具 iOS开发
手把手教你-MAC虚拟环境搭建TensorFlow开发环境
手把手教你-MAC虚拟环境搭建TensorFlow开发环境
255 0
|
机器学习/深度学习 数据采集 人工智能
计算机视觉技术综述
计算机视觉技术综述
|
机器学习/深度学习 数据采集 SQL
【Python机器学习专栏】使用Pandas处理机器学习数据集
【4月更文挑战第30天】本文介绍了如何使用Python的Pandas库处理机器学习数据集,涵盖数据读取、概览、清洗、转换、切分和保存等步骤。通过Pandas,可以从CSV等格式加载数据,进行缺失值、异常值处理,数据类型转换,如归一化、类别编码,并实现训练集与测试集的划分。此外,还展示了如何保存处理后的数据,强调了Pandas在数据预处理中的重要性。
602 0
|
Kubernetes 应用服务中间件 数据安全/隐私保护
yaml文件格式详解 及 k8s实战演示
yaml文件格式详解 及 k8s实战演示
|
人工智能 算法 数据处理
【OpenVI-图搜系列—多模态检索实战篇】基于表征大模型的多模态检索系统
信息检索产品几乎是人们生活中必不可少的工具,经常用的有文本搜文本、图片搜图片等应用。以上任务均为单模态的检索。而多模态检索则处理涵盖原有的单模态检索任务以外,也包含跨模态检索任务,即文搜图、文搜视频等任务。要实现这一任务,则需要底层的表征模型具备图文对齐的能力,换句话说,要实现多模态检索,表征模型应实现将不同模态信息的特征映射到同一个域内,从而实现不同模态之间的相互检索。CLIP的多模态技术出现以来,给多模态检索领域带来了新的技术变革,使得实现基于通用表征大模型的大规模多模态检索系统成为可能。
2068 0
【OpenVI-图搜系列—多模态检索实战篇】基于表征大模型的多模态检索系统
OpenCV-基于自定义色条实现灰度图上色
OpenCV-基于自定义色条实现灰度图上色
264 0