多模态论文一:CLIP模型主要内容讲解【原理+代码】

一、CLIP模型主要内容讲解

  CLIP(Contrastive Language-Image Pre-training)是OpenAI在2021年发布的一种用于图像和文本联合表示学习的模型。CLIP的核心思想是通过对比学习来预训练一个模型,使其能够理解图像和文本之间的关系。以下是CLIP的工作原理和步骤:

1. 数据集

  CLIP使用大规模的图像-文本对数据集进行预训练,例如从互联网上收集的4亿个图像-文本对。这些数据集包含了丰富的图像和对应的描述文本,使得模型能够学习到广泛的视觉概念和语言表达。

2. 模型架构

  CLIP由两个主要部分组成:

  • 图像编码器:用于将图像转换为特征向量。图像编码器可以是卷积神经网络(如ResNet)或Transformer模型(如ViT)。
  • 文本编码器:用于将文本转换为特征向量。文本编码器通常是一个Transformer模型。

3. 对比学习

  CLIP通过对比学习来训练模型。具体来说,对于一个批次中的每个图像-文本对,模型会计算图像和文本的特征向量,并使用对比损失函数来优化模型参数。对比损失函数的目标是使得匹配的图像-文本对的特征向量尽可能接近,而不匹配的图像-文本对的特征向量尽可能远离。

4. 损失函数

  CLIP使用的损失函数是对称的对比损失函数。具体来说,对于每个图像-文本对,模型会计算两个方向的损失:

  • 图像到文本的损失:计算图像特征向量和文本特征向量之间的相似度,并优化使得匹配的图像-文本对的相似度最大化。
  • 文本到图像的损失:计算文本特征向量和图像特征向量之间的相似度,并优化使得匹配的文本-图像对的相似度最大化。

5. 推理阶段

  在推理阶段,CLIP可以用于多种任务,例如:

  • 图像分类:给定一个图像,模型可以将其特征向量与预定义的文本类别(如“猫”、“狗”等)的特征向量进行比较,选择相似度最高的类别作为预测结果。
  • 文本到图像检索:给定一个文本描述,模型可以将其特征向量与图像库中的图像特征向量进行比较,检索出与文本描述最匹配的图像。

二、 动机

  在计算机视觉领域,迁移学习的一种常见做法是先在如ImageNet这样的大规模数据集上进行预训练,然后在具体的下游任务上进行微调。这种预训练通常基于有监督学习,需要大量的数据标注,因此成本较高。近年来,随着自监督学习方法的兴起,这一局面得到了改变。自监督学习方法,包括基于对比学习的方法如MoCo和SimCLR,以及基于图像掩码的方法如MAE和BeiT,它们的优势在于不再依赖于数据标注。然而,无论是传统的监督学习还是新兴的自监督学习,它们在迁移到下游任务时,仍然需要进行有监督的微调,无法实现真正的零样本学习(Zero-shot)。
  对于有监督模型而言,由于它们在预训练数据集上使用了固定类别数的分类器,因此在新的数据集上需要重新定义分类器并进行训练。而对于自监督模型,虽然代理任务有助于表征学习,但在迁移到其他数据集时,同样需要添加新的分类器进行有监督训练。
  相比之下,在自然语言处理(NLP)领域,基于自回归或语言掩码的预训练方法已经相当成熟,并且预训练模型能够轻松实现零样本迁移到下游任务,例如OpenAI的GPT-3。这种差异一方面源于文本和图像这两种完全不同的模态,另一方面则是因为NLP模型可以利用互联网上丰富多样的文本数据。
  这就引出了一个问题:我们能否利用互联网上的大量文本来预训练视觉模型,从而实现类似NLP领域的零样本迁移能力?这一问题的探讨,不仅涉及跨模态学习的深入研究,也为视觉模型的预训练和迁移学习开辟了新的可能性。
  所以openai基于前面的工作,从文本信息获取监督信息的方式,做了以下两件事:1.足够大的数据集(爬取清洗了4亿对图像文本对),2.多模态(图像跟文本),统一用transformer架构,使用对比学习训练。
