📚 学习教程

【高级应用】Day18:多模态应用开发–图文音视频AI应用实战

· 2026-04-12 · 6 阅读

【高级应用】Day18:多模态应用开发–图文音视频AI应用实战

👤 龙主编 📅 2026-04-12 👁️ 6 阅读 💬 0 评论

章节导语

GPT-4V能看图,Gemini能看视频,Whisper能听音频——多模态AI正在重新定义AI的能力边界。不再是”能说会道”,而是”能说会道能看能听能理解”。

但多模态不是简单地把几个模型拼在一起。不同模态的数据格式不同、特征空间不同、语义粒度不同,如何让它们”对齐”是核心难题。

本文系统讲解多模态AI的核心概念和技术方案:从早期融合、晚期融合到层次化融合,从CLIP到Flamingo,从图文对到大一统模型。帮你建立完整的多模态知识体系。

一、前置说明

1.1 学习路径

阶段 内容
前置 Transformer架构(Day5)、注意力机制
本篇 多模态学习与融合

1.2 读者需要的基础

  • 深度学习基础:理解CNN、RNN、Transformer
  • PyTorch基础:能实现简单的模型
  • 向量空间概念:理解嵌入、相似度计算

1.3 学习目标

学完本文,你将能够:

  • 理解多模态学习的核心挑战
  • 掌握不同融合策略的优缺点
  • 理解CLIP等经典模型的设计思想
  • 实现简单的多模态应用
  • 根据场景选择合适的多模态方案
多模态
图1:多模态学习概述

二、多模态学习的核心挑战

2.1 什么是多模态

模态(Modality)是指信息的表现形式。常见模态包括:

  • 文本:文字、词语、句子
  • 图像:图片、图表、截图
  • 音频:语音、音乐、环境声
  • 视频:图像序列+音频+时间维度
  • 触觉:压力、温度、纹理

多模态学习是指让AI系统能够同时理解和处理多种模态的信息。人类天然是多模态的——我们看书、听音乐、看电影,各种感官信息综合形成完整的体验。AI也在朝这个方向发展。

2.2 核心挑战

多模态学习的核心挑战有三个:

挑战一:异构性

不同模态的数据格式完全不同。文本是离散的符号序列,图像是连续的像素矩阵,音频是连续的波形信号。它们有不同的统计特性、不同的维度、不同的表示方式。如何找到一种统一的表示方式,是第一个难题。

挑战二:关联性

“一只猫在沙发上睡觉”——这句话和一张猫的图片描述的是同一个场景。但文本中的”猫”和图像中的猫像素模式完全不同。如何学习它们之间的对应关系?

挑战三:缺失性

实际场景中,往往不是所有模态都同时可用。比如配图文章,可能只有文字没有图片;比如视频通话,可能只有音频没有视频。如何处理模态缺失?

2.3 发展历程

多模态学习的发展经历了几个阶段:

早期(2014-2016):Image Captioning时代。用CNN提取图像特征,用RNN生成描述文字。代表作Show and Tell。

中期(2017-2019):视觉问答(VQA)时代。LSTM+Attention,让模型能回答关于图片的问题。

近期(2020-2022):CLIP时代。对比学习让图文特征空间统一,多模态任务迎来突破。

当前(2023-):大一统时代。GPT-4V、Gemini等多模态模型,一个模型处理所有模态。

融合策略
图2:多模态融合策略对比

三、融合策略

3.1 早期融合

早期融合(Early Fusion)是在模型最底层把不同模态的特征拼接在一起,然后统一处理。

比如图像和文本:先把图像用CNN提取特征,把文本用Embedding层提取特征,然后拼接成一个向量,输入到后面的网络。

优点:模型可以从一开始就学习模态间的交互,能捕捉到非常细粒度的跨模态关联。

缺点:不同模态的特征往往在不同尺度上发挥作用,早期融合可能过早融合,丢失信息。另外,当模态缺失时处理困难。

3.2 晚期融合

