玄同 765

大语言模型 (LLM) 开发工程师 | 中国传媒大学 · 数字媒体技术(智能交互与游戏设计)

CSDN · 个人主页 | GitHub · Follow


关于作者

  • 深耕领域:大语言模型开发 / RAG 知识库 / AI Agent 落地 / 模型微调
  • 技术栈:Python | RAG (LangChain / Dify + Milvus) | FastAPI + Docker
  • 工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案

「让 AI 交互更智能,让技术落地更高效」
欢迎技术探讨与项目合作,解锁大模型与智能交互的无限可能!


【论文解读】CLIP:图文对比学习开启多模态预训练新范式

论文:Learning Transferable Visual Models From Natural Language Supervision
作者:Alec Radford, Jong Wook Kim et al. (OpenAI)
发表会议:ICML 2021
论文链接:https://arxiv.org/abs/2103.00020

摘要:CLIP通过自然语言监督学习视觉模型,在4亿图文对上训练后,实现了零样本迁移到多种视觉任务。该方法将图像和文本映射到同一嵌入空间,通过对比学习对齐图文表征。CLIP在ImageNet上达到76.2%的零样本准确率,与有监督的ResNet-50相当,开启了多模态预训练的新范式。本文深入解析CLIP的架构设计、训练方法及其对多模态学习的影响。


一、从有监督预训练到自然语言监督

传统的视觉模型预训练依赖于人工标注的类别标签,如ImageNet的1000个类别。这种范式存在两个根本性限制。首先是标注成本,高质量的人工标注需要大量人力物力。其次是语义封闭,模型只能理解预定义的类别,无法泛化到新概念。

CLIP提出了一种革命性的思路:使用自然语言作为监督信号。互联网上存在海量的图文对数据——每张图片往往配有标题、描述或标签。这些数据虽然噪声较大,但规模庞大且语义丰富。

CLIP范式

自然语言
互联网图文对

对比学习

零样本迁移

传统范式

人工标注
ImageNet 1000类

有监督训练

固定类别分类

自然语言监督的优势在于:它不需要人工定义类别,可以直接从文本中学习语义;它天然支持零样本迁移,因为任何概念都可以用自然语言描述。


二、CLIP架构设计

CLIP的架构非常简洁,由两个编码器组成:图像编码器和文本编码器。图像编码器可以是ResNet或Vision Transformer,文本编码器是一个Transformer。

2.1 对比预训练

CLIP的训练目标是最大化匹配图文对的相似度,同时最小化不匹配图文对的相似度。对于一个包含N个图文对的批次,CLIP构建一个N×N的相似度矩阵,对角线是正样本对,其余是负样本对。

对比学习

嵌入空间

编码器

输入

图像批次
N张图片

文本批次
N段描述

图像编码器
ResNet/ViT

文本编码器
Transformer

图像嵌入 I₁...Iₙ

文本嵌入 T₁...Tₙ

相似度矩阵
N×N

对称交叉熵损失

import torch
import torch.nn as nn
import torch.nn.functional as F


class CLIP(nn.Module):
    """
    CLIP模型
    
    通过对比学习将图像和文本映射到同一嵌入空间。
    
    Attributes:
        image_encoder: 图像编码器
        text_encoder: 文本编码器
        projection_dim: 投影维度
        temperature: 温度参数
    """
    
    def __init__(
        self,
        image_encoder: nn.Module,
        text_encoder: nn.Module,
        image_dim: int = 512,
        text_dim: int = 512,
        projection_dim: int = 512,
        temperature: float = 0.07
    ):
        super().__init__()
        self.image_encoder = image_encoder
        self.text_encoder = text_encoder
        self.temperature = temperature
        
        self.image_projection = nn.Linear(image_dim, projection_dim, bias=False)
        self.text_projection = nn.Linear(text_dim, projection_dim, bias=False)
    
    def forward(
        self,
        images: torch.Tensor,
        texts: torch.Tensor
    ) -> tuple:
        """
        前向传播
        
        Args:
            images: 图像张量 [batch_size, C, H, W]
            texts: 文本token ids [batch_size, seq_len]
            
        Returns:
            (图像嵌入, 文本嵌入, 相似度矩阵)
        """
        image_features = self.image_encoder(images)
        text_features = self.text_encoder(texts)
        
        image_embeddings = self.image_projection(image_features)
        text_embeddings = self.text_projection(text_features)
        
        image_embeddings = F.normalize(image_embeddings, dim=1)
        text_embeddings = F.normalize(text_embeddings, dim=1)
        
        logits = (image_embeddings @ text_embeddings.t()) / self.temperature
        
        return image_embeddings, text_embeddings, logits
    
    def compute_loss(
        self,
        logits: torch.Tensor
    ) -> torch.Tensor:
        """
        计算对比损失
        
        Args:
            logits: 相似度矩阵 [batch_size, batch_size]
            
        Returns:
            对称交叉熵损失
        """
        batch_size = logits.size(0)
        labels = torch.arange(batch_size, device=logits.device)
        
        loss_i = F.cross_entropy(logits, labels)
        loss_t = F.cross_entropy(logits.t(), labels)
        
        return (loss_i + loss_t) / 2


