跳转至

07-多模态学习

📌 本章定位理论基础与算法原理

本章侧重多模态学习的数学原理算法理论,包括: - 多模态表示学习与对齐的数学基础 - 融合策略的理论框架(早期/晚期/中间融合) - CLIP、BLIP等模型的核心算法原理与推导 - 对比学习(InfoNCE Loss)的数学理解

🔗 相关章节导航: | 侧重点 | 章节 | 说明 | |--------|------|------| | 理论原理 | 👉 本文档 | 数学推导、算法原理、融合策略理论 | | CV应用 | 计算机视觉/13-多模态学习 | VLM架构对比、实战项目、部署应用 | | 大模型 | LLM学习/多模态大模型 | GPT-4o/Gemini等多模态大模型 | | 具身智能 | 具身智能/VLA模型 | 视觉-语言-动作模型 |

学习时间: 约6-8小时 难度级别: ⭐⭐⭐⭐ 中高级 前置知识: CNN、Transformer、注意力机制、对比学习概念、PyTorch 学习目标: 理解多模态融合的核心方法,掌握CLIP、BLIP等视觉-语言模型的原理与使用


目录


1. 多模态学习概述

1.1 什么是多模态

模态 示例
文本 文章、标题、评论
图像 照片、医学影像、卫星图
音频 语音、音乐、环境声
视频 电影、监控、短视频
结构化 表格、知识图谱

多模态学习:融合来自多种模态的信息,使模型获得更全面的理解能力。

1.2 核心挑战

挑战 说明
表示 (Representation) 如何将不同模态映射到统一空间
对齐 (Alignment) 如何找到跨模态的对应关系
融合 (Fusion) 如何组合多模态信息
翻译 (Translation) 如何从一种模态生成另一种
协同学习 一种模态的知识如何帮助另一种

1.3 应用全景

Text Only
多模态应用
├── 理解类
│   ├── 图像描述生成 (Image Captioning)
│   ├── 视觉问答 (VQA)
│   └── 视频理解
├── 检索类
│   ├── 文搜图 / 图搜文
│   └── 跨模态检索
├── 生成类
│   ├── 文生图 (Text-to-Image)
│   ├── 文生视频
│   └── 语音合成
└── 交互类
    ├── 多模态对话
    └── 具身智能 (Embodied AI)

2. 多模态表示与对齐

多模态对齐机制

2.1 联合表示 vs 协同表示

类型 说明 方法
联合表示 将多模态特征投影到同一共享空间 CLIP, VSE++
协同表示 各模态保留独立表示,通过约束保持关联 CCA, 双塔模型

2.2 对齐方式

方式 粒度 示例
全局对齐 整张图 ↔ 整个句子 CLIP
局部对齐 图像区域 ↔ 词/短语 SCAN, ALBEF
时序对齐 视频帧 ↔ 字幕时间戳 视频描述生成

2.3 对比学习用于对齐

Text Only
图像编码器                       文本编码器
   ↓                              ↓
[v₁, v₂, ..., vₙ]     [t₁, t₂, ..., tₙ]
         ↘                  ↙
      对比损失: 配对的(vᵢ,tᵢ)拉近
              非配对的(vᵢ,tⱼ)推远

3. 多模态融合策略

多模态融合架构

3.1 三种融合时机

策略 位置 特点
早期融合 输入层拼接 简单,但难以处理异构输入
晚期融合 决策层融合 各模态独立编码,灵活
中间融合 中间层交互 平衡交互深度和模块化

3.2 注意力融合

方法 机制
Cross-Attention 一种模态作为Query,另一种作为Key/Value
Co-Attention 两种模态互相关注
Self-Attention 拼接所有模态后统一自注意力

3.3 Cross-Attention 实现

Python
import torch
import torch.nn as nn