晚期融合(Late Fusion)是在模型高层分别处理各模态,最后在决策层融合。

比如图像分类和文本分类任务:图像分支输出图像的分类概率,文本分支输出文本的分类概率,最后把两个概率向量加权平均或拼接。

优点:各模态可以独立处理,互不干扰;模态缺失时容易处理,缺失哪个分支就只用其他分支。

缺点:无法学习到底层的跨模态关联,融合效果有限。

3.3 层次化融合

层次化融合(Hierarchical Fusion)是早期和晚期的折中,在多个层次上逐步融合。

比如先在底层做图像的局部特征融合,再在中层融合文本和图像的语义特征,最后在高层做最终决策。

优点:兼顾底层关联和高层的语义抽象,更灵活。

缺点:实现复杂度高,需要仔细设计融合层次和方式。

3.4 融合策略对比

策略 融合层次 优点 缺点
早期融合 底层 细粒度关联 模态缺失难处理
晚期融合 高层 模态独立处理 关联性弱
层次化融合 多层 灵活兼顾 复杂度高

四、对比学习与CLIP

4.1 对比学习的思想

CLIP(Contrastive Language-Image Pre-training)是多模态学习的里程碑。它基于一个简单的思想:让匹配的图文在特征空间中距离近,让不匹配的图文距离远。

训练数据是大量的图文对——互联网上抓取的图片和对应的描述文字。对比学习的目标是:

正样本对:同一张图片和它的描述文字,在特征空间中应该接近。

负样本对:不同图片和描述文字,在特征空间中应该远离。

通过大量的对比学习,模型学会了图文之间的对应关系——”狗”的图片和”a dog”的文字会被映射到特征空间的相近位置。

4.2 CLIP的架构

CLIP由两个编码器组成:

图像编码器:用Vision Transformer(ViT)把图像转换成特征向量。

文本编码器:用Transformer把文本转换成特征向量。

两个编码器输出的向量维度相同,比如都是768维。然后计算文本和图像向量的余弦相似度,匹配的对应该有高相似度。

4.3 CLIP的应用

CLIP训练好后,可以用于多种任务:

零样本图像分类:把类别名称作为文本输入,计算与图像的相似度。这实现了无需训练数据就能分类的能力。

图文检索:根据文本搜索相关图片,或根据图片搜索相关文本。

图像生成引导:Stable Diffusion等图像生成模型用CLIP作为条件引导,控制生成内容。

五、多模态实战

5.1 图像特征提取

import torch
import torch.nn as nn
from PIL import Image
from torchvision import transforms

class ImageEncoder(nn.Module):
    """图像编码器
    
    使用预训练的Vision Transformer提取图像特征
    """
    
    def __init__(self, embed_dim=768):
        super().__init__()
        # 加载预训练的ViT模型
        from torchvision.models import vision_transformer
        self.vit = vision_transformer.vit_b_16(weights='IMAGENET1K_V1')
        
        # 去掉分类头,只保留特征提取部分
        self.vit.heads = nn.Identity()
        
        # 投影层
        self.projection = nn.Linear(768, embed_dim)
        
        self.transform = transforms.Compose([
            transforms.Resize(224),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], 
                             std=[0.229, 0.224, 0.225])
        ])
    
    def forward(self, images):
        """提取图像特征
        
        Args:
            images: PIL Image或Tensor [B, 3, 224, 224]
        
        Returns:
            features: 图像特征向量 [B, embed_dim]
        """
        if isinstance(images, PIL.Image.Image):
            images = self.transform(images).unsqueeze(0)
        
        with torch.no_grad():
            features = self.vit(images)
        
        features = self.projection(features)
        return features
    
    def extract(self, image_path):
        """从文件路径提取特征"""
        image = Image.open(image_path).convert('RGB')
        return self.forward(image)

# 使用
if __name__ == "__main__":
    encoder = ImageEncoder()
    
    # 提取单张图片特征
    features = encoder.extract("example.jpg")
    print(f"图像特征维度: {features.shape}")

