视觉问答 VQA:让模型看懂图像并回答问题
视觉问答 VQA:让模型看懂图像并回答问题
什么是视觉问答
视觉问答(Visual Question Answering,VQA)是一项结合计算机视觉与自然语言处理的跨模态任务。给定一张图像和一个关于该图像内容的自然语言问题,模型需要理解视觉信息与文本语义,并生成正确的答案。答案形式可以是单词、短语、二值判断甚至数字。与传统的图像描述不同,VQA 要求模型不仅仅“看见”图像中的对象,更要进行关系推理、属性识别、计数、逻辑判断等深层语义理解。
VQA 的典型场景:
- 输入:一张图(例如:一只猫坐在窗台上)
- 问题:“窗台是什么颜色的?”
- 输出:答案(例如:“白色”)
VQA 的核心工作原理
整体流程抽象
VQA 系统通常包含以下步骤:
- 图像编码:使用 CNN 或 ViT 等模型提取图像特征。
- 问题编码:使用 LSTM/GRU 或 Transformer 将自然语言问题转换为向量表示。
- 多模态融合:将图像特征与问题向量进行交互融合,生成联合表示。
- 答案推理:基于联合表示预测答案,可以看作分类(从预定义候选池中选择)或生成任务。
关键组件详解
图像特征提取
- 卷积神经网络(CNN):早期VQA模型多采用在 ImageNet 上预训练的 VGGNet、ResNet 等,提取整图或区域特征。
- 区域特征与自底向上注意力:使用 Faster R-CNN 等目标检测器,提取图像中显著区域(对象)的特征,每个区域对应一个特征向量。这种“自下而上”的注意力机制极大提升性能。
- Vision Transformer (ViT):直接将图像切分为 patch,输入 Transformer 编码器,获得更具全局感受野的特征。现代VQA多采用 ViT 或其变体,如 CLIP 的视觉编码器部分。
问题特征提取
- 循环神经网络:早期采用 LSTM 或 GRU,将问题 token 序列编码为单一向量。
- Transformer 编码器:对问题词元序列进行自注意力计算,获得上下文相关的表示,效果更佳。
- 预训练语言模型:可直接使用 BERT、RoBERTa 等提取问题嵌入,或与视觉模型联合预训练。
多模态融合
这是 VQA 的难点,要求两种异质信息深度交互。常见融合方法有:
- 简单拼接/逐元素运算:将图像特征和问题特征 concat 后送入全连接层,或做元素乘/加。
- 双线性池化:如 MLB(多模态低秩双线性池化)、MFB(多模态分解双线性池化)、Mutan,通过张量分解压缩交互参数,在特征层级进行丰富的二阶交互。
- 注意力机制:堆叠注意力(SAN)、平行共同注意力(BAN、MCAN),让模型同时关注图像中与问题相关的区域,以及问题中与视觉相关的单词。
- Transformer 跨模态融合:利用交叉注意力(Cross-Attention),让视觉特征作为 Query,问题特征作为 Key/Value,或反之,实现细粒度对齐。ViLBERT、LXMERT、UNITER 等模型均基于此架构。
答案预测与训练目标
- 分类范式:将 VQA 视作从固定答案词表中多选分类。通常取训练集中出现频率较高的答案(如 top 3000)作为候选。使用 softmax 交叉熵损失。
- 生成范式:使用解码器逐词生成答案,适合自由形式答案和计数问题。但需要序列监督,早期应用较少,当前借助视觉语言预训练模型已大量使用。
- VQA v2 特殊评估:由于答案可能存在同义不同形,使用软准确率(Soft Accuracy),即预测答案与多个基准答案的模糊匹配(例如 “very tall” 和 “tall” 可视为部分匹配)。
主流模型架构演进
早期经典模型
- VIS+LSTM:基线模型,将 CNN 特征与 LSTM 编码的问题拼接,MLP 分类。
- SAN (Stacked Attention Networks):多次查询注意力,逐步聚焦图像相关区域。
- Faster R-CNN + Bottom-Up Top-Down:使用目标检测的视觉特征取代整图全局特征,加上面向问题的 top-down 注意力,成为经典强基线。
联合嵌入与双线性改进
- Mutan / MLB / MFB:通过张量分解压缩实现高效双线性交互,在 VQA v1 上表现优秀。
预训练时代的跨模态 Transformer
- ViLBERT / LXMERT / VisualBERT:双流或单流架构,利用大规模图文对进行预训练(掩码语言建模、图文匹配等),然后在 VQA 任务上微调。
- UNITER / OSCAR:引入物体标签作为桥梁,将图像区域表示为区域特征+标签 embedding,进一步对齐语义。
- CLIP + 适配:利用 CLIP 的联合图文嵌入,配合冻结或微调进行 VQA。
近期大模型与通用视觉语言模型
- BLIP-2 / InstructBLIP:使用 Q-Former 连接冻结的视觉编码器和语言模型,通过指令微调显著提升零样本 VQA 能力。
- LLaVA / MiniGPT-4:将视觉编码器(如 ViT)与开源大语言模型对齐,训练简单线性投影层或 MLP,即可进行多模态对话问答。
- PaLI / GIT / Flamingo:Google、DeepMind 等公司推出的超大规模视觉语言模型,在 VQA 基准上屡创新高。
核心数据集与评测基准
VQA v1 与 v2
- VQA v1:基于 MS-COCO 和抽象场景,包含开放式和多项选择题。存在严重的数据偏置(如问题类型与答案存在强相关性),模型可能不看过图像就猜中答案。
- VQA v2:针对 v1 的偏置问题进行了平衡,每张图片配对两个相似但答案不同的问题,强迫模型利用视觉信息。是当前使用最广泛的基准之一。
其他代表性数据集
- Visual Genome QA:来自 Visual Genome 数据集的自然问题,覆盖丰富的对象、属性和关系。
- CLEVR:合成图像数据集,专门测试模型的计数、比较、空间关系推理能力,去除现实世界的噪声,检验推理极限。
- GQA:基于真实图像但使用场景图自动生成问题,提供细致的组合推理测试,并带有结构化注解。
- OK-VQA:需要外部知识才能回答的问题(如“这幅画是什么风格的?”),考验知识的综合运用。
- TextVQA:问题需要场景文本的理解(如“这个招牌上写的什么字?”),要求模型具备 OCR 与文本推理能力。
- VizWiz:由盲人拍摄的真实需求图像,问题实用且可能包含图像质量问题,更具现实挑战。
评估指标
- 简单准确率:预测答案是否与人工标注答案之一完全匹配。
- VQA 标准准确率:对开放型答案采用软精确匹配,公式为
Acc = min( 1, #预测答案与人工答案匹配人数/3),确保多个等价回答能被认可。 - 一致性、鲁棒性等其他专项指标:如 VQA-Repair 的防偏置指标。
VQA 的应用场景
- 辅助视觉障碍人士:手机拍照并询问周围环境、钞票面额、产品日期等。
- 智能交互与机器人:机器人理解环境并接受人类自然语言查询,如“桌上哪个杯子是空的?”
- 医学影像分析:医学 VQA,回答关于 X 光片、病理切片的问题,辅助诊断。
- 智能相册与搜索:对个人图像库进行自然语言搜索,如“找出所有有海滩和狗的照片”。
- 电商与内容审核:回答关于商品图片的详细属性问题,或检测违规内容。
面临的挑战与发展趋势
语言先验与偏置
模型往往会利用训练数据中的表面统计相关性,而不真正理解图像。去偏置方法包括生成对抗样本、因果推断、数据增强等。
细粒度识别与推理
对颜色、纹理、计数的高精度需求,以及多跳推理(如“左侧第二个男人的帽子颜色”)还远未解决。
外部知识融合
许多问题需要常识或专业领域知识,如何将知识图谱、检索信息与视觉语言模型无缝集成是关键。
效率与部署
大模型虽性能卓越,但推理成本和时延限制了移动端应用。模型压缩、知识蒸馏、高效注意力设计仍是重点。
可解释性
用户需要知道模型为什么给出某个答案,注意力可视化、文本解释生成是活跃研究方向。
多语言与多文化
VQA 主要面向英文,构建中文及其他低资源语言的 VQA 系统,以及适应不同文化背景的答案仍有大量空白。
动手实践:快速搭建一个简易 VQA 模型
环境准备与数据加载
选择 VQA v2 或 CLEVR 作为入门。以下是一个基于 PyTorch 的极简实现概念:
import torch
import torch.nn as nn
from torchvision.models import resnet50
from transformers import BertTokenizer, BertModel
模型定义(简化的基线)
class SimpleVQA(nn.Module):
def __init__(self, num_answers, img_feat_dim=2048, ques_feat_dim=768, hidden_dim=1024):
super().__init__()
self.visual_encoder = resnet50(pretrained=True)
self.visual_encoder.fc = nn.Identity() # 去掉分类头
self.text_encoder = BertModel.from_pretrained('bert-base-uncased')
self.fusion = nn.Sequential(
nn.Linear(img_feat_dim + ques_feat_dim, hidden_dim),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(hidden_dim, num_answers)
)
def forward(self, images, input_ids, attention_mask):
img_feat = self.visual_encoder(images) # [batch, 2048]
text_output = self.text_encoder(input_ids=input_ids, attention_mask=attention_mask)
text_feat = text_output.pooler_output # [batch, 768]
combined = torch.cat([img_feat, text_feat], dim=1)
logits = self.fusion(combined)
return logits
训练循环概览
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
for epoch in range(epochs):
for batch in train_loader:
images, question_tokens, labels = batch
logits = model(images, question_tokens['input_ids'], question_tokens['attention_mask'])
loss = criterion(logits, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
实际应用时需构建数据加载器,将答案映射为固定类别编号,并实现评测逻辑。推荐在 Google Colab 上使用 VQA 的开源工具包(如 vqa-maskrcnn-benchmark 或 HuggingFace 的 transformers 中的 VQA 模型)。
进阶资源
- 论文必读:VQA 综述 (2017),Bottom-Up and Top-Down Attention,ViLBERT,LXMERT,BLIP-2。
- 开源框架:Hugging Face
transformers中的ViltForQuestionAnswering,MMF (MultiModal Framework),LAVIS。 - 在线课程:Stanford CS231n (视觉部分), CS224n (NLP部分) 中涉及VQA的章节。
- 竞赛平台:VQA Challenge 官网,EvalAI 评测。
通过从基础融合模型开始,逐步加入注意力、预训练视觉语言模型,你可以深入掌握视觉问答的核心奥秘。现在,找几张图片,试着问模型几个问题吧!