
1. 先搞清楚一个问题Visual Relationship Detection到底在做什么1.1 从检测出物体到理解物体之间的关系去年我被一个项目逼着去做图像中的关系推理最开始以为这就是目标检测一个分类头的事把两个框的特征拼在一起过个全连接层输出谓词类别完事。结果在真实验证集上被按在地上摩擦——尤其是那些视觉上几乎无法区分的谓词模型输出完全是在碰运气。后来翻到这篇Visual Relationship Detection with Language Priors才意识到问题不出在特征提取上而是在于我把这个任务理解得太窄了。Visual Relationship Detection视觉关系检测要解决的事情很直白给定一张图片输出形如主语谓词宾语的三元组比如人骑自行车、杯子放在桌子上。它和纯目标检测的本质区别在于检测只回答哪里有什么关系检测还要回答这些东西之间是什么关系。这里的主语和宾语通常是图像中的物体谓词则可以是空间关系on、above、under、比较关系taller than、动作关系riding、eating等。别看描述很简单这个任务有一个让纯视觉方法非常难受的特点组合爆炸。假设物体类别有100种谓词类别有70种那么理论上需要判别的关系组合就是 100 × 100 × 70 70万种。而训练数据里能覆盖到的组合通常只有几千种剩下的全是零样本组合。这还不算最棘手的——即使某个组合在训练集里出现了如果只出现了三五次视觉模型也根本学不出稳定模式。1.2 三个子任务与评测口径要读这篇论文第一步是搞清楚它评估的到底是什么。论文把任务拆成了三个由易到难的子任务Predicate Prediction给定真实的物体框和物体类别只预测两个物体之间的谓词。这是最纯净的评估用来衡量模型对关系本身的建模能力。Phrase Detection同时输出关系短语的边界框覆盖主语、宾语及其空间上下文和短语类别类似将关系描述当作一种带属性的区域检测。Relationship Detection从零开始检测物体再输出所有物体对之间的关系即检测关系联合任务。对应的评测指标主要是 Recall50 和 Recall100。意思是对每张图的预测三元组按置信度排序后取前50或前100个看能召回多少标注的真实关系。它不要求预测框和真实框完全重合只要求IoU超过阈值通常是0.5同时三元组完全匹配。还有一个容易被忽略的评测变体零样本关系检测zero-shot relationship detection。测试集中会故意安排一些主语-宾语对在训练集里没见过的组合比如训练集里从未出现过人-斑马的图片但测试集要求模型预测人骑斑马或者人喂斑马。这个设置直接考验模型的组合泛化能力也是本文语言先验最能发力的地方。1.3 纯视觉模型为什么在这里天然吃亏导师当年跟我说过一句话关系检测的难点不在于视觉特征提取而在于先验建模。我一开始没太当回事直到我在一个包含70个谓词的评估集上做错误分析才看懂。视觉模型本质是条件分布建模p(predicate | visual_features)它希望从图像像素里找到能区分不同谓词的线索。问题是大量谓词在像素层面几乎不提供判别信息。比如马看见人和马靠近人单看一张静态图视觉特征差异极小甚至人类标记者都需要借助常识或者视频上下文才能判断。再比如on和above在很多角度下视觉几乎一样模型只能靠猜。更糟糕的是数据分布。VRD数据集的谓词分布极度不均衡on、has、with这类高频谓词占了绝大部分样本而eating、chasing、carrying这类动作相关谓词数量很少。标准的交叉熵训练会让模型倾向于把所有关系都预测成高频类因为这样损失最小。我在复现时看到的现象就是纯视觉模型在on、has上的准度还行但长尾谓词几乎没有输出。这个困境指向一个关键洞察——关系三元组的联合分布并不是完全由视觉决定的。主语类别人和宾语类别苹果一旦确定人们能想到的合理谓词范围一下就缩小了吃、拿、看、放……而不太可能是飞。这种知识不需要看图片也能获得它藏在语言统计规律里。Language Priors 的思路正是把这个语言层面的先验显式建模出来去辅助视觉模型。2. Language Priors 的两个实现分支统计频率与词向量映射2.1 频率先验从训练集里直接统计谓词分布论文里第一种语言先验实现方式非常朴素但效果立竿见影。它的逻辑是这样的既然主语或宾语的类别已知那谓词的先验分布可以直接从训练三元组的统计中得到。具体做法是统计两组条件概率。第一组是主语条件分布p(predicate | subject)含义是当主语是人时谓词出现的历史概率分布——人更常与骑、吃、坐搭配几乎不与飞搭配。第二组是宾语条件分布p(predicate | object)含义是当宾语是苹果时谓词的概率分布——苹果更常与吃、拿、切搭配。然后对两者做组合论文里是对数域相加等价于假设主语和宾语条件独立得到给定主语-宾语对时的谓词先验分数。实现时有个小细节值得注意直接统计会有零概率问题。比如训练集里人和自行车同时出现时恰好没有骑这个标注那p(骑|人, 自行车)直接为0这对后续融合是非常不利的。所以必须做平滑处理最常用的是拉普拉斯平滑Add-1平滑给每个谓词至少一个单位的计数。别小看这个操作它对低频率类的鲁棒性影响很大平滑强度都不需要太大因为统计分布的峰值出现在高频类上主要目的是把尾部概率抬起来一点。这个分支的优点在于零训练成本和可解释性没有引入任何额外参数直接把标注库变成了知识库。缺点也很明显它完全无法泛化到统计中不存在的组合一旦测试时出现人-斑马这种训练里没见过的组合它只能给出接近均匀的先验帮助有限。2.2 词向量先验用词嵌入补上没见过的组合纯统计方法解决不了组合泛化这是词向量分支存在的意义。核心出发点非常漂亮语义相近的词在向量空间里距离也近人-马和人-斑马在语义空间里应该很接近那么人骑马这个关系的谓词向量对人骑斑马也是有指导意义的。具体做法大致分为三步。第一步用预训练好的 word2vec 把主语、谓语、宾语都映射到向量空间。第二步学习一个映射函数f输入主语和宾语的词向量论文里是把两者拼接后作为输入输出一个预测的谓语向量。这个映射函数用带隐层的全连接网络实现非线性映射能力足够。第三步预测出的谓语向量与候选谓词词表中的每个谓词向量做余弦相似度得到语言先验的打分分布。训练这个映射函数时输入是训练集中所有出现过的三元组里的(subject, object)监督信号是真实谓词对应的 word2vec 向量。损失函数用余弦相似度/均方误差这一类距离度量让预测向量尽量接近真实谓词向量。我复现时觉得这个方法本质上是在做从名词对到动词向量的回归。它真正厉害的地方在于即使测试时遇到训练集里没有的(subject, object)组合只要它们的词向量和某个训练过的组合语义相近映射函数输出的谓语向量就会倾向于落在合理的区域。这恰恰是频率先验做不到的。2.3 两种先验的适用边界维度频率先验词向量先验信息来源训练集三元组统计大规模语料预训练词向量建模对象离散条件概率表名词对到谓词向量的连续映射对高频关系非常准确取决于词向量质量和网络容量对未见组合基本失效有一定泛化能力计算成本几乎为零需要训练一个MLP成本低可解释性强可直接查看概率表弱只能观察向量近邻两种先验并不是竞争关系论文的用法是让它们各自贡献分数。频率先验负责把握全局分布形状词向量先验负责填补组合空洞两者相加通常比单独使用任何一个都稳。我后面会细说融合的具体公式。3. 视觉分支与语言先验的融合打分到底是怎么组合的3.1 视觉侧怎么提取关系特征视觉分支相对常规但有几个实现选择值得讲。输入是一对物体框(subject_box, object_box)以及它们的类别信息子任务不同类别来源不同在 Predicate Prediction 里直接用真实类别在 Relationship Detection 里用检测结果。特征来源是预训练检测网络的 RoI 特征比如 Fast R-CNN 的 fc7 层特征。除了两个框各自的视觉特征论文还利用了位置/空间信息。这在关系检测里非常重要因为很多谓词on、above、under、next to本质上是由两个框的相对几何关系决定的。常见的做法是把两个框的坐标差、面积比、交叠面积等几何特征拼进特征向量或者直接用一个单独的几何分支建模。视觉特征和几何特征拼接后经过两层全连接网络最后输出70维的谓词分数。一个在复现时容易踩的坑是训练视觉分支时如果只用正例三元组模型会缺少这两个物体之间没有任何标注关系的负例概念。但在关系检测的评估里你需要对所有物体对打分排序负例的控制直接影响Recallk的质量。实际做法是引入一个background类把所有出现过但未标注关系的物体对作为背景负例或者干脆忽略负例只对正例对打分——后者在零样本评测里更常用因为评测集合通常已经限定在标注过关系的物体对范围内。3.2 融合公式与权重λ的调参逻辑语言先验分支输出的是谓词分布分数视觉分支输出的也是谓词分数。融合方式论文里用的是加权组合大致可以写成score_final(predicate) score_visual(predicate) λ * score_language(predicate)或者写成概率域的乘法形式p(predicate | image, subject, object) ∝ p_visual(predicate) * p_language(predicate)^λ两种形式本质等价λ控制的是语言先验对最终决策的干预强度。λ越大模型越倾向于输出符合语言常识的关系λ越小模型越相信视觉证据。λ的取值直接决定成败这个必须调。我复现时的经验是先固定视觉分支单独把语言分支跑通观察它的分数量级再在一个小的验证集上网格搜索λ。如果λ太大模型会把所有人都预测成骑或吃因为这是语言先验里概率最高的选项视觉证据被完全淹没如果λ太小语言先验等于白加长尾谓词还是出不来。论文里给的效果范围我印象中是λ取1~2之间时增益最大但具体值依赖你的视觉特征规模和数据分布应以验证集为准。3.3 为什么不能只靠语言先验做推理一个很自然的问题既然语言先验这么强为什么还要视觉分支直接用p(predicate | subject, object)不就行了答案是语言先验描述的是一般规律而不是这张图的规律。一个反例是如果图里是一只狗和一辆汽车语言先验可能会强推狗追汽车但视觉证据表明狗只是站在车旁边如果你只有一个先验分布你完全无法感知这个反例。更常见的情况是同一对物体可以存在多个合理关系比如人在公园长椅上和人在长椅旁边在语言上都是合理的但视觉证据决定了到底是on还是next to。所以语言先验的角色应该是缩小搜索空间、提高长尾类别的排序而不是替视觉做决定。融合设计成可调节的加权形式就是这个考虑让视觉分支在主位语言先验在旁边扶一把。这个观念后来在做多模态模型时也一直影响着我先验是锚点不是答案。4. 实验复盘语言先验到底在哪些地方把效果拉起来了4.1 指标上的整体趋势论文的实验在主推的组合模型下相比纯视觉基线的提升是显著的。我当时看到这个结果的第一反应是语言先验的效果居然比很多精心设计的视觉特征还大。这和我们平时特征为王的直觉是相反的但它恰恰点出了关系检测任务的一个结构性特征——这个任务的难度很多不在视觉侧而在语义组合侧。具体数字我不建议你们照抄论文摘要里的单个值因为不同版本报告的口径有差异。我这里只说趋势在 predicate prediction 子任务上纯视觉模型和纯语言模型单独拎出来都不算强但两者融合后Recall100 和 Recall50 都有明显跳升融合效果大于各部分之和。这说明视觉特征和语言先验的信息有很好的互补性——视觉分支擅长识别动作类关系的细微差异语言先验擅长把高频谓词的排序拉对。4.2 从谓词类别维度看涨跌不是所有关系都受益把结果按谓词类别拆开能发现一个很有意思的分化语言先验的增益主要集中在两类谓词上。一类是高频但视觉线索弱的谓词。比如on、has、with它们的视觉特征高度相似模型经常搞混。语言先验在这里起作用的方式很直接当主语是桌子、宾语是书时先验强烈偏向on直接把视觉分支犹豫不决的分数拉开。另一类是中等频率的动作类谓词。比如eating、riding这些词在视觉上其实有线索但训练样本太少视觉分支学不扎实。语言先验提供了人食物 → 吃、人马/自行车 → 骑这样的语义惯性把排序往上提。反过来语言先验对高度依赖视觉细节的关系帮助有限。比如人注视猫与人靠近猫主语宾语完全相同区别全在人的姿态和朝向里。此时语言先验给两者的分数几乎一样最终还是得靠视觉分支来定。这也解释了为什么融合而不是替代是正解。谓词类型代表例子纯视觉表现加入语言先验后主要原因高频通用on、has、with尚可但容易混显著提升先验能区分高频类之间的倾向中频动作riding、eating学习不充分明显提升语义惯性补充训练样本不足高频空间above、below依赖几何特征提升有限视觉几何信息本身较强细微动作looking at、pointing at差帮助有限区分需要视觉细节语言无法提供4.3 零样本设置下语言先验的真正价值零样本关系检测是这篇论文最能展示语言先验实力的赛场。这里测试的三元组组合在训练中完全没出现过视觉分支面对的是彻底的分布外输入。纯视觉模型在这种设置下几乎只能依赖物体类别特征猜测Recall值非常低。频率先验在零样本组合下也基本失效因为它的概率表里根本没有这个组合的条目。真正起作用的是词向量先验即使人-斑马没有出现在训练集里但由于斑马与马的词向量接近映射函数可以把训练中人-马 → 骑的知识迁移过去给人骑斑马一个合理的先验分数。我在复现时专门跑了这一组实验结论和论文一致zero-shot 场景下加入词向量先验后指标提升幅度比全监督场景更大。这也给所有做组合泛化的研究者一个启发如果希望模型对没见过的概念组合有基本判断力必须在特征空间里保证语义相近的东西距离近这是语言预训练向量带来的免费午餐。4.4 定性结果模型输出到底能不能看论文里做了个挺有意思的人类评估实验让被试者判断一段关系描述是机器生成的还是人类标注的结果很多人区分不出来。这类图灵测试式的评估虽然有主观性但至少说明了加入语言先验后模型输出的关系三元组在语言合理性上有了本质提升。不过我复现时也发现定性结果里翻车的情况不少。最常见的错误是语言先验太强时模型会输出常识上可能但图像中不存在的关系。比如一张两个人并排走的图模型可能会输出人推人因为先验里人人推并不罕见。这类错误在指标上不一定暴露可能因为某个真实关系被排序在后导致recall变化不明显但在实际应用中是致命伤——这再次印证语言先验只能作为辅助不能成为主导。5. 复现这篇论文时最容易踩的坑5.1 数据集预处理一个定义不清就会毁掉实验VRD 数据集的原始格式是 JSON 标注包括图像 id、物体框、物体名词、关系三元组。第一步要把这些解析成统一的样本索引看起来简单但要处理几个容易出错的点。第一主语和宾语的多词名称问题。物体类别bike和bicycle可能同指一个东西但会被当成两个不同类别关系标注里的主语宾语有时候是短语而不是单词。做词向量先验前必须统一词表把多词短语映射到核心名词否则词向量查不到会产生大量噪声。我在复现时选择直接以数据集官方给的物体类别名称为准做映射效果比较稳。第二训练/测试划分中的信息泄漏。语言先验的统计是全局统计如果在统计p(predicate | subject)时混入了测试集三元组零样本评测就失效了。处理方式是严格只用训练集划分的标注来统计先验和训练词向量映射函数。第三负例的处理口径。很多复现版本会忽略负例只在有标注关系的物体对里做排序。这在实际使用时会有问题真实图片里大部分物体对之间没有显式关系推理时会给你输出一堆毫无意义的关系。建议在训练视觉分支时加入 background 类让模型学会不和物体对之间随便建立关系。5.2 词向量选择与映射网络训练的细节论文里的词向量即便是用预训练模型word2vec 本身也有版本和语料差异。我试过对比两个不同语料训练的 word2vec对最终指标的影响大概是1到2个点。如果你的实验对最终结果敏感建议在论文基础上固定一个公开可复现的词向量版本并说明清楚。映射网络训练时容易过拟合。输入是(subject_vec, object_vec)输出是谓语向量监督是真实谓词的 word2vec 向量。训练样本量不大数千到几万条三元组网络如果太大很容易在训练集上 loss 很低但预测的谓语向量落在语义上不合理的区域。我的做法是隐藏层用一层就够了比如256维加 dropout训练中监控验证集上的余弦相似度而不是训练 loss。此外对输出向量做 L2 归一化也有帮助因为最终比较用的是余弦相似度让输出落在单位球面上更稳定。5.3 训练和推理阶段的不一致问题视觉分支训练时用的是真实物体框但是在 Relationship Detection 评测里测试输入是检测器输出的预测框。检测框和真实框之间存在位置偏移特征分布会漂移。这在论文的 Predicate Prediction 子任务里不明显因为用的是真实框但放到联合检测时就非常突出。处理方式通常两种一是端到端微调检测器和关系分支二是把检测结果作为候选框在验证集上校准视觉特征例如对检测框特征做简单的scale归一。前者效果更好但工程复杂后者实现快但上限有限。论文本身更偏重方法验证所以复现时建议先跑通 Predicate Prediction 子任务再处理联合检测的工程问题。还有一个一致性问题是语言先验的全局高频偏置。统计先验天然偏向高频谓词如果不加控制融合后会让模型的预测分布整体向高频类收缩。我在调参时发现把语言分支的分数先做一次 z-score 归一化或log变换再与视觉分数相加比直接加原始分数更稳。这个经验论文里没写但对复现效果影响不小。5.4 零样本评测的计算规范零样本关系检测的评测集定义是测试三元组中的(subject, object)组合不出现在训练集标注里。这里有两个细节容易搞错。第一组合是否出现是按(subject, object)对来判断还是按subject, predicate, object完整三元组判断论文里用的前者。如果你的复现代码用了后者零样本集合会变大指标也会不同和别人对比时就会出现对不上数的情况。第二计算 Recallk 时排序列表里要不要过滤语法不合理的组合论文的做法是在候选里排除不满足语法规则的组合这也会影响分母必须在代码里保持一致。我当时因为没注意这两点跑了将近一周的实验结果和论文对不上后来逐行查评测代码才发现是排序候选集过滤逻辑的问题。建议复现时先拿论文公开的评测代码核对再自己写。6. 从这篇论文看语言先验思路的后续演化6.1 语言先验如何一路走向视觉-语言预训练这篇论文发表于2016年放在当时的背景里看它属于较早把语言统计规律作为一等公民引入视觉推理的工作。沿着这条思路往后的演化脉络其实非常清晰。2017年的 VTransE 用翻译嵌入translation embedding直接建模subject, predicate, object的向量关系思想是subj_vec pred_vec ≈ obj_vec本质上是对语言先验做更紧致的结构化建模。2018年的 Neural Motif Networks 则指出了另一个方向的先验视觉关系数据集中存在很强的上下文偏置比如某些物体的出现会带动周围关系模式这也可以视为一种更高阶的语言/常识先验。到了 Oscar、VinVL 这类视觉-语言预训练模型object tags 被显式用作视觉和文本之间的锚点说白了就是用语言标签来帮助视觉理解只是先验变成了可学习的跨模态对齐。还有一个不能再明显的继承者是 CLIP 这类大规模图文对比模型。它们做的是在海量图文对上学p(text | image)的分布这不就是一种从数据中涌现的语言先验区别只在于2016年这篇论文是先验来自小规模标注统计今天的模型先验来自上亿图文对。底层逻辑一脉相承视觉理解任务里的很多不确定性本质上要靠语言的分布规律来消解。6.2 现在复现这篇论文还有什么现实价值坦率地说今天再拿这个方法去打 SOTA 已经不现实了。大规模预训练模型的 zero-shot 和组合泛化能力已经远超这种手工设计先验。但我觉得它仍然值得复现和学习原因有三。第一它是理解 Scene Graph Generation场景图生成的最佳入口。今天所有场景图相关的论文基本都绕不开关系检测这个基础任务而这篇是少数把为什么关系检测难、语言先验为什么有用讲得特别清楚的方法之一。第二它提供了一个先验建模的范式课。做多模态任务时先验从哪来、怎么和视觉融合、融合强度怎么控制这三个问题绕不开这篇论文用最简单的方式演示了一遍完整流程。遇到新任务时我习惯先问自己能不能用这篇论文的思路搭一个 baseline往往比一上来就堆模型有效得多。第三它对长尾和组合泛化问题的剖析在今天仍然不过时。现在多模态大模型在常识性的组合上很强但在细粒度、罕见组合上依然会犯低级错误。理解用语言先验兜底这个思想对设计评测集、诊断模型失效模式依然有直接参考价值。我个人的体会是复现经典论文的价值不在于再用它做实验产出而在于借它的简单设计看清一个问题的本质结构。这篇论文用很朴素的语言先验讲明白了视觉关系检测的核心矛盾这个收获比任何指标提升都值。