六、文本特征提取

6.1 文本编码器

import torch
import torch.nn as nn
from transformers import BertTokenizer, BertModel

class TextEncoder(nn.Module):
    """文本编码器
    
    使用预训练的BERT模型提取文本特征
    """
    
    def __init__(self, embed_dim=768):
        super().__init__()
        self.bert = BertModel.from_pretrained('bert-base-uncased')
        self.projection = nn.Linear(768, embed_dim)
        
        # 冻结BERT参数(如果数据少)
        # for param in self.bert.parameters():
        #     param.requires_grad = False
    
    def forward(self, input_ids, attention_mask):
        """提取文本特征
        
        Args:
            input_ids: 文本token IDs [B, seq_len]
            attention_mask: 注意力掩码 [B, seq_len]
        
        Returns:
            features: 文本特征向量 [B, embed_dim]
        """
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
        
        # 使用[CLS] token的特征作为句子表示
        pooled_output = outputs.pooler_output
        
        features = self.projection(pooled_output)
        return features

class TextProcessor:
    """文本处理工具"""
    
    def __init__(self, max_length=128):
        self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
        self.max_length = max_length
    
    def encode(self, texts):
        """批量编码文本
        
        Args:
            texts: 文本列表
        
        Returns:
            input_ids, attention_mask
        """
        encoding = self.tokenizer(
            texts,
            padding=True,
            truncation=True,
            max_length=self.max_length,
            return_tensors='pt'
        )
        return encoding['input_ids'], encoding['attention_mask']

# 使用
if __name__ == "__main__":
    text_encoder = TextEncoder()
    text_processor = TextProcessor()
    
    # 编码文本
    texts = ["a cat sitting on a couch", "a dog running in the park"]
    input_ids, attention_mask = text_processor.encode(texts)
    
    # 提取特征
    features = text_encoder(input_ids, attention_mask)
    print(f"文本特征维度: {features.shape}")

七、多模态匹配实战

7.1 图文匹配模型

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

class MultimodalMatcher(nn.Module):
    """图文匹配模型
    
    基于CLIP思想,计算图文相似度
    """
    
    def __init__(self, embed_dim=512, temperature=0.07):
        super().__init__()
        self.image_encoder = ImageEncoder(embed_dim)
        self.text_encoder = TextEncoder(embed_dim)
        self.temperature = nn.Parameter(torch.ones([]) * temperature)
    
    def forward(self, images, input_ids, attention_mask):
        """计算图文相似度
        
        Args:
            images: 图像张量 [B, 3, 224, 224]
            input_ids: 文本token IDs [B, seq_len]
            attention_mask: 注意力掩码 [B, seq_len]
        
        Returns:
            logits: 图文相似度 [B, B]
        """
        # 提取特征
        image_features = self.image_encoder(images)
        text_features = self.text_encoder(input_ids, attention_mask)
        
        # L2归一化
        image_features = F.normalize(image_features, p=2, dim=1)
        text_features = F.normalize(text_features, p=2, dim=1)
        
        # 计算余弦相似度
        logits_per_image = torch.matmul(image_features, text_features.t()) * torch.exp(self.temperature)
        logits_per_text = logits_per_image.t()
        
        return logits_per_image, logits_per_text
    
    def compute_loss(self, logits_per_image, logits_per_text, batch_size):
        """计算对比学习损失
        
        使用交叉熵损失,对角线是正样本
        """
        labels = torch.arange(batch_size, device=logits_per_image.device)
        
        loss_image = F.cross_entropy(logits_per_image, labels)
        loss_text = F.cross_entropy(logits_per_text, labels)
        
        loss = (loss_image + loss_text) / 2
        return loss

