ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

GQA数据集全流程实操:场景图、功能程序与视觉推理评测避坑指南

GQA数据集全流程实操:场景图、功能程序与视觉推理评测避坑指南 我第一次认真接触GQAGraph Question Answering数据集是在一个视觉问答项目里被VQA v2的语言偏置恶心到不行的时候。当时模型在训练集上跑得风生水起一上验证集就露馅——因为很多题目模型不看图都能答对它压根没在“看”只是在“背答案”。后来我把评测基准切到GQA整个团队对模型能力的判断才有了个更靠谱的参考。这篇文章不是官方文档复读而是我从下载、解析、训练到评测GQA的一整套实操记录外加这个数据集内部的场景图结构、功能程序、评估逻辑和一堆容易踩的坑。如果你正在做视觉问答、视觉推理、多模态大模型评测或者你只是好奇“一段自然语言问题是怎么从一张结构化场景图里自动生成的”这篇内容应该能帮你省掉不少摸索时间。1. GQA数据集是什么它凭什么能测出“推理能力”1.1 名字拆开看Graph、Question、AnswerGQA数据集的全称含义很好理解Graph对应底层的场景图Scene GraphQuestion和Answer则是叠加在场景图之上、通过自动组合生成的问答对。场景图是它的地基图片里的每个物体是节点物体和物体之间的关系是边物体的颜色、材质、位置等属性挂在对应节点上。整张图就被翻译成了一幅结构化的“图级知识图谱”后边所有问题都从这张图谱里派生出来。这个设计的妙处在于问答只是最终呈现形式真正的核心是“让模型跟结构化场景知识打交道”。你在GQA上做视觉问答表面是在做VQA实际上是在做组合式推理模型必须理解物体属性、物体之间的关系、空间位置、数量关系还要按照问题里的逻辑步骤逐步求解。这也是GQA和早期VQA数据集最本质的区别。1.2 发布背景它解决了VQA数据集的三个老毛病GQA由斯坦福大学团队提出发表于ICCV 2019。当时主流视觉问答数据集的问题已经很突出我概括成三条第一语言先验太严重。VQA v2之前的老数据集里“天空是什么颜色”这种问题答案大概率是“蓝色”模型只要学会语言模式就能蒙对。VQA v2通过配平正负样本缓解了一部分但问题本身依然偏向简单模型还是能走捷径。第二问题复杂度不够。大量问题停留在“是不是”“有几个”“什么颜色”这类单跳认知层面缺少“先找到桌子上的杯子再判断杯子左边的东西是什么”这种多步组合推理。单靠这种数据模型学不会真正的结构化理解。第三答案生成不可控。一个细节或属性对应好几个明显不同的答案表达模型只要选到其中一个就算对实际上它对场景的理解仍然模糊。GQA的做法是从数据源头重构所有题目都从场景图自动生成每个问题都带一个功能程序functional program相当于给问题配了标准“解题步骤”答案天然是确定且可验证的。这样模型就没法靠语言偏置浑水摸鱼想答对就得顺着场景图走一遍推理链路。1.3 与VQA v2、CLEVR、Visual Genome的横向对比很多朋友问我GQA和常见数据集到底什么关系我用一个表格做对照数据集图像来源问题规模是否带程序图像类型主要考察能力VQA v2COCO约110万否真实图像基础视觉问答、语言理解CLEVR程序合成约85万是合成图像组合式推理、多跳逻辑Visual Genome真实图像无标准QA部分真实图像场景图标注、关系理解GQAVisual Genome过滤官方称约2200万是真实图像组合推理、视觉问答、场景理解这个表一看就明白GQA想同时拿到CLEVR的逻辑严谨性和真实图像的复杂多样性。CLEVR的问题太规则、图像太干净模型在合成图上学到的推理很难迁移到现实中Visual Genome有海量结构化标注但没有标准QA任务VQA v2有真实图像和问答却缺程序化逻辑。GQA正好补在这个空档上。1.4 为什么发布好几年了现在依然值得关注大模型时代很多人觉得传统数据集过时了但我在评测多模态模型时依然会保留GQA。原因是模型越大越容易在常规VQA上刷分GQA这种带程序、带场景图、答案可控的数据集反而更容易暴露模型的真实推理短板。近两年具身智能也经常讨论“数据集质量”的问题GQA里“结构化场景图自动生成问题程序化答案”的组合对评估一个系统是否真正理解环境、能否根据指令执行多步推理非常有参考价值。它可能不是规模最大的但它的结构设计和评测理念至今仍然在线。2. 数据集构成与核心指标2.1 规模到底有多大GQA的官方数字我得先说清楚避免大家被不同来源搞糊涂。它包含约11.3万张真实图像这些图像来自Visual Genome经过筛选后保留下来覆盖大量真实世界复杂场景室内的、室外的、街景的、物品种类繁多的都有。场景图方面官方数据表明每张图平均包含约17个物体物体带属性标注物体与物体之间带关系标注。物体类别覆盖常见生活物品、动物、人等属性涵盖颜色、材质、大小等关系类型包括空间关系、动作关系、穿着关系等。整批场景图标注量非常庞大从几千万量级往下砍也够训练用。问答对数量要特别注意官方论文里说约2200万指的是通过场景图自动组合生成的全量问题集包括大量变体和组合。实际下载后官方在questions压缩包里也提供了这个完整集合但常规训练时大家基本会用train/val/test这样的划分文件训练集规模通常在百万条上下。所以如果你看到“GQA 2200万”和“训练集只有90万”两个说法不用怀疑它们都没错只是统计口径不同。2.2 官方数据划分与文件组织GQA官方把问答数据分成三类训练集、验证集、测试集测试集不公开答案。验证集用于本地调参测试集要提交到官方评测平台才能拿到分数。整个数据包主要包含四块内容图像文件、场景图文件、问题与答案文件、评估工具包。图像文件负责提供原始图片场景图文件提供每张图的图结构标注问题文件提供问题文本、答案文本、功能程序以及对应的图像ID评估工具包则是计算准确率和一致性指标的脚本。测试集不公开答案这个设计很关键。如果测试集答案公开了很容易出现团队反复用测试集调参的现象最终分数看起来漂亮但泛化能力没保证。把答案锁住倒逼大家在验证集上做扎实的迁移实验这是评测类数据集该有的态度。2.3 问题类型和答案分布GQA的问题设计覆盖面很广包括“是什么”“在哪里”“什么时候”“是谁”“哪一个”“怎么样”“是否是”以及“选择性问题”等。不同问题类型的难度差异很明显“是不是”类偏向判断验证模型对单一条件的理解关系和时间类问题需要模型真正建模物体之间的交互选择和比较类问题还要加入逻辑判断。答案形式以短语为主比如“红色”“在桌子上”“是”“不是”等。相比开放词典式的答案集GQA的答案空间要收敛得多这对评估准确率非常友好模型不需要生成一段长文本只需要给出一个短语或单词。但也别小看这个答案空间官方收集的答案类别依然有上千种想刷到高准确率并不容易。2.4 功能程序问题背后的“解题步骤”GQA最打动我的设计是功能程序。每个问题都对应一段程序化表达这段程序描述了从场景图中得到答案的完整步骤。举个例子对于问题“坐在沙发上的猫是什么颜色的”程序会先执行“过滤”操作找出图中所有“猫”再执行“关系”操作筛选出其中“坐在沙发上”的那些最后执行“查询属性”操作读取“颜色”属性。整个过程像是对场景图做了一次小型数据库查询。有了功能程序数据集能做很多事情第一可以对模型做中间监督不只看最终答案还能判断模型是否在正确的路径上第二可以按程序结构对问题做细粒度分层分析模型在哪些操作上容易出错第三可以做可控的数据增强通过操作组合生成更多样化的问题。这些能力在传统VQA数据集上是完全找不到的。2.5 评估指标的细节准确率以外还有一致性GQA官方评测不是只给一个准确率。除了常规的top-1准确率之外它特别强调一致性指标。一致性用大白话说就是模型对同一场景里同一个事实的不同问法回答必须自洽。比如场景图里明确有一只猫在沙发左侧那模型对“猫在沙发左边吗”和“沙发右边有猫吗”这两个问题不能一个答对另一个答错。如果出现这种矛盾说明模型其实没理解空间关系不过是瞎蒙对了一题。评测脚本还会考察答案的有效性和合理性。有效性看答案是否在合法答案集里合理性看答案是否跟场景相关内容匹配。这几个指标加在一起比单看准确率难作弊得多。我自己刷GQA时发现一个模型准确率涨了2个点但一致性掉得飞快这个模型八成是靠语言表层信息硬顶上去的。3. 数据格式与标注体系逐层拆解3.1 场景图的完整结构长什么样先打开场景图文件看一眼整体是JSON格式最外层键是图像ID每个图像ID下面挂着图像的宽高、物体列表等信息。物体这一层就很有意思了每个物体有唯一ID、名称、位置框坐标、属性列表和关系列表。位置框坐标是绝对像素坐标可以直接用来画框可视化属性列表存的是颜色、材质这类描述关系列表存的是该物体跟其他物体的关系每条关系指定了关系类型和目标物体ID。我贴一个简化后的结构示例{ 2345678: { width: 640, height: 480, objects: { 0: { name: cat, x: 100, y: 120, w: 80, h: 60, attributes: [gray, small], relations: [ {object: 1, name: on}, {object: 2, name: next to} ] } } } }实际文件里物体数量会多很多关系也更复杂。你完全可以把这份JSON当成一个图数据库来用两个物体之间的边就是relations数组里的条目。自己做推理模型时这种结构化数据可以直接喂给图神经网络。3.2 问答文件的JSON结构问答文件的顶层键是问题ID每条记录包含图像ID、问题文本、答案文本、功能程序以及一些辅助字段。我平时主要关心前四个字段。图像ID用来关联场景图和图像文件问题文本是模型输入答案文本是监督信号功能程序是中间推理路径。代码示例import json with open(val_questions.json) as f: qa json.load(f) qid list(qa.keys())[0] item qa[qid] print(问题:, item[question]) print(答案:, item[answer]) print(图像ID:, item[imageId]) print(程序:, json.dumps(item[program], indent2)[:2000])程序字段是一个嵌套结构最底层的操作通常是“过滤”上层操作可能是“关系”“验证”“选择”等。如果你之前接触过CLEVR会发现这个程序形式和CLEVR很像但GQA的操作类型更贴近真实语言表达跳出了合成图像的局限。3.3 用Python快速加载并打印一条样本第一次加载GQA时我强烈建议先跑一段脚本把样本可视化别上来就训模型。这样能帮你快速理解数据形态是否跟你预期一致也能发现文件格式是否有小的字段名差异。下面这段脚本可以打印问题、答案、图像ID并解析程序的主操作序列import json with open(val_questions.json) as f: qa json.load(f) def collect_ops(node): ops [node.get(operation)] for dep in node.get(dependencies, []): ops.extend(collect_ops(dep)) return ops for qid in list(qa.keys())[:5]: item qa[qid] print(Q:, item[question]) print(A:, item[answer]) ops collect_ops(item[program]) print(Ops:, ops) print(- * 50)输出可能类似Q: Is the cat sitting on the sofa? A: yes Ops: [verify, filter, relate]看到这个结构之后你就能理解为什么我说GQA的问题是带步骤的。操作序列本身就是一种监督信号。3.4 评估脚本和提交评测方式GQA官方GitHub仓库里有评估脚本下载后将你的预测结果保存成JSON格式键是问题ID值是该问题模型输出的答案文本然后跑评估脚本就能得到准确率、一致性等指标。python evaluator.py --predictions predictions.json --questions val_questions.json --scene_graphs val_sceneGraphs.json提交到测试集的流程也类似但要注意自己造好测试集问题的预测文件提交到官方评测平台之后由服务器计算分数本地永远看不到测试集的官方答案。这个机制保证测试集不被污染但也要求你必须在验证集上把问题彻底调明白再上测试。4. 从下载到训练一份完整实操记录4.1 下载前的准备工作GQA官网的下载入口是一个表单填一下名字、邮箱、机构这些基本信息提交后下载链接会发到邮箱里点邮件里的链接就能拿到各压缩包。这个流程不算复杂但有几件事务必提前准备。第一硬盘空间。图像文件加场景图加问答文件整套下载下来需要的空间相当可观建议至少预留几十GB具体大小以官网邮件说明为准。第二网络环境。推荐用服务器下载别用自己笔记本的浏览器断了又要从头来比较痛苦。第三核对文件完整性。有条件的话对一下文件大小或者MD5我踩过解压到一半发现文件损坏的坑。4.2 服务器上的目录组织和解压在服务器上建个目录专门放GQA然后按模块解压不要把所有文件都塞到根目录。我习惯这样组织mkdir -p /data/gqa cd /data/gqa wget 邮件中的下载链接 unzip questions1.2.zip unzip sceneGraphs.zip unzip images.zip unzip eval.zip解压完最好看一眼目录结构确认图像文件、场景图文件、问答文件各自路径。尤其是图像GQA图像来源是Visual Genome文件名可能跟Visual Genome原始ID不完全对应后续加载数据时要以场景图或问答文件里的图像ID为准。4.3 第一步读取一个场景图并可视化可视化这一步特别能帮助理解数据。我直接把目标图像和场景图里所有物体的框画出来代码不复杂import json from PIL import Image, ImageDraw with open(val_sceneGraphs.json) as f: sgs json.load(f) image_id 2345678 sg sgs[image_id] img Image.open(fimages/{image_id}.jpg).convert(RGB) draw ImageDraw.Draw(img) for obj_id, obj in sg[objects].items(): x, y, w, h obj[x], obj[y], obj[w], obj[h] draw.rectangle([x, y, x w, y h], outlinered, width3) draw.text((x, y - 10), obj[name]) img.save(gqa_sample_vis.jpg)运行完你会看到一张图上密密麻麻都是框每个框都对应一个物体。这时候再去看问题文本比如“猫左边的东西是什么”你就能很直观地理解模型需要完成的任务先定位猫再按空间关系找到目标物体最后读取名称。这种具象认识对后续设计模型非常有帮助。4.4 第二步构建一个人能跑通的简单VQA基线模型结构不用复杂一个基础的双流模型就够跑通流程。图像分支用预训练ResNet提取特征文本分支用LSTM编码问题然后把两个特征拼接起来送进全连接层做答案分类。# 伪代码级别的训练循环 import torch.nn as nn class SimpleVQA(nn.Module): def __init__(self, vocab_size, answer_size): super().__init__() self.resnet load_pretrained_resnet() self.lstm nn.LSTM(vocab_size, hidden_size256) self.classifier nn.Linear(2048 256, answer_size) def forward(self, image, question_tokens): img_feat self.resnet(image) # (B, 2048) q_feat, _ self.lstm(question_tokens) # (B, 256) logits self.classifier(torch.cat([img_feat, q_feat], dim-1)) return logits loss_fn nn.CrossEntropyLoss() # 正常往下写数据加载和训练循环即可这个模型准确率肯定不高但它能验证数据加载逻辑有没有问题图像有没有对上、问题文本有没有进对位置、答案词表有没有建全。跑通这一步之后再去替换更强模型就顺理成章了。4.5 内存优化与训练技巧很多朋友一上来就踩内存爆掉的坑。场景图和问答文件都是大JSON直接json.load进内存16G内存的机器会很吃力32G的也未必舒服。我的做法是分片加载。既然问题文件是JSON对象可以用流式解析或者按需加载把不需要的字段先剔除。图像特征可以提前抽好存成npy或h5文件训练时直接读特征不要再走一遍ResNet。构建答案词表时统计训练集答案覆盖度把出现次数很低的答案归入“未知”类能有效缩小分类头规模。训练过程中验证集的评估阶段建议用官方评估脚本算准确率和一致性而不是自己写个简单的LoRA分类正确率了事。GQA的一致性指标很能反映问题很多模型准确率还行但一致性崩掉这种模型拿到真实场景里基本不能用。5. 常见问题与避坑指南5.1 下载和文件问题问得最多的是邮件链接失效。这种链接一般有有效期过期了去官网重新填一次表单即可。还有图像包过大导致下载中断的问题建议用支持断点续传的下载工具或者拆成多个压缩包逐个下载别硬扛一个超大文件。解压后记得做一次完整性检查。GQA官网通常会提供文件校验值或大小参考如果发现解压报错基本就是文件下载不完整重新下载对应文件是唯一办法。5.2 大JSON文件解析和内存问题问答文件是几十万甚至是百万级条目的JSON直接json.load非常耗内存。我踩过一次内存溢出的坑之后改成了流式解析工具比如ijson配合字段过滤效率立刻上来了。如果你只关心question、answer、imageId、program这几个字段可以解析时只保留它们丢掉其他辅助字段内存占用能降一大截。还有一个实际操作建议把问答文件转成更紧凑的格式比如parquet或pandas DataFrame后面每次实验加载就快很多。第一次转换虽然要等一会儿但后续节省的时间非常可观。5.3 测试集没有答案怎么提交测试集不公开答案这个很多人一开始不习惯。我的建议是先在验证集上充分调参把验证集准确率和一致性都稳定了再跑到测试集上提交。提交格式一般就是JSON文件键是问题ID值是答案文本字段名不能写错否则服务器直接报错。注意保存好你的问题ID映射。有些人把问题ID改成从0开始的索引导致提交时对不上号白白浪费提交次数。我的习惯是始终保留原始问题ID所有中间处理都带着原始ID走避免最后做映射时出错。5.4 与COCO、Visual Genome等数据集配合使用GQA图像来自Visual Genome所以如果你同时用Visual Genome的原始标注有时能对照着做跨数据集迁移。COCO跟GQA没有直接对应关系但如果你做的是目标检测或分割的预训练再用GQA做视觉推理评测这条路径是完全可行的。需要特别注意的是ID对应关系。GQA内部使用的图像ID跟Visual Genome的原始ID可能有差异使用前务必确认映射关系别想当然认为两个ID是同一个数字。5.5 常见问题速查表问题现象可能原因解决办法下载链接失效链接过期重新填写表单获取新链接解压文件报错压缩包下载不完整重新下载并核对校验值内存溢出JSON文件过大流式解析、字段过滤、转parquet训练时图像对不上图像ID映射错误按场景图/问答里的imageId索引图像测试集提交失败预测JSON字段名错误对照官方提交模板检查格式准确率高但一致性低模型依赖语言偏置引入程序监督或做推理结构增强6. 一些使用体会与扩展方向6.1 什么时候选GQA什么时候不选我个人观点GQA非常适合做推理能力评测和结构化场景理解研究尤其是你想验证一个模型到底有没有真正理解多跳关系时。但如果你的目标是做开放域对话或大规模预训练数据GQA的问题仍然偏模板化多样性不足以单独作为预训练语料。通常我会把GQA跟VQA v2、COCO Caption等混合使用让模型既接触真实开放问答又有场景图约束下的严格推理训练。另一个建议是别只盯着最终准确率。GQA最值得利用的就是功能程序和场景图这两个中间监督研究性项目完全可以把程序当训练目标让模型学会“先找物体再找关系再输出答案”这在可解释性上价值很大。6.2 后续还能怎么玩我对GQA的期待还远没到头。一方面可以基于它的程序生成更多复杂问题把单跳问题改造成多跳推理链另一方面可以把它跟现代视觉大模型结合设计组合性更强的评测任务比如“换一张图但保留同样的问题模板看模型是否稳定输出一致答案”。具身智能领域同样值得参考。机器人要理解“先拿起红色杯子左边的钥匙”这类指令本质上就是GQA里“关系属性空间推理”的组合。把GQA的结构化标注迁移到具身场景作为数据集质量校验或者模型评测基准都是值得尝试的方向。最后说一点个人体会我每次训练完一个模型都会回看几个GQA的失败案例。答案明明很直观模型就是会在关系型问题上栽跟头而且栽得很稳定。与其纠结刷高那一个点不如用GQA先把模型的推理短板彻底排一遍。这个习惯我到现在做多模态评测都还在用。
返回列表