跳转到内容

DPR — 用 BERT 双塔把检索从 BM25 时代拉进稠密向量时代

是什么

DPR(Dense Passage Retrieval)是一种用神经网络做开放域问答检索的模型——给一个问题,它从千万级段落库里挑出最可能含答案的几段。日常类比:旧搜索引擎(BM25)像图书管理员只认书名和关键词,你问 ‘苹果手机售价’ 必须文档里写过 ‘苹果’ 和 ‘手机’ 才能召回;DPR 像一个读过全部书的人,他把每段话理解后浓缩成一张 768 维的语义卡片,你问问题时也浓缩成同样的卡片,然后比对卡片间的相似度——哪怕原文一个关键词都不重,也能找到。

它解决的痛点是 2019 年开放域 QA 的瓶颈:BM25 召回的段落里正确答案常常根本不在,下游 reader 模型再强也无能为力。DPR 把召回阶段换成稠密检索,端到端 QA 准确率提升 9-19 个绝对点。

为什么重要

不理解 DPR,下面这些事都没法解释:

  • 为什么 2020 年之后 RAG 系统的默认检索器是 ‘双塔 BERT + faiss’,而不是 BM25
  • 为什么 ColBERT / SPLADE / E5 / BGE 这些后续模型全在 ‘DPR 框架的某个零件’ 上做改进
  • 为什么 ‘in-batch negatives’ 成了对比学习训练检索器的工业标配
  • 为什么开放域 QA 的两阶段架构(retriever + reader)能在 2020 年突然爆发——retriever 终于配得上 reader

核心要点

DPR 的全部巧思可以拆成 三步

  1. 双塔编码:问题用一个 BERT,段落用另一个 BERT(不共享权重)。各自取 [CLS] 那个 768 维向量当作整段的代表。这一步关键在 不共享权重——问题和段落的语言风格不同,分开学习更准。

  2. 内积相似度:问题向量 q 和段落向量 p 算 sim(q, p) = q · p,最大的就是答案最可能在的段落。预先把所有段落编码后存进 faiss,查询时只算一次问题编码 + 一次 ANN 搜索。

  3. 对比学习训练:每个正例(问题,正确段落)配一堆负例。负例两种来源——同 batch 里别人的正例(in-batch negatives,免费拿)+ BM25 召回但不含答案的段落(hard negatives,更难辨)。loss 推动正例对内积高、负例对内积低。

三种检索范式对比

范式表达方式速度精度关键词依赖
BM25词频统计+IDF
DPR 单向量768 维 [CLS]极快
late interactiontoken 级向量聚合更高

DPR 占据 ‘极快 + 高精度’ 的格子,是后来稠密检索的工业默认起点。

实践案例

案例 1:DPR 召回为什么比 BM25 强

问题:‘谁发明了万维网?‘。文档:‘蒂姆·伯纳斯-李在 1989 年于 CERN 提出了一种超文本系统的设计……’。

BM25 看 ‘万维网’ 是否出现——文档里写的是 ‘超文本系统’,关键词不重合,召回失败。DPR 把问题和文档各自编成 768 维向量,‘万维网’ 和 ‘超文本系统’ 在语义空间中靠近,内积高,召回成功。

这就是 ‘从字面到语义’ 的跃迁。

案例 2:五个 QA 数据集上的实测

数据集BM25 Top-20DPR Top-20提升
Natural Q.59.178.4+19
TriviaQA66.979.4+13
WebQuestions55.073.2+18
CuratedTREC70.979.8+9
SQuAD68.863.2-6

注意 SQuAD 上 DPR 反而输给 BM25——SQuAD 的问题是注释员看着段落写的,关键词重合天然高,BM25 的字面匹配反而占优。这给后人留下经验:领域不同则检索器选择不同

案例 3:in-batch negatives 为什么这么省

batch 大小 128,里面是 128 对(问题,正例段落)。训练时把它当成一个 128×128 的矩阵——对角线是正例,其他全是别人的正例当成 ‘我的负例’。这样一次前向就有 127 个负样本,不用额外 GPU 计算。

加上 BM25 hard negatives(每个问题挂 1-2 个),总负样本超过 250 个/问题,训练信号充足。

案例 4:检索质量如何影响下游 QA

DPR 论文里给了 retriever 召回率到端到端 QA EM 的传导:retriever Top-100 召回率从 BM25 的 76% 提到 DPR 的 86%,下游 reader 同款不变,QA EM 从 32 涨到 41。这十个百分点几乎全来自检索阶段的提升——证明了 ‘检索是 QA 的天花板’。

踩过的坑

  1. 训练数据要带正例:没有 ‘问题-正例段落’ 配对就训不了,所以 DPR 强依赖 NQ / TriviaQA 这种已标注集,冷启动困难。

  2. 领域漂移严重:MS MARCO / NQ 训出的 DPR 直接用到医学、法律、代码上效果会大幅下降。后来 BEIR 基准证明这点,并催生了 GPL / E5 等领域无关训练法。

  3. hard negatives 选择敏感:BM25 挑出的 ‘负例’ 里偶尔混着真正的正例(标注遗漏),训练时被当负例打压,模型反而学坏。实践里要做去重和置信度过滤。

  4. single-vector 信息瓶颈:768 维浓缩一段几百字必然丢信息。问题里多个细节(日期+地点+人名)很难全保留,这是 ColBERT / late interaction 后来要解决的痛点。

  5. batch size 决定上限:in-batch negatives 越多越好,但 GPU 显存有限;后来 GradCache / cross-device 通信解决这个。原文用 V100 32G 跑 batch 128。

  6. inner product vs cosine:DPR 用内积不归一化,向量长度参与打分——长向量天然分高,可能产生偏置。后来很多工作改用 cosine(先归一化)。

  7. reader 端是否一起训:原文分两阶段(先训 retriever 再训 reader),后来 RAG / REALM 证明端到端联合训练能再涨点,但实现复杂。

  8. 段落切分粒度敏感:DPR 假设输入是 100 词左右的段落,太长会被截断丢尾,太短则上下文不全。预处理阶段的 chunking 策略(固定窗口 / 句子边界 / 滑动重叠)直接影响最终召回率,这是工程上常被忽视的隐含超参。