在这里插入图片描述
  蓝色是回归预测,也就是根据图像去预测对应的文本标签,这个任务难度是巨大的,而且一个图像可以有多个文本表述范式;橘黄色是在特诊空间进行预测,根据图像特征去预测文本特征。绿色是图像-文本匹对的损失,这个是最快收敛的,任务相对简单。同时这样的设置可以更好地将 图像与文本的语义信息绑定到一起。

三、模型

在这里插入图片描述

1. 训练过程

伪代码
在这里插入图片描述

2. 模型细节

  这里的image encoder可以是ResNet也可以是ViT;text encoder可以是CBOW也可以是Transformer。
图像、文本分别经过encoder之后得到的特征,会进行线性投影以及L2归一化操作。
  L2 归一化(L2 normalization)是一种常见的数据预处理技术,用于将数据向量的长度缩放到单位范数(即 L2 范数为 1)。对于一个向量 v = [ v 1 , v 2 , … , v n ] \mathbf{v} = [v_1, v_2, \ldots, v_n] v=[v1,v2,,vn],其 L2 范数定义为:
∥ v ∥ 2 = v 1 2 + v 2 2 + ⋯ + v n 2 \|\mathbf{v}\|_2 = \sqrt{v_1^2 + v_2^2 + \cdots + v_n^2} v2=v12+v22++vn2
L2 归一化后的向量 v ′ \mathbf{v}' v 计算如下:
v ′ = v ∥ v ∥ 2 = [ v 1 ∥ v ∥ 2 , v 2 ∥ v ∥ 2 , … , v n ∥ v ∥ 2 ] \mathbf{v}' = \frac{\mathbf{v}}{\|\mathbf{v}\|_2} = \left[ \frac{v_1}{\|\mathbf{v}\|_2}, \frac{v_2}{\|\mathbf{v}\|_2}, \ldots, \frac{v_n}{\|\mathbf{v}\|_2} \right] v=v2v=[v2v1,v2v2,,v2vn]
这样处理后,向量 v ′ \mathbf{v}' v 的 L2 范数为 1:
∥ v ′ ∥ 2 = ( v 1 ∥ v ∥ 2 ) 2 + ( v 2 ∥ v ∥ 2 ) 2 + ⋯ + ( v n ∥ v ∥ 2 ) 2 = 1 \|\mathbf{v}'\|_2 = \sqrt{\left( \frac{v_1}{\|\mathbf{v}\|_2} \right)^2 + \left( \frac{v_2}{\|\mathbf{v}\|_2} \right)^2 + \cdots + \left( \frac{v_n}{\|\mathbf{v}\|_2} \right)^2} = 1 v2=(v2v1)2+(v2v2)2++(v2vn)2 =1

3. 损失函数细节