# 训练示例
def train_step(matcher, images, input_ids, attention_mask, optimizer):
    matcher.train()
    optimizer.zero_grad()
    
    batch_size = images.size(0)
    logits_per_image, logits_per_text = matcher(images, input_ids, attention_mask)
    loss = matcher.compute_loss(logits_per_image, logits_per_text, batch_size)
    
    loss.backward()
    optimizer.step()
    
    return loss.item()

八、多模态应用

8.1 零样本图像分类

CLIP最厉害的应用之一是零样本分类。不需要训练数据,只需要把类别名称列出来。

比如ImageNet有1000个类别。推理时,把这1000个类别名称都encode成文本特征,然后和图像特征计算相似度,取相似度最高的作为预测类别。

def zero_shot_classify(matcher, image, class_names):
    """零样本图像分类
    
    Args:
        matcher: 训练好的多模态模型
        image: PIL Image
        class_names: 类别名称列表
    
    Returns:
        预测的类别名称
    """
    # 编码图像
    image_features = matcher.image_encoder.extract(image)
    image_features = F.normalize(image_features, p=2, dim=1)
    
    # 编码文本(类别名称)
    class_texts = [f"a photo of a {name}" for name in class_names]
    input_ids, attention_mask = text_processor.encode(class_texts)
    class_features = matcher.text_encoder(input_ids, attention_mask)
    class_features = F.normalize(class_features, p=2, dim=1)
    
    # 计算相似度
    similarities = torch.matmul(image_features, class_features.t())
    pred_idx = similarities.argmax(dim=1).item()
    
    return class_names[pred_idx]

# 使用
class_names = ["cat", "dog", "bird", "car", "airplane"]
prediction = zero_shot_classify(matcher, test_image, class_names)
print(f"预测类别: {prediction}")

8.2 图像描述生成

多模态模型也可以用于图像描述。但和CLIP不同,这需要解码器生成文本。

常用方案是结合预训练的图像编码器(如ViT)和语言模型(如GPT),在图文数据上做微调。

九、最佳实践

9.1 数据处理

数据平衡:不同模态的数据量要平衡。如果图文对数据中文本描述普遍较短,可能导致文本编码器学得不够好。

数据清洗:图文对数据中有很多噪声,比如图片和文本不相关、文本描述过于简单等。需要仔细清洗。

数据增强:图像可以做随机裁剪、翻转、颜色抖动等增强。但文本增强要小心,改变文本语义会影响学习。

9.2 模型训练

温度参数:对比学习中的温度参数很重要。温度太高,相似度区分度低;温度太低,模型可能崩溃。要通过验证集调优。

批次大小:对比学习需要较大的批次来提供足够的负样本。批次太小,负样本质量差,学习效果不好。

学习率:对比学习的学习率通常比分类任务高。建议使用warmup和余弦衰减。

9.3 评估指标

任务 指标
图文检索 Recall@K、mAP
图像分类 Top-1/5准确率
图像描述 BLEU、CIDEr、SPICE

十、总结

多模态是AI发展的必然方向。真实世界的信息本身就是多模态的——文本、图像、声音交织在一起。AI要真正理解世界,必须具备多模态能力。

融合策略是核心问题。早期融合、晚期融合、层次化融合各有优劣,要根据任务特点选择。

对比学习是多模态预训练的主流方法。CLIP开创了图文对比学习的范式,后续很多工作都基于此改进。

多模态应用场景丰富。从零样本分类到图像描述,从视频理解到多模态对话,多模态AI正在渗透到各个领域。

延伸阅读

  • CLIP论文:Learning Transferable Visual Models From Natural Language Supervision
  • BLIP:Bootstrapping Language-Image Pre-training
  • GPT-4V:多模态GPT的进展

课后练习

基础题:用CLIP实现一个图文检索系统,给定文本返回最相关的图片。

进阶题:实现一个零样本图像分类器,在5个类别上达到90%以上的准确率。

挑战题:用PyTorch从零实现一个简化版CLIP,包括图像编码器、文本编码器和对比学习损失。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

微信公众号二维码

扫码关注公众号

QQ
QQ二维码

扫码添加QQ