class CrossAttention(nn.Module):  # 继承nn.Module定义神经网络层
    """跨模态注意力:query来自模态A, key/value来自模态B"""
    def __init__(self, dim, n_heads=8):  # __init__构造方法,创建对象时自动调用
        super().__init__()  # super()调用父类方法
        self.n_heads = n_heads
        self.head_dim = dim // n_heads

        self.q_proj = nn.Linear(dim, dim)
        self.k_proj = nn.Linear(dim, dim)
        self.v_proj = nn.Linear(dim, dim)
        self.out_proj = nn.Linear(dim, dim)
        self.scale = self.head_dim ** -0.5

    def forward(self, query, context):
        """
        query: [B, Lq, D] 模态A的序列
        context: [B, Lk, D] 模态B的序列
        """
        B, Lq, D = query.shape
        Lk = context.size(1)

        Q = self.q_proj(query).view(B, Lq, self.n_heads, self.head_dim).transpose(1, 2)  # 链式调用,连续执行多个方法
        K = self.k_proj(context).view(B, Lk, self.n_heads, self.head_dim).transpose(1, 2)
        V = self.v_proj(context).view(B, Lk, self.n_heads, self.head_dim).transpose(1, 2)

        attn = (Q @ K.transpose(-2, -1)) * self.scale
        attn = attn.softmax(dim=-1)

        out = (attn @ V).transpose(1, 2).reshape(B, Lq, D)  # reshape重塑张量形状
        return self.out_proj(out)

class MultimodalFusionBlock(nn.Module):
    """双向跨模态融合块"""
    def __init__(self, dim):
        super().__init__()
        self.text_to_image = CrossAttention(dim)
        self.image_to_text = CrossAttention(dim)
        self.norm1 = nn.LayerNorm(dim)
        self.norm2 = nn.LayerNorm(dim)
        self.ffn_image = nn.Sequential(
            nn.Linear(dim, dim * 4), nn.GELU(), nn.Linear(dim * 4, dim)
        )
        self.ffn_text = nn.Sequential(
            nn.Linear(dim, dim * 4), nn.GELU(), nn.Linear(dim * 4, dim)
        )

    def forward(self, image_feat, text_feat):
        # 图像关注文本
        image_feat = image_feat + self.text_to_image(image_feat, text_feat)
        image_feat = image_feat + self.ffn_image(self.norm1(image_feat))

        # 文本关注图像
        text_feat = text_feat + self.image_to_text(text_feat, image_feat)
        text_feat = text_feat + self.ffn_text(self.norm2(text_feat))

        return image_feat, text_feat

4. CLIP:对比语言-图像预训练

CLIP对比学习

4.1 架构

Text Only
              CLIP架构
  图像编码器(ViT/ResNet)    文本编码器(Transformer)
        ↓                        ↓
    图像嵌入 vᵢ              文本嵌入 tⱼ
        ↓                        ↓
       L2归一化                 L2归一化
              ↘            ↙
           相似度矩阵 S[i,j] = vᵢ·tⱼ / τ
         对比损失 (InfoNCE)

4.2 训练目标

给定 batch 中 \(N\) 对图文对,训练互信息最大化:

\[\mathcal{L} = -\frac{1}{2N}\sum_{i=1}^{N}\left[\log\frac{\exp(v_i \cdot t_i / \tau)}{\sum_j \exp(v_i \cdot t_j / \tau)} + \log\frac{\exp(t_i \cdot v_i / \tau)}{\sum_j \exp(t_i \cdot v_j / \tau)}\right]\]

4.3 CLIP的能力

能力 说明
零样本分类 无需训练样本,通过文本描述分类
跨模态检索 文搜图 / 图搜文
开放词汇目标检测 检测任意文本描述的物体
图文相似度 评估图文匹配程度

4.4 零样本分类原理

Text Only
输入图像 → 图像编码器 → 图像嵌入 v
候选标签: ["猫", "狗", "鸟"] → 文本模板: "一张{类别}的照片"
  → 文本编码器 → 文本嵌入 [t₁, t₂, t₃]

预测类别 = argmax(v · tᵢ)

5. BLIP/BLIP-2:视觉-语言预训练

5.1 BLIP的三个预训练任务

任务 目标 作用
ITC 图文对比学习 对齐表示
ITM 图文匹配判断 细粒度理解
LM 图像条件文本生成 生成能力

5.2 BLIP-2的Q-Former

引入Q-Former作为图像编码器与LLM之间的桥梁:

Text Only
冻结图像编码器 → Q-Former (可训练) → 冻结LLM
              可学习的查询向量
              通过交叉注意力
              提取图像信息

优势:将图像理解与语言生成解耦,大幅减少训练成本。

5.3 视觉-语言模型对比

模型 架构 预训练数据 关键创新
CLIP 双塔 4亿图文对 对比学习,零样本
BLIP 统一编解码 1.29亿 字幕生成+过滤去噪
BLIP-2 Q-Former + LLM 桥接冻结视觉与语言模型
LLaVA ViT + LLM 150K 视觉指令调优

6. 视觉问答与图文生成

6.1 视觉问答(VQA)

Text Only
输入: 图像 + 问题("图中有几只猫?")
处理: 图像编码 + 文本编码 → 融合 → 答案预测
输出: "2只"

6.2 图像描述生成(Image Captioning)

Python
class SimpleCaptioner(nn.Module):
    """简化的图像描述生成模型"""
    def __init__(self, visual_dim, vocab_size, embed_dim, hidden_dim):
        super().__init__()
        self.visual_proj = nn.Linear(visual_dim, embed_dim)
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.decoder = nn.TransformerDecoder(
            nn.TransformerDecoderLayer(embed_dim, nhead=8),
            num_layers=6
        )
        self.output_proj = nn.Linear(embed_dim, vocab_size)

    def forward(self, visual_features, token_ids):
        """
        visual_features: [B, N_patch, visual_dim] 图像特征
        token_ids: [B, L] 文本token序列
        """
        # 投影视觉特征
        memory = self.visual_proj(visual_features)  # [B, N_patch, embed_dim]
        memory = memory.transpose(0, 1)  # [N_patch, B, embed_dim]

        # 文本嵌入
        tgt = self.embedding(token_ids).transpose(0, 1)  # [L, B, embed_dim]

        # 因果掩码
        L = tgt.size(0)
        causal_mask = torch.triu(torch.ones(L, L), diagonal=1).bool()

        # 解码
        out = self.decoder(tgt, memory, tgt_mask=causal_mask)
        return self.output_proj(out.transpose(0, 1))  # [B, L, vocab_size]

7. 多模态大模型(LMM)

视觉语言模型架构

7.1 架构范式

Text Only
LMM通用架构:
    视觉编码器 (ViT, 通常冻结)
    投影层 / 适配器(桥接视觉与语言)
    大语言模型 (LLM, 可能冻结/LoRA微调)
    多模态输出(文本回答、推理等)

7.2 代表模型

模型 LLM基座 视觉编码器 特点
GPT-4V GPT-4 未公开 最强多模态理解
LLaVA Vicuna/Llama CLIP ViT 简洁高效,开源
Qwen-VL Qwen ViT 中文优秀
InternVL InternLM InternViT 动态分辨率

7.3 视觉指令调优

与纯文本指令调优类似,使用带图像的指令数据微调模型:

JSON
{
  "image": "photo_001.jpg",
  "conversations": [
    {"from": "human", "value": "<image>\n请描述这张图片的内容。"},
    {"from": "gpt", "value": "图片展示了一只金毛猎犬在草地上奔跑..."}
  ]
}

8. 实战:CLIP零样本分类与检索

Python
import torch
import torch.nn.functional as F
from PIL import Image

# 使用HuggingFace的transformers加载CLIP
# pip install transformers
from transformers import CLIPProcessor, CLIPModel

def clip_zero_shot_classification(image_path, candidate_labels):
    """CLIP零样本图像分类"""
    model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
    processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

    image = Image.open(image_path)
    texts = [f"a photo of a {label}" for label in candidate_labels]  # 列表推导式,简洁创建列表

    inputs = processor(text=texts, images=image, return_tensors="pt", padding=True)

    with torch.no_grad():  # 禁用梯度计算,节省内存
        outputs = model(**inputs)
        logits = outputs.logits_per_image  # [1, n_labels]
        probs = logits.softmax(dim=-1)

    for label, prob in zip(candidate_labels, probs[0]):  # zip按位置配对多个可迭代对象
        print(f"  {label}: {prob.item():.4f}")  # .item()将单元素张量转为Python数值

    predicted = candidate_labels[probs.argmax().item()]
    return predicted