对称性的损失设计

  在CLIP的训练中,损失设计包括两个方向:从图像到文本和从文本到图像。这两个方向的交叉熵损失计算如下:

  1. 计算相似度矩阵

    • 假设有 n n n 对图像-文本对,图像编码表示为 I \mathbf{I} I,文本编码表示为 T \mathbf{T} T
    • 相似度矩阵 S \mathbf{S} S 的元素 s i j s_{ij} sij 表示第 i i i 个图像和第 j j j个文本之间的相似度。通常,使用余弦相似度计算:
      S i j = cos ⁡ ( I i , T j ) = I i ⋅ T j ∥ I i ∥ ∥ T j ∥ S_{ij} = \cos(\mathbf{I}_i, \mathbf{T}_j) = \frac{\mathbf{I}_i \cdot \mathbf{T}_j}{\|\mathbf{I}_i\| \|\mathbf{T}_j\|} Sij=cos(Ii,Tj)=Ii∥∥TjIiTj
  2. 定义标签

    • 标签向量为 t e x t l a b e l s = np.arange ( n ) text{labels} = \text{np.arange}(n) textlabels=np.arange(n),表示对角线上的元素是匹配的图像-文本对。
  3. 交叉熵损失

    • 图像到文本的交叉熵损失 loss i \text{loss}_i lossi
      loss i = cross_entropy_loss ( S , labels , axis = 0 ) \text{loss}_i = \text{cross\_entropy\_loss}(\mathbf{S}, \text{labels}, \text{axis}=0) lossi=cross_entropy_loss(S,labels,axis=0)
      这里, axis = 0 \text{axis}=0 axis=0 表示对每一行(即每个图像对应的所有文本)计算损失。

    • 文本到图像的交叉熵损失 ( \text{loss}_t )
      loss t = cross_entropy_loss ( S , labels , axis = 1 ) \text{loss}_t = \text{cross\_entropy\_loss}(\mathbf{S}, \text{labels}, \text{axis}=1) losst=cross_entropy_loss(S,labels,axis=1)
      这里, axis = 1 \text{axis}=1 axis=1 表示对每一列(即每个文本对应的所有图像)计算损失。

  4. 综合损失

    • 最终的损失是这两个方向的交叉熵损失的平均值:
      loss = loss i + loss t 2 \text{loss} = \frac{\text{loss}_i + \text{loss}_t}{2} loss=2lossi+losst

其中,

  • 图像到文本的交叉熵损失

    • 对于每个图像 I i \mathbf{I}_i Ii,计算它与所有文本的相似度 S i , : \mathbf{S}_{i,:} Si,:
    • 使用交叉熵损失,将这些相似度与标签(正确匹配的文本索引)进行比较,确保每个图像找到正确的文本描述。
  • 文本到图像的交叉熵损失

    • 对于每个文本 T i \mathbf{T}_i Ti,计算它与所有图像的相似度 S : , i \mathbf{S}_{:,i} S:,i
    • 使用交叉熵损失,将这些相似度与标签(正确匹配的图像索引)进行比较,确保每个文本找到正确的图像。

  这种设计的对称性确保了模型在训练过程中同时优化图像到文本和文本到图像的匹配效果。通过这种方式,模型不仅能够从图像中找到相应的文本描述,还能够从文本中找到对应的图像。这种双向优化使得CLIP模型在实际应用中表现更加鲁棒和准确。

4. zero shot tranfer

  这个算是CLIP最大的创新点,之前的有监督学习或者说无监督学习,主要的目的是获取一个强大的特征抽取器(backbone),但是在应用到下游任务的时候,基本上还是要收集下游数据进行微调的。CLIP做到这样的两点:1.无需微调;2.文本信息引导模型迁移

5. promot engineering and ensembing

在做zero-shot推理的时候要用到。

- 标签单词文本多义性polysemy,所以只给一个标签单词并不合适。
- 训练的时候文本信息是句子,而预测的时候标签是单词,这有影响,存在distribution gap的问题,可以做promot template来巧妙解决,如设定好模板:"A photo of a {label}",同时可以再细化,比如已经知道数据集是宠物分类,那就可以使用"A photo of a {label},a type of pet."
- ensembing就是使用多个提示模板,然后综合多个模板的结果。

在CLIP模型中,文本和图像都会被提取为特征嵌入(feature embeddings)。这些特征嵌入的形状(shape)取决于模型的架构和输入数据的处理方式。

6. 图像特征、文本特征嵌入的形状

对于图像特征嵌入,通常的形状是 (batch_size, embedding_dim),其中:

  • batch_size 是输入图像的批次大小。
  • embedding_dim 是图像特征嵌入的维度,这个维度取决于模型的架构。例如,对于CLIP的ViT-B/32模型,embedding_dim 通常是512。