适用 vs 不适用场景

适用

  • 开放域 QA 的检索阶段,候选段落量级 1M-100M
  • 用户查询和文档语言风格差异大(口语问 vs 正式答)的场景
  • 已有大量标注 ‘问题-段落’ 对的领域(NQ / TriviaQA / 客服 FAQ)
  • 需要毫秒级检索 + 千万级索引的工业 RAG 系统

不适用

  • 关键词匹配天然强(SQuAD 类、产品 SKU 搜索)→ 先试 BM25
  • 完全没标注数据的冷启动 → 选 BM25 或 contriever 这种无监督稠密检索
  • 候选段落 < 1000 → 直接用 cross-encoder 全量打分
  • 需要可解释打分(合规要求)→ 选 BM25 加神经 reranker

历史小故事(可跳过)

  • 2018 年:BERT 出世,但拿来检索只有少量探索,主流仍是 BM25 + 神经 reranker 两段式
  • 2019 年:ORQA(Lee et al.)首次端到端联合训练 BERT 检索器+reader,效果好但训练昂贵
  • 2020 年 4 月:Karpukhin 等人在 Facebook AI 提出 DPR——把检索单独训练,简单粗暴但全面碾压 BM25,发表在 EMNLP 2020
  • 2020 年下半年:ColBERT / RAG / REALM 三个方向同时爆发,全把 DPR 当起点
  • 2022 年:BEIR 基准揭示 DPR 跨领域弱点,催生 contriever / GPL / E5 一系列零样本检索方案
  • 2024 年:DPR 思想在 RAG 工业落地中无处不在——Cohere / OpenAI Embeddings / BGE / Jina 都是 ‘DPR 加大版’

学到什么

  1. ‘语义 vs 字面’ 的换代——DPR 让检索从 1972 年 BM25 时代正式进入神经向量时代,后续十年的检索研究全在这个框架内
  2. 双塔的工程价值是 ‘可预索引’——问题和段落各自独立编码,段落向量可提前算好存 faiss;这是和 cross-encoder 的根本分界
  3. 对比学习负样本是命门——in-batch negatives + BM25 hard negatives 是 DPR 的核心训练秘方,几乎所有后续检索器都沿用
  4. ‘够用就好’ 的力量——DPR 没用什么花哨结构,就是 BERT [CLS] + 内积 + 对比损失,但通过精心选择训练数据和负例就赢了;提醒后人系统设计常常拼细节而非新概念
  5. 领域是检索器的隐含维度——同一架构换领域要重训,这个限制至今没完全解决,是 BEIR / E5 等后续工作的主战场
  6. 数据胜过架构——DPR 没有引入新结构却赢了 BM25,说明 ‘怎么训’ 比 ‘怎么搭’ 重要,这条经验被后来 SimCSE / E5 反复印证
  7. 检索是 QA 的天花板——下游 reader 再强也救不了召回失败的样本,DPR 把这个天花板抬高了 10 个点,这是开放域 QA 在 2020 年集中爆发的真正原因

延伸阅读

关联

  • bert —— 提供 [CLS] 向量作为整段语义代表,是 DPR 双塔的基础
  • colbert-2020 —— 直接后继,把 DPR 单向量换成 token 级 late interaction,精度更高
  • dssm-2013 —— 双塔思想的鼻祖,DPR 是 BERT 时代的重写版
  • bm25-okapi —— DPR 的对照基线,论文里展示了 5 个数据集上的对比
  • okapi-bm25-1994 —— 经典字面检索算法,DPR 在 4/5 QA 数据集上压制它
  • anserini-2017 —— BM25 的现代实现,DPR 论文里的实际跑分基线
  • transformer —— BERT 的底层架构,间接是 DPR 表达能力的来源
  • attention —— BERT 内部的核心机制,让 [CLS] 能聚合整段语义

反向链接

  • ance-2020 —— ANCE — 让模型自己挖训练负例,对比学习的”自给自足”
  • anserini-2017 —— Anserini — 把工业搜索引擎 Lucene 改造成学术 IR 实验台
  • attention —— Attention Is All You Need
  • bert —— BERT — 双向 Transformer 预训练
  • cocondenser-2021 —— coCondenser — 让 BERT 的 [CLS] 在预训练就学会”代表整段话”
  • colbert-2020 —— ColBERT — 让 BERT 检索既准又能扛大规模
  • doc2query-2019 —— doc2query — 让模型替文档预想”会被怎么搜”再写进倒排表
  • e5-2022 —— E5 — 用海量”自然出现的文本对”训通用 embedding
  • ms-marco-2016 —— MS MARCO — 1 千万 Bing 真实查询喂饱神经检索的标准评测集
  • replug-2023 —— REPLUG — 不动 LLM 一根毛,只把检索器调到它的”口味”上
  • rocketqa-2021 —— RocketQA — 把稠密检索的训练拧到工业级
  • splade-2021 —— SPLADE — 让神经网络学出稀疏向量,直接复用倒排索引