def clip_image_text_retrieval(image_paths, query_text):
    """CLIP文搜图检索"""
    model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
    processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

    images = [Image.open(p) for p in image_paths]
    inputs = processor(text=[query_text], images=images,
                      return_tensors="pt", padding=True)

    with torch.no_grad():
        outputs = model(**inputs)
        similarities = outputs.logits_per_text[0]  # [n_images]

    ranked = similarities.argsort(descending=True)
    print(f"查询: '{query_text}'")
    for rank, idx in enumerate(ranked):  # enumerate同时获取索引和元素
        print(f"  #{rank+1}: {image_paths[idx]} (score: {similarities[idx]:.3f})")

    return ranked

# 使用示例
# clip_zero_shot_classification("cat.jpg", ["cat", "dog", "bird", "car"])
# clip_image_text_retrieval(["a.jpg", "b.jpg", "c.jpg"], "a dog playing frisbee")

9. 面试高频题

Q1: CLIP是如何实现零样本分类的?

:CLIP通过对比学习在4亿图文对上训练图像编码器和文本编码器,将图像和文本映射到同一嵌入空间。零样本分类时,将候选类别通过文本模板(如"a photo of a {class}")编码为文本嵌入,计算输入图像嵌入与各文本嵌入的余弦相似度,选择相似度最高的类别。无需任何标注训练数据即可分类。

Q2: 多模态融合有哪几种策略?各有什么优缺点?

:(1) 早期融合:输入层拼接,交互充分但难处理异构数据;(2) 晚期融合:各模态独立编码后在决策层合并,灵活但交互不够;(3) 中间融合:通过Cross-Attention等在中间层交互,平衡深度与模块化。实际中间融合最常用,如BLIP-2的Q-Former。

Q3: BLIP-2的Q-Former解决了什么问题?

:Q-Former通过一组可学习的查询向量,在冻结的图像编码器和冻结的LLM之间搭建桥梁。它解决了两个问题:(1) 避免端到端训练大型视觉和语言模型的巨大计算开销;(2) 通过交叉注意力从图像中提取与语言相关的信息,过滤无关视觉信息。

Q4: 当前多模态大模型的通用架构是什么?

:视觉编码器(通常是预训练的ViT/CLIP视觉部分) + 投影/适配层(如MLP或Q-Former) + 大语言模型。视觉编码器将图像转为patch特征序列,投影层将视觉特征映射到LLM的输入空间,LLM基于视觉信息进行推理和文本生成。

Q5: 跨模态对齐的挑战是什么?

:(1) 语义鸿沟——不同模态的底层表示差异巨大(像素 vs 词向量);(2) 粒度不匹配——图像是2D空间信号,文本是1D序列,且描述粒度不同;(3) 多对多关系——一张图可对应多种描述,一段文本可匹配多张图;(4) 数据质量——网络爬取的图文对噪声大、配对不精确。


10. 练习与自我检查

编程练习

  1. 基础:使用HuggingFace加载CLIP模型,实现零样本图像分类
  2. 进阶:实现一个跨模态检索系统(文搜图 + 图搜文)
  3. 挑战:基于BLIP-2实现图像描述生成,并尝试视觉问答

检查清单

  • 能说明多模态学习的五大挑战(表示、对齐、融合、翻译、协同学习)
  • 理解早期/中间/晚期融合的区别
  • 能实现Cross-Attention跨模态融合模块
  • 理解CLIP的对比学习训练方式和零样本分类原理
  • 了解BLIP-2的Q-Former架构和训练策略
  • 知道当前多模态大模型的通用架构范式
  • 能使用现有工具完成零样本分类或检索任务
  • 了解视觉指令调优的概念

多模态应用

扩展阅读: - Radford et al., 2021: Learning Transferable Visual Models From Natural Language Supervision (CLIP) - Li et al., 2023: BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders and LLMs - Liu et al., 2024: Visual Instruction Tuning (LLaVA) - Baltrušaitis et al., 2019: Multimodal Machine Learning: A Survey and Taxonomy