对于文本特征嵌入,形状通常也是 (batch_size, embedding_dim),其中:

  • batch_size 是输入文本的批次大小。
  • embedding_dim 是文本特征嵌入的维度,这个维度同样取决于模型的架构。对于CLIP的ViT-B/32模型,embedding_dim 通常也是512。

代码

这里使用PyTorch和Hugging Face的Transformers库来加载和使用CLIP模型。这个代码展示了如何使用CLIP模型进行图像分类和文本到图像的检索。

  1. 安装必要的库:
pip install torch transformers pillow
  1. 加载CLIP模型并进行图像分类:
import torch
from PIL import Image
from transformers import CLIPProcessor, CLIPModel# 加载预训练的CLIP模型和处理器
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")# 定义图像路径和文本类别
image_path = "path_to_your_image.jpg"
text_labels = ["a photo of a cat", "a photo of a dog", "a photo of a bird"]# 加载图像
image = Image.open(image_path)# 处理图像和文本
inputs = processor(text=text_labels, images=image, return_tensors="pt", padding=True)# 计算特征向量并进行分类
with torch.no_grad():outputs = model(**inputs)logits_per_image = outputs.logits_per_image  # 图像到文本的相似度得分
probs = logits_per_image.softmax(dim=1)  # 概率分布# 输出分类结果
for i, label in enumerate(text_labels):print(f"{label}: {probs[0][i].item():.2%}")# 输出最高概率的类别
predicted_class = text_labels[probs[0].argmax()]
print(f"Predicted class: {predicted_class}")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

49、PHP 实现堆排序

