4. 多模态特征融合模块设计

任务目标

设计并实现一个多模态特征融合模块,将视觉特征(来自图像编码器)与语言特征(来自文本编码器)进行有效融合。本案例采用门控融合方案,通过可学习的门控权重动态调节两种模态信息的贡献比例,并提供一个最小可运行的验证闭环。

核心实现

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

class GatedFusionModule(nn.Module):
    """门控多模态融合模块:动态加权视觉与语言特征"""
    def __init__(self, visual_dim: int, text_dim: int, fused_dim: int):
        super().__init__()
        # 将两种模态映射到同一维度
        self.visual_proj = nn.Linear(visual_dim, fused_dim)
        self.text_proj = nn.Linear(text_dim, fused_dim)
        # 门控生成器:基于拼接后的特征生成融合权重
        self.gate = nn.Sequential(
            nn.Linear(fused_dim * 2, fused_dim),
            nn.ReLU(),
            nn.Linear(fused_dim, fused_dim),
            nn.Sigmoid()
        )
        # 融合后的归一化层
        self.layer_norm = nn.LayerNorm(fused_dim)

    def forward(self, visual_feat: torch.Tensor, text_feat: torch.Tensor) -> torch.Tensor:
        """
        Args:
            visual_feat: [B, visual_dim] 视觉特征
            text_feat:   [B, text_dim]   语言特征
        Returns:
            fused_feat:  [B, fused_dim]  融合特征
        """
        # 投影到公共空间
        v = self.visual_proj(visual_feat)
        t = self.text_proj(text_feat)
        # 计算门控权重(逐元素)
        gate_input = torch.cat([v, t], dim=-1)
        g = self.gate(gate_input)  # [B, fused_dim],取值(0,1)
        # 门控加权融合
        fused = g * v + (1 - g) * t
        return self.layer_norm(fused)

# ---------- 最小验证闭环 ----------
def verify_fusion():
    torch.manual_seed(42)
    B, v_dim, t_dim, f_dim = 4, 512, 768, 256

    # 构造模拟输入(实际使用时来自视觉/文本编码器)
    visual_feat = torch.randn(B, v_dim)
    text_feat = torch.randn(B, t_dim)

    model = GatedFusionModule(v_dim, t_dim, f_dim)
    fused = model(visual_feat, text_feat)

    # 验证1:输出形状正确
    assert fused.shape == (B, f_dim), f"输出形状错误: {fused.shape}"
    # 验证2:输出经过LayerNorm,均值接近0、方差接近1
    mean = fused.mean(dim=-1).abs().mean().item()
    var = fused.var(dim=-1).mean().item()
    # 验证3:门控权重确实在(0,1)区间内
    with torch.no_grad():
        v = model.visual_proj(visual_feat)
        t = model.text_proj(text_feat)
        g = model.gate(torch.cat([v, t], dim=-1))
        g_min, g_max = g.min().item(), g.max().item()

    print(f"输出形状: {tuple(fused.shape)}")
    print(f"输出均值值的均值: {mean:.4f} (应接近0)")
    print(f"输出方差的均值: {var:.4f} (应接近1)")
    print(f"门控权重范围: [{g_min:.4f}, {g_max:.4f}] (应在0~1之间)")
    print("验证通过:形状正确、归一化有效、门控范围合法")

if __name__ == "__main__":
    verify_fusion()

运行与验证

环境依赖:Python 3.8+,PyTorch 1.9+(需支持nn.LayerNorm)。无需额外数据集或预训练模型。

运行方式:

python gated_fusion.py

通过条件:程序无异常退出,且输出以下结果:

  • 输出形状为 (4, 256),与fused_dim一致;
  • 输出均值值接近0(通常<0.05),方差接近1(通常0.8~1.2),证明LayerNorm生效;
  • 门控权重范围在(0,1)内,证明Sigmoid门控有效。

融合效果评估说明

本模块的融合效果可通过以下两种方式量化评估:

  • 门控分布分析:统计g的均值。若均值接近0.5,说明两种模态贡献均衡;若偏向0或1,说明模型倾向于信任某一模态。在真实任务中,可观察不同输入下门控值的变化来判断模态重要性。
  • 下游任务对比:将融合特征接入分类头,分别与仅视觉特征、仅语言特征、简单拼接三种基线对比准确率。若门控融合的准确率高于任一单模态基线,则证明融合有效。

本案例代码实现了门控融合核心逻辑,可直接替换为交叉注意力(将gate替换为nn.MultiheadAttention)进行扩展对比。

门控多模态融合模块数据流 视觉特征 [B, 512] 语言特征 [B, 768] Linear投影 → [B, 256] Linear投影 → [B, 256] 拼接 [B, 512] 门控生成器 Linear+ReLU+Linear +Sigmoid → g∈(0,1) 融合: g·v + (1-g)·t 逐元素加权 LayerNorm → 融合特征 [B, 256]