毕业项目!综合运用全部知识,实现一个多模态分类系统——融合图像和文本信息进行分类。
输入:图像 + 文本描述
输出:分类标签
核心挑战:如何有效融合两种模态的信息
| 策略 | 做法 | 优缺点 |
|---|---|---|
| 早期融合 | 输入层拼接 | 简单,但可能丢失模态特性 |
| 晚期融合 | 各自编码后融合 | 保留模态特性,常用 |
| 注意力融合 | 跨模态注意力 | 效果最好,计算量最大 |
图像 → CNN/ViT → 图像特征 f_img
文本 → LSTM/Transformer → 文本特征 f_txt
融合:f = α·f_img + (1-α)·f_txt 或 Concat
分类:f → FC → 类别
import torch
import torch.nn as nn
# 多模态分类系统
print("=== 多模态分类系统 ===")
# 图像编码器(简化CNN)
class ImageEncoder(nn.Module):
def __init__(self, output_dim=128):
super().__init__()
self.cnn = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(64, 128, 3, padding=1), nn.ReLU(), nn.AdaptiveAvgPool2d(1),
)
self.fc = nn.Linear(128, output_dim)
def forward(self, x):
x = self.cnn(x).view(x.size(0), -1)
return self.fc(x)
# 文本编码器(LSTM)
class TextEncoder(nn.Module):
def __init__(self, vocab_size=5000, embed_dim=64, hidden_dim=128, output_dim=128):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, output_dim)
def forward(self, x):
x = self.embedding(x)
_, (h, _) = self.lstm(x)
h = torch.cat([h[-2], h[-1]], dim=1)
return self.fc(h)
# 多模态融合分类器
class MultimodalClassifier(nn.Module):
def __init__(self, img_dim=128, txt_dim=128, num_classes=10, fusion='concat'):
super().__init__()
self.img_encoder = ImageEncoder(img_dim)
self.txt_encoder = TextEncoder(output_dim=txt_dim)
self.fusion = fusion
if fusion == 'concat':
self.classifier = nn.Sequential(
nn.Linear(img_dim + txt_dim, 256), nn.ReLU(), nn.Dropout(0.3),
nn.Linear(256, num_classes)
)
elif fusion == 'attention':
self.attention = nn.Sequential(
nn.Linear(img_dim + txt_dim, 128), nn.ReLU(),
nn.Linear(128, 2), nn.Softmax(dim=1)
)
self.classifier = nn.Linear(max(img_dim, txt_dim), num_classes)
def forward(self, img, txt):
img_feat = self.img_encoder(img)
txt_feat = self.txt_encoder(txt)
if self.fusion == 'concat':
combined = torch.cat([img_feat, txt_feat], dim=1)
return self.classifier(combined)
elif self.fusion == 'attention':
combined = torch.cat([img_feat, txt_feat], dim=1)
weights = self.attention(combined) # B×2
weighted = weights[:, 0:1] * img_feat + weights[:, 1:2] * txt_feat
return self.classifier(weighted)
# 训练对比
torch.manual_seed(42)
num_classes = 10
img_data = torch.randn(200, 3, 32, 32)
txt_data = torch.randint(0, 5000, (200, 20))
labels = torch.randint(0, num_classes, (200,))
for fusion in ['concat', 'attention']:
model = MultimodalClassifier(fusion=fusion)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.CrossEntropyLoss()
for epoch in range(50):
optimizer.zero_grad()
out = model(img_data, txt_data)
loss = loss_fn(out, labels)
loss.backward()
optimizer.step()
with torch.no_grad():
acc = (model(img_data, txt_data).argmax(1) == labels).float().mean()
params = sum(p.numel() for p in model.parameters())
print(f"融合方式={fusion}: acc={acc:.2%}, params={params:,}")
# 单模态 vs 多模态对比
print("\n=== 单模态 vs 多模态 ===")
# 仅图像
img_model = ImageEncoder(10)
img_opt = torch.optim.Adam(img_model.parameters(), lr=0.001)
for _ in range(50):
img_opt.zero_grad()
loss = nn.CrossEntropyLoss()(img_model(img_data), labels)
loss.backward()
img_opt.step()
img_acc = (img_model(img_data).argmax(1) == labels).float().mean()
# 仅文本
txt_model = TextEncoder(output_dim=10)
txt_opt = torch.optim.Adam(txt_model.parameters(), lr=0.001)
for _ in range(50):
txt_opt.zero_grad()
loss = nn.CrossEntropyLoss()(txt_model(txt_data), labels)
loss.backward()
txt_opt.step()
txt_acc = (txt_model(txt_data).argmax(1) == labels).float().mean()
# 多模态
mm_model = MultimodalClassifier(fusion='concat')
mm_opt = torch.optim.Adam(mm_model.parameters(), lr=0.001)
for _ in range(50):
mm_opt.zero_grad()
loss = nn.CrossEntropyLoss()(mm_model(img_data, txt_data), labels)
loss.backward()
mm_opt.step()
mm_acc = (mm_model(img_data, txt_data).argmax(1) == labels).float().mean()
print(f"仅图像: {img_acc:.2%}")
print(f"仅文本: {txt_acc:.2%}")
print(f"多模态: {mm_acc:.2%}")
本课的核心知识点构成了实战项目学习的重要一环。让我们从更高维度审视这些知识之间的关系:
⚠️ 初学者常犯的错误:
💡 最佳实践:
深度学习是一个整体——每一课的知识都不是孤立的:
💡 继续深入的学习路径:
在真实多模态数据集(如Hateful Memes)上训练。
实现跨模态注意力机制替代简单拼接。
了解CLIP的对比学习范式,分析其零样本能力。
⚠️ 需要避免的典型错误:
💡 提升模型性能的系统方法:
理解本课内容需要将其置于更大的知识网络中。每个核心概念都不是孤立的,它们相互关联、相互支撑:
建立正确的直觉比记住公式更重要:
1. 维度直觉:高维空间中,数据分布与低维直觉截然不同(维度诅咒)
2. 信息瓶颈:神经网络逐层压缩信息,保留任务相关的、丢弃无关的
3. 流形假设:高维数据实际分布在低维流形上,学习即发现流形结构
4. 偏差-方差权衡:简单模型欠拟合(高偏差),复杂模型过拟合(高方差)
本课作为实战项目阶段的核心内容,与前后课程紧密关联:
| 关联课程 | 关联点 | 协同效应 |
|---|---|---|
| 前序课程 | 提供了本课的基础知识 | 循序渐进的理解 |
| 后续课程 | 本课内容是后续的基础 | 逐步构建能力 |
| 平行课程 | 同一阶段的互补知识 | 多角度深入理解 |
| 实战项目 | 综合运用所有知识 | 理论与实践结合 |
💡 准备面试时,确保能回答以下问题:
掌握本课内容后,可以通过以下方式继续深入:
恭喜!你已经从零掌握了深度学习的全貌!