class CLIPEncoder:
    """
    CLIP编码器封装
    
    提供零样本分类和图文检索功能。
    """
    
    def __init__(self, model: CLIP, tokenizer, preprocess):
        self.model = model
        self.tokenizer = tokenizer
        self.preprocess = preprocess
    
    @torch.no_grad()
    def encode_image(self, image) -> torch.Tensor:
        """编码图像"""
        image_tensor = self.preprocess(image).unsqueeze(0)
        image_features = self.model.image_encoder(image_tensor)
        image_embeddings = self.model.image_projection(image_features)
        return F.normalize(image_embeddings, dim=1)
    
    @torch.no_grad()
    def encode_text(self, text: str) -> torch.Tensor:
        """编码文本"""
        text_tokens = self.tokenizer([text])
        text_features = self.model.text_encoder(text_tokens)
        text_embeddings = self.model.text_projection(text_features)
        return F.normalize(text_embeddings, dim=1)
    
    def zero_shot_classify(
        self,
        image,
        class_names: list,
        prompt_template: str = "a photo of a {}"
    ) -> str:
        """
        零样本分类
        
        Args:
            image: 输入图像
            class_names: 类别名称列表
            prompt_template: 提示模板
            
        Returns:
            预测类别
        """
        image_embedding = self.encode_image(image)
        
        text_embeddings = []
        for class_name in class_names:
            text = prompt_template.format(class_name)
            text_embedding = self.encode_text(text)
            text_embeddings.append(text_embedding)
        
        text_embeddings = torch.cat(text_embeddings, dim=0)
        
        similarities = (image_embedding @ text_embeddings.t()).squeeze(0)
        predicted_idx = similarities.argmax().item()
        
        return class_names[predicted_idx]

2.2 零样本迁移

CLIP的核心能力是零样本迁移。给定一个新的分类任务,只需要将类别名称转换为文本描述,然后计算图像与每个类别描述的相似度,选择最相似的类别作为预测结果。

这种能力的来源是CLIP在大规模图文对上学习到的通用视觉-语言对齐。模型理解了"狗"、“猫”、"汽车"等概念的视觉特征,即使这些概念在训练时没有以分类标签的形式出现。


三、CLIP的性能与局限

CLIP在多个基准测试上展现了强大的零样本能力。在ImageNet上,CLIP的零样本准确率达到76.2%,与有监督的ResNet-50相当。在自然分布偏移数据集(如ImageNetV2、ImageNet-R)上,CLIP的鲁棒性明显优于有监督模型。

但CLIP也存在一些局限。首先是细粒度识别能力较弱,对于相似类别的区分(如不同品种的狗)不如有监督模型。其次是抽象概念理解有限,CLIP更擅长识别具体物体而非抽象概念。第三是计算成本较高,需要大规模数据和计算资源进行训练。


四、CLIP的影响与后续发展

CLIP的成功开启了多模态预训练的新时代。它证明了自然语言可以作为强大的监督信号,学习到可迁移的视觉表征。

后续工作如BLIP、Flamingo、GPT-4V等都借鉴了CLIP的图文对齐思想,并在更多模态和更复杂任务上取得了突破。CLIP的零样本能力也被广泛应用于图像生成(如DALL-E、Stable Diffusion)的文本引导。


五、总结

CLIP以其简洁的设计和强大的零样本能力,成为多模态学习的里程碑工作。它的核心贡献可以概括为三点:自然语言监督,利用海量图文对数据学习通用表征;对比学习框架,高效地学习图文对齐;零样本迁移,无需微调即可适应新任务。

CLIP的成功启示我们:自然语言是连接不同模态的桥梁。通过学习视觉与语言的对齐,我们可以构建更加通用和灵活的AI系统。


参考链接

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