题目: PHP 实现堆排序 描述: 堆排序基本思想:堆排序(HeapSort)是一树形选择排序。在排序过程中,将R[l…n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择…

代码打包大师班:掌握PyInstaller,发布无阻

安装PyInstaller:打包之旅的起点 首先,确保你的Python开发环境已就绪,然后借助pip这位全能助手,安装PyInstaller。打开命令行,键入以下指令,耐心等待安装完成: pip install pyinstallerPyInst…

C++20之设计模式(22):策略模式

策略模式 策略模式动态策略静态策略总结 策略模式 假设您决定使用包含多个字符串的数组或向量,并将它们作为列表输出 ["just", "like", "this"]。 如果考虑不同的输出格式,您可能知道需要获取每个元素,并将其…

数据传输安全--SSL VPN

目录 IPSEC在Client to LAN场景下比较吃力的表现 SSL VPV SSL VPN优势 SSL协议 SSL所在层次 SSL工作原理 SSL握手协议、SSL密码变化协议、SSL警告协议三个协议作用 工作过程 1、进行TCP三次握手、建立网络连接会话 2、客户端先发送Client HELLO包,下图是包…

Oracle对比两表数据的不一致

MINUS 基本语法如下 [SQL 语句 1] MINUS [SQL 语句 2];举个例子: select 1 from dual minus select 2 from dual--运行结果 1-------------------------------- select 2 from dual minus select 1 from dual--运行结果 2所以,如果想找所有不一致的&a…

MySQL with recursive 用法浅析

目录 写在前面 语句功能 with recursive 语法讲解 细节补充 “union all”语句 添加递归终止条件 写在前面 介绍“with recursive”用法的文章不少,但我都觉得讲的不够通俗,所以干脆自己写一篇。话不多说,进入正题。 语句功能 with r…

【数据结构】二叉树链式结构——感受递归的暴力美学

前言: 在上篇文章【数据结构】二叉树——顺序结构——堆及其实现中,实现了二叉树的顺序结构,使用堆来实现了二叉树这样一个数据结构;现在就来实现而二叉树的链式结构。 一、链式结构 链式结构,使用链表来表示一颗二叉树…

python kivy制作GUI界面---ScreenManager多界面跳转

目录 介绍项目演示代码示例介绍 由于开了新的项目,需要制作适合一次开发多端多环境运行的桌面端项目,找了大部分的项目,目前主推的框架主要有:kivy、wxpython、electron等可以快速开发的,由于项目预测体积不会太大,所以暂时不考虑PyQt啦,多了不少,少了不唠,直接进入主…

FPGA:有限状态机

从以下6个实验理解状态机的概念 开发板频率为 50 M H z 50MHz 50MHz,一个时钟周期是 20 n s 20ns 20ns。 1、实验一:LED灯亮0.25秒、灭0.75秒的状态循环 通过之前的分析,我们实现频闪灯时,是让led灯在0.5秒实现一次翻转,而这里…

【我的OpenGL学习进阶之旅】讲一讲GL_TEXTURE_2D和GL_TEXTURE_EXTERNAL_OES的区别

在使用OpenGL ES进行图形图像开发时,我们常使用GL_TEXTURE_2D纹理类型,它提供了对标准2D图像的处理能力。这种纹理类型适用于大多数场景,可以用于展示静态贴图、渲染2D图形和进行图像处理等操作。 另外,有时我们需要从Camera或外部视频源读取数据帧并进行处理。这时,我们…

经典文献阅读之--World Models for Autonomous Driving(自动驾驶的世界模型:综述)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务,并且需要GPU资源,可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU,按时收费每卡2.6元,月卡只需要1.7元每小时&…

linux-conda环境安装配置教程

以下是一个超详细的Linux-Conda环境安装教程,该教程涵盖了从系统准备到环境配置的全过程: 一、准备工作 确认系统环境: 确认操作系统的版本和系统架构。可以通过以下命令获取这些信息:uname -a lsb_release -a这些命令将显示你的内核版本、系统名称、硬件架构和操作系统版…

html+css 实现水波纹按钮

前言:哈喽,大家好,今天给大家分享htmlcss 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 文…

python重命名图片

在Python中,获取图片路径并根据当前时间戳重命名图片通常涉及以下几个步骤: 确定图片的原始路径:首先,你需要知道图片的当前位置。获取当前时间戳:然后,使用Python的datetime模块来获取当前时间的时间戳。…

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储!实际业务开发中,token是一个表示着用户登录状态的重要信息,它有自己的生命周期。因此,这个参数值必须实例化存储在本地中。不能跟着pinia。因为pinia是基于内存设计的模…

事务和函数索引

事务 事务的定义 事务(Transaction),就是将一组SQL语句放在同一批次内去执行,如果一个SQL语句出错,则该批次内 的所有SQL都将被取消执行。 事务的特点 一个事务中如果有一个数据库操作失败,那么整个 事务…

若依框架 : 生成代码

6.生成代码 6.1.配置生成设置 ruoyi-generator -> src -> main -> resources -> generator.yml 由于 案例中 表都有 前缀 为 tta_ , 这里设置去掉 6.2.生成代码 6.2.1.导入数据库中的表 6.2.2.修改设置 6.2.2.1.设置生成信息 点击 编辑 -> 生成信息 特别…

SqlServer 使用T-SQL单纯的复制表数据

今天用Sql Server Manager Studio 先复制一个库建立一个新库出来,各种报错,也不知道是为什么,连备份再还原都不行,算了,自己写个SQL 脚本来执行算了...... 坏处是视图,存储过程和函数都没有复制过来 -- 设…

m4a怎么转mp3?m4a转mp3的几种方法教程

m4a怎么转mp3?M4A音频格式的全称MPEG-4 Audio,是一种音频压缩格式。这种格式以其卓越的音质和相对较小的文件大小而广受欢迎,尤其是在音乐存储、在线流媒体以及音频编辑等领域。M4A格式被广泛应用于苹果公司的产品中,如iPhone、iP…

开放式耳机会成为未来的主流吗?开放式耳机推荐指南

开放式耳机是否会成为未来的主流,是一个值得探讨的问题。 从目前的市场趋势和技术发展来看,有一些因素支持开放式耳机可能成为主流。 一方面,人们对于健康和舒适的关注度不断提高。长时间佩戴传统耳机可能导致耳部不适,而开放式…