信息速览
一个抽取式模型在一代阅读理解基准上拿到 86 分 F1,看起来已经能读文章。把同一个模型搬到加入不可回答题的下一代基准上,分数掉到 66 分。掉的不是识字能力,也不是匹配能力——同一篇文章、同一批段落、同一套指标——掉的是"知道自己不知道"这件事本身。这条落差之所以值得反复引用,是因为它把一类平时看不见的失败变成了可以量化的数字。而做出它的方法朴素得有些意外:没有新的模型结构,也没有新的评测公式,只是请众包工作者专门去写那种读起来像能答、实际在这一段里无处可答的问题。2016 年的版本给出十万余个人工提问,2018 年的版本在同样的文章上追加五万余道这样的题,两者合起来恰好是一次干净的前后对照。
在此之前,机器阅读理解的评测长期困在一个替代方案上:用自动生成的完形填空考题,或者给几个选项做多选。这类构造省力,却把任务改写成了匹配题——模型可以靠句子表面的重合度拿高分,不必真正处理问句与文本的关系。SQuAD 换了三条规矩:问题由人读完段落之后自己提;答案必须是原文里的一段连续文字,用字符偏移锁定;提这十万个问题的人,事先并不知道答案应该长什么样。三条规矩叠加,才有了那条 86 到 66 的落差。
它同时也把"稀缺性"钉死在一个具体的形状上:维基百科公开文本、英文、单语言、单任务、答案必须能被两个指针夹住。这既是它在十年间被反复当作基准的原因,也是它不适合当做生成式问答或多跳推理训练粮的原因。一屏速览见下表。
一屏速览
| 维度 | 内容 |
|---|---|
| 全名 | Stanford Question Answering Dataset(SQuAD),斯坦福问答数据集 |
| 发布方 | 斯坦福大学 Stanford NLP Group;Rajpurkar、Zhang、Lopyrev、Liang 提出 |
| 首次发布 | 2016 年 6 月(arXiv:1606.05250,EMNLP 2016),官方页面称 SQuAD 1.0/1.1 |
| 现行版本 | SQuAD 2.0,2018 年 6 月(arXiv:1806.03822,ACL 2018) |
| 官方站点 | https://rajpurkar.github.io/SQuAD-explorer/ (旧址 stanford-qa.com 仍可直接访问) |
| 语料来源 | 英文维基百科(English Wikipedia)文章的正文段落 |
| 1.1 规模 | 100,000+ 问答对,覆盖 500+ 篇文章(官方主页口径) |
| 2.0 构成 | 1.1 的十万道题 + 五万余道众包编写的对抗性不可回答题 |
| 发布文件 | train-v2.0.json(官方标注 40 MB)、dev-v2.0.json(官方标注 4 MB) |
| 实际体积 | train 42,123,633 字节;dev 4,370,528 字节 |
| train 集清点 | 442 篇文章、19,035 个段落、130,319 道题,其中 43,498 道标为不可回答 |
| dev 集清点 | 35 篇文章、1,204 个段落、11,873 道题,其中 5,945 道标为不可回答 |
| 测试集 | 隐藏不发布,须提交模型由官方运行评测 |
| 文件格式 | 单个 JSON 文件,顶层 version 与 data 两层 |
| 答案形态 | 上下文中的连续字符片段,由 answer_start 字符偏移定位 |
| 标注方式 | 众包工作者阅读段落后自行提问,并在段落中标出答案片段 |
| 许可 | CC BY-SA 4.0(署名—相同方式共享) |
| 评测指标 | 精确匹配(Exact Match,EM)与词级 F1,两个榜单一律双列给出 |
| 人类表现 | 1.1 榜单:EM 82.304 / F1 91.221;2.0 榜单:EM 86.831 / F1 89.452 |
| 榜单前列 | 1.1 榜首 {ANNA}(单模型)EM 90.622 / F1 95.719;2.0 榜首 IE-Net(集成)EM 90.939 / F1 93.214 |
| 典型用途 | 抽取式问答训练与评测、跨度指针网络研究、预训练语言模型微调基准 |
| 明确不适合 | 生成式问答、开放域无上下文问答、多跳推理、非英文场景、艺术性或观点性提问 |
§1 它要解决的具体麻烦
1.1 阅读理解评测一直在用"别人的任务"顶替
在 SQuAD 出现之前,做机器阅读理解的人手里的评测资源大致是两类。第一类是自动构造的完形填空:从文章里挖掉一个词或实体,让模型填回去。它便宜、规模可以无限放大,但答案只能是那个被挖掉的符号,问句本身不承担语义,模型学到的是"在附近找同类词"。第二类是把人工编写的考试题或四选一题目印刷化,它引入了真正的问句,但答案空间被压缩成几个选项,模型可以通过排除靠一个关键词的错配拿到正确的那一票。
真正的麻烦在于:这两类替身都无法回答"模型到底读懂没有"。它们很容易被化简成一道道技巧题,而模型并不需要对齐问句里的中心词与文本里的述谓。SQuAD 的替代办法是把评测拉回最原始的形状——给一段原文,提一个问题,答案必须是从原文里拎出来的一段话。这个形状有三重约束力:
| 约束 | 它排掉了什么 | 结果 |
|---|---|---|
| 问题由人提,且提时看不到标准答案 | 排掉"逆向出题"的模板题 | 问句的语法与侧重点自发多样化 |
| 答案必须是原文连续片段 | 排掉自由生成与选择题的取巧路径 | 任务变成"在文本上定位一段区间" |
| 答案由多名众包分别给出 | 排掉单一标注者的措辞偏好 | 评测时与多份人工参考答案逐一比对,取最高的一份 |
第三重约束尤其关键,它直接决定了 F1 怎么算:预测结果要和该问题的多份参考答案分别比,取最高的一份。这不是给模型放水,而是承认"这一段文字到哪收尾"本身就有多种合理切法。它同时带来一个附带好处——评测不需要任何外部资源:不用同义词词典、不用句法解析器、不用人工裁判,一个脚本给出两个数即可。这也是为什么这个任务能在十年里被几千篇工作反复引用而不产生口径分裂。
1.2 三条常见的错误期待
第一条,期待它是"更大的训练集"。SQuAD 的任务形状非常窄:给定段落,答案必在段落里。在这个形状下训练出来的能力很难迁移到"答案不在给的上下文里"的现实场景,反而会强化模型"随便挑一段"的倾向。2.0 版引入不可回答题,就是官方自己对这条期待的直接回应。
第二条,期待它是"问答通用能力的证明"。榜上 EM 与 F1 都清楚地超越人类数字,但这个超越发生在单段落、必定可答、单谓词的窄任务上。它证明的是跨度定位能力强,不是语言理解能力可以跨任务迁移。
第三条,期待官方发布了完整数据。实际上官方只发训练与开发两个文件。很多论文把 dev 集当最终发布会数字用,严格来说那不是榜单口径——榜单成绩必须经过官方隐藏测试集(§5.5)。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 抽取式问答的训练与评测 | 十万余题、标注严格、评测脚本公开 | 够,这是它设计的起点 |
| 跨度指针网络 / 起始结束位置预测研究 | 答案带字符偏移,可直接监督位置 | 够,且是最早成规模的位置监督语料 |
| 弃权(abstention)机制研究 | 五万余道敌手写成的不可回答题 | 够,这是别处很难复制的设计 |
| 预训练语言模型的能力体检 | 榜单双列 EM/F1 并保留历年提交记录 | 够做体检,不够做能力推断 |
| 生成式问答 / 自由文本答复 | 答案为原文片段 | 不够,训练目标本身即受限 |
| 开放域问答(不给上下文) | 每题都绑定一段上下文 | 不够,需另配检索层 |
| 多跳 / 跨文档推理 | 每题只在单段落内答题 | 不够,答案永远在同一段里 |
| 中文等非英文任务 | 仅英文 | 不够,官方发布物不含其他语言 |
| 医学或法律等专业领域问答 | 语料为通用维基百科 | 不够做领域上线,可做领域适应对照 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你刚写完一个跨度预测模型,需要一个标准跑道 | 提供统一口径的 EM/F1 与官方评测脚本,可与已发表结果直接对比 | 在 dev 上调通,然后按官方教程提交拿 test 成绩 |
| 你担心模型"蒙也会蒙一个" | 2.0 里一半左右的开发题无法回答,专测弃权 | 分别报告可答题与不可答题上的成绩,别只看总分 |
| 你在做医学抽取式问答,缺一个通用领域的对照 | 同为抽取式、同为 span 监督,可把领域模型放回这里看掉分 | 用站内 emrqa、clicr 一类医学抽取式资源做领域侧,SQuAD 做通用侧 |
| 你要给预训练模型做能力体检 | 榜单把人类表现与机器表现同列,能看出逐年进展幅度 | 只把它当体检项目,别当上线效果的承诺 |
| 你想复现某篇论文的训练流程 | 只有两个 JSON 文件,无解压、无附属清单 | 一次下完即可(§5.2),注意保存原始字节数做校验 |
1.5 一句话判断
它不是"更大的粮仓",而是"更窄的跑道":把每一个问题都钉在同一段维基文字上时,模型没有瞎猜的余地,也因此它的分数能被解释。
1.6 不适合谁:四条边界
不适合拿来做通用问答系统的最终效果评估。 任务形状锁死在"给定段落、答案在内",缺了检索层与无法定位的诚实回答,这两件恰恰是产品上线最容易翻车的地方。
不适合拿来做多语言或跨语言迁移的结论。 官方只发英文。任何把它翻译再造的版本都不在 CC BY-SA 4.0 的原始发布范围内(§3.4),引用时要写明那是第三方重制。
不适合拿来训练自由生成式答复。 答案的形态只有"原文片段"一种,用久了会让模型养成"复述即答"的习惯。
不适合做专业领域的直接上线依据。 它是通用百科语料。在医学、法律、金融这类高风险领域,它最多扮演对照组的角色,不能替代领域内的评测(§6.3)。
§2 数据构成与规格
2.1 只有两个文件,却有两层嵌套
作为 SQuAD 抽取式阅读理解集的官方发布物,页面上只有两个下载按钮:训练与开发。没有目录树、没有压缩包、没有校验和文件。下载回来的是两个独立的 JSON,结构完全一致。
| 项 | train-v2.0.json | dev-v2.0.json |
|---|---|---|
| 官方标注体积 | 40 MB | 4 MB |
| 实际字节数 | 42,123,633 | 4,370,528 |
| 顶层字段 | version、data |
version、data |
version 取值 |
v2.0 |
v2.0 |
| 清点到的文章数 | 442 | 35 |
| 清点到的段落数 | 19,035 | 1,204 |
| 清点到的题数 | 130,319 | 11,873 |
| 其中不可回答题 | 43,498 | 5,945 |
id 唯一性 |
130,319 个互不重复 | 11,873 个互不重复 |
plausible_answers |
不可回答题均带该字段 | 不可回答题几乎都带该字段 |
两个文件加起来不到 50 MB,全量一次下完毫无压力,这也是它在教学与快速复现场景里特别好用的原因。层级始终只有文章、段落、题三层,字段总数不超过十个,读一遍即可穷举——这种"结构透明"本身是一种重要的工程属性:没有隐含的表、没有关联主键要 join、没有需要额外下载的元数据。
嵌套关系可以这样顺着往下走:data 是文章数组,每篇文章有 title 与 paragraphs;每个段落有 context 与 qas;每道题挂在具体段落下。这意味着上下文不是每题一份副本,而是每题引用所属段落的那一份正文。做上下文缓存或去重时,应该以段落为单位去重,而不是以题为单位。换句话说,直接把习题撑平成"每行一个问题"的表会让同一段正文重复几十次,处理全量训练集时这一点直接决定了显存放不放得下。
2.2 字段字典
| 字段 | 位置 | 取值形态 | 含义 | 使用注意 |
|---|---|---|---|---|
version |
顶层 | v2.0 |
数据集版本串 | 是字符串而不是数字 |
data |
顶层 | 数组 | 文章列表 | train 442 项,dev 35 项 |
title |
文章 | Normans、Sky_(United_Kingdom) |
维基页面名 | 保留下划线与括号,可直接当 URL 段 |
paragraphs |
文章 | 数组 | 该文的段落列表 | 同一文章多段共用同一个 title |
context |
段落 | 字符串 | 段落正文,答案必在其内 | 是答案偏移的唯一参照系 |
qas |
段落 | 数组 | 挂在该段下的题目 | 一道题只属于一个段落 |
question |
题 | 字符串 | 众包提出的问题 | 无 ? 也可能,标点自由 |
id |
题 | 56ddde6b9a695914005b9628 式 24 位十六进制串 |
题目唯一标识 | dev 集内 11,873 个 id 互不重复;提交预测时用它做键 |
is_impossible |
题 | true / false |
是否在给定段落中无法回答 | 2.0 起才有,1.1 的文件里没有 |
answers |
题 | 数组 | 参考答案列表 | 不可回答题为空数组 |
answers[].text |
答案 | 字符串 | 答案文本 | 必须与上下文对应位置的子串完全相同 |
answers[].answer_start |
答案 | 整数 | 答案首字符在 context 中的偏移 |
按字符计数,不是按 token |
plausible_answers |
题 | 数组 | 不可回答题的"似是而非"答案 | 只出现在 is_impossible 为真的题上,两个文件都有 |
对全部 dev 题按 answer_start 回切原文得到的片段,与 answers[].text、plausible_answers[].text 逐字符一致,无一处错位。这条核对结果说明偏移是可靠的,可以直接拿来当作模型输出位置的监督信号。
2.3 一条样本的完整解剖
以 dev 集第一篇文章 Normans 的第一道可答题为例:
import json
#-- 官方只发布两个 JSON,读入后是普通 dict
d = json.load(open('dev-v2.0.json'))
print(d['version']) #-- v2.0
print(len(d['data'])) #-- 35 篇文章
art = d['data'][0]
print(art['title']) #-- Normans
print(len(art['paragraphs'])) #-- 39 个段落
para = art['paragraphs'][0]
ctx = para['context']
q = para['qas'][0]
print(q['question']) #-- In what country is Normandy located?
print(q['id']) #-- 56ddde6b9a695914005b9628
print(q['is_impossible']) #-- False
print(q['answers']) #-- 三份参考答案,text 均为 France,answer_start 均为 159
a = q['answers'][0]
#-- 用字符偏移回切原文,应得到完全一致的子串
print(repr(ctx[a['answer_start']:a['answer_start'] + len(a['text'])]))
这段里藏着两个容易被忽略的结构事实。第一,answers 是数组而不是单个对象——dev 集里同一道题会列多份参考答案,示例中三份都写成 France,起止偏移也相同。训练时取哪一份、评测时怎么比,是两个不同的决策,不能默认"第一个是对的、其余是冗余"。第二,answer_start 是字符偏移而不是 token 序号。一旦把上下文交给分词器切成子词,偏移量就必须重算,否则监督位置整体错位——这是英文分词器环境下最常见的第一个 bug,而且它不会报错,只会让分数悄悄变低。
同一篇文章里还能找到一道不可回答题:
| 字段 | 取值 |
|---|---|
question |
Who gave their name to Normandy in the 1000’s and 1100’s |
id |
5ad39d53604f3c001a3fe8d1 |
answers |
[](空数组) |
is_impossible |
true |
plausible_answers |
[{"text": "Normans", "answer_start": 4}] |
这道题就是 2.0 的核心设计:问题读起来完全像一道真提问,段落开头也确实写着 Normans,但"谁给这片地方起了名"的答案在给的这一段里并不成立。plausible_answers 给的是那种"看起来对、其实不对"的诱饵答案,评测脚本会专门围着它算模型有没有被勾住。
2.4 三种答案形态
| 形态 | 出现位置 | is_impossible |
answers |
plausible_answers |
模型该做什么 |
|---|---|---|---|---|---|
| 可答且单答案 | train 的可答题(86,821 道全部如此) | false |
恰好一份答案 | 字段不存在 | 输出该片段 |
| 可答且多参考 | dev 的可答题 | false |
多份参考答案 | 字段不存在 | 输出与任一参考答案重叠最高的片段 |
| 不可答 | 两个文件里的敌手题 | true |
空数组 | 均一带该字段 | 弃权,输出空答案 |
train 里形态非常干净:可答题一律只有一份参考答案,不可答题一律没有答案。dev 则相反,可答题的参考答案份数并不固定,示例中的 France 列了三份。这个差别是有意为之的——训练给单一监督,评测给最大宽容,评测方的"答案到此为止可以有多种切法"这件事完全由 dev 承担。
dev 集 11,873 道题里 5,945 道是第三种形态,其余是第二种。这个约一比一的形态结构是 2.0 设计的直接结果:每一道可答题都被配了一道长得像它的不可答题。训练脚本若忽略了第三种形态,等于默认全部可答,模型在该弃权的地方会有近一半的概率猜出一个答案来。
2.5 1.1 与 2.0 的字段差异
| 层 | SQuAD 1.1 | SQuAD 2.0 | 迁移影响 |
|---|---|---|---|
顶层 version |
1.1 |
v2.0 |
读文件时不要硬解析成数字 |
| 题级字段 | 无 is_impossible |
必有 is_impossible |
老代码按"全可答"假设写的要重写 |
| 答案组织 | answers 非空 |
不可答题 answers 为空 |
取 answers[0] 前必须判空 |
不可答题的 plausible_answers |
无 | 两个文件里不可答题都带该字段 | 1.1 时代的评测脚本无法评测 2.0 |
| 评测脚本 | evaluate-v1.1.py |
evaluate-v2.0.py |
两者不可混用 |
| 榜单 | SQuAD1.1 Leaderboard | SQuAD2.0 Leaderboard | 分数不可跨榜比较 |
最后一行值得单独讲:一个模型在 1.1 榜上的 F1 和在 2.0 榜上的 F1 是两件不同的东西。官方论文摘要里给出的直接对照是"1.1 上 86% F1 的强神经系统在 2.0 上只有 66% F1",落差约二十个百分点。写论文时把两个版本的总分混着报,是最容易被挑出来的硬伤——两个版本的人类基线本身就不同,把它们放进同一张表等于默认了两套口径可以互换。
2.6 为什么答案粒度是片段而不是实体或选项
| 粒度 | 谁在用 | 它带来的额外自由度 | SQuAD 为何不选 |
|---|---|---|---|
| 实体 spans(NER 式) | 各类实体识别评测 | 可以出题机器化 | 提前决定了答案的类别,限死了问句能问什么 |
| 选择题选项 | 考试题基准 | 可直接与标准答案比对 | 模型可仅靠排除法,不必定位文本 |
| 自由生成文本 | 生成式问答 | 表达最自由 | 自动评测困难,需人工或弱监督 |
| 原文连续片段 | SQuAD | 起止两个自由度 | 评测全自动,且强制模型真的去找位置 |
起止两个自由度看着不多,恰好落在便于自动评测的位置:它足以让不同模型的表现拉开差距(句末的边界词到底算不算、插入的重大状语从句要不要带),又足以让评测完全自动化(与参考答案比 EM 和词级 F1)。
2.7 两个文件里没有的东西
反过来看"缺什么",往往比看"有什么"更快判断能不能用:
| 缺失项 | 后果 | 怎么补 |
|---|---|---|
| README 与使用说明 | 字段含义只能从结构与论文推断 | 官方页面的 Getting Started 段落是唯一书面说明 |
| 随包的 LICENSE 文件 | 许可要回到网页上找 | 把主页 URL 与许可名称抄进自己的文档 |
| 校验和 | 无法用 md5 判断完整性 | 用 json.load 能否通过代替 |
| 测试集 | 不能自行评测最终成绩 | 走官方提交通道 |
| 众包工作者标识 | 无法按标注者分组做一致性分析 | 无替代方案,官方未公开这部分信息 |
| 采集时间与轮次 | 无法判断同一篇文章是否被多轮提问 | 无替代方案 |
| 逐题的答案类型标签 | 不能按"人名/时间/地点"分层报告 | 需要自己引入外部标注器 |
最后一行值得展开:官方没有给每道题打上"这是问时间的还是问地点的"这类标签。想做按答案类型分层的分析,必须自己挂一个外部的命名实体识别器,而这一层的误差会叠加到你的结论里。论文里如果做了这种分层,务必写明用的是哪个外部工具。
§3 它是谁的数据
3.1 贡献者
| 角色 | 承担的部分 |
|---|---|
| 斯坦福 NLP 研究组 | 任务定义、众包流水线设计、质量控制、榜单维护 |
| 论文作者(2016) | Pranav Rajpurkar、Jian Zhang、Konstantin Lopyrev、Percy Liang |
| 论文作者(2018) | Pranav Rajpurkar、Robin Jia、Percy Liang |
| 众包工作者 | 阅读段落提出十万个问题,标出答案,并额外编写五万余道不可回答题 |
| 维基百科社群 | 原始文本来源,许可链条上游 |
数据所有权的链条是三层:维基文本在最下层(其许可向上兼容到 CC BY-SA 4.0),众包劳动在中间,斯坦福的任务设计与质量控制处于最上层。这三层叠加的结果就是整个数据集最终采用 CC BY-SA 4.0 而不是更宽的 CC BY 或 CC0(§3.4)。
3.2 时间线
| 时间 | 事件 | 出处 |
|---|---|---|
| 2016-06-16 | SQuAD 论文 arXiv 首版提交 | arXiv:1606.05250 v1 |
| 2016-10 | EMNLP 2016 正式收录 | 论文备注栏 |
| 2016 | SQuAD 1.0/1.1 发布,官方站点 stanford-qa.com 上线 | 官方主页 “SQuAD1.0 paper” 链接 |
| 2018-06-11 | 《Know What You Don’t Know》 arXiv 提交 | arXiv:1806.03822 v1 |
| 2018 | SQuAD 2.0 发布,官网迁入 rajpurkar.github.io/SQuAD-explorer | 官方主页与 GitHub 仓库 |
| 2018-10-05 | BERT 登上 1.1 榜单并开始超越人类数字 | 官方 1.1 榜单记录 |
| 2021-06-04 | 2.0 榜单现有最高分记录(IE-Net) | 官方 2.0 榜单记录 |
| 2021-07-24 | 1.1 榜单现有最高分记录({ANNA}) | 官方 1.1 榜单记录 |
| 当前 | 站点仍可访问,榜单不再频繁更新 | 官方主页访问确认时间 2026-10-30 |
3.3 采集场景
流程与常见的"先有题再找答案"相反:先把段落发给众包工作者,让他读完自己提问,然后在自己刚读完的那段文字里标出能一句话回答的部分。这一步保证了三件事——问题出自真实读者的好奇,答案必定落在这一段里,答案的边界也由同一位读者当场决定。三者一起,才让"问句—答案—偏移"成为一个自洽的三元组,而不是三段互不相干的拼接。
2.0 增加了一道反向工序:给众包工作者一个已作答的可答题,要求他改写出一道"读起来同样合理但这一段里答不出来"的新问题。目标写得很直白——要让两个问题在语言表层尽可能像。这就是为什么 EM 落差并非来自"难题变难了",而是来自"不能答的题看起来能答"。
官方页面没有公开众包工作者的资格筛查、培训材料与一致性检验的具体做法,只公开了流程的结果形态。这一条要写进自己论文的局限性里:能确认的是"每一步都由人完成",不能确认的是"人之间的一致性到了什么程度"。想给出标注质量的可信结论,需要自己做一轮小规模复标。
3.4 来源层次与许可的传染
| 层次 | 内容 | 许可含义 |
|---|---|---|
| 上游 | 英文维基百科正文 | 上游许可为 CC BY-SA 体系 |
| 中游 | 众包产生的问题与答案偏移 | 作为演绎作品一并受上游条款约束 |
| 下游 | 两个 JSON 发布物 | 官方明确声明按 CC BY-SA 4.0 分发 |
| 再下游 | 任何人基于它加工的新发布物 | 需署名并沿用相同方式共享 |
实践中这意味着两件事。第一,把它跟进公司内部产品原材料里去并不触发传染(未对外分发演绎作品),但把它重制后再公开(翻译、增补、重组),一般需要同样按 CC BY-SA 4.0 开放。第二,引用时不仅要引两篇论文,还要把许可名称与来源 URL 写清楚——这是 CC BY-SA 的署名要件。
§4 它最独特的东西
4.1 稀缺性:三件事同时成立
抽取式任务不稀缺,人工提问不稀缺,十万级规模放在今天也不稀缺。稀缺的是三者同时成立,并且在不同版本中给出了前后一致的对照:
| 条件 | 单独看是否常见 | 三者同时达到十万级的资源 |
|---|---|---|
| 答案是原文片段 | 常见(NER、语义角色、各类跨度任务) | 少 |
| 问题由人自主提出 | 少见(多数是自动或半自动) | 少 |
| 十万个以上 | 常见(自动生成类可以无限放大) | 少 |
| 另有五万道敌手不可答题 | 罕见 | 本文库范围内未见同量级对照 |
4.2 差异化证据:那条二十个百分点的落差
官方论文摘要给的是一个极具体的事实陈述:“一个在 SQuAD 1.1 上做到 86% F1 的强神经系统,在 SQuAD 2.0 上只有 66% F1。” 两个数字在同一句话里并列,是官方对这个落差最直接的表达。它的含义值得拆开:
| 对比 | 1.1 上的 86% | 2.0 上的 66% |
|---|---|---|
| 文章与段落 | 同批维基文章 | 同批维基文章 |
| 评测脚本 | 词级 F1 | 词级 F1 |
| 模型 | 同一个 | 同一个 |
| 多出来的要求 | 无 | 必须先判断能不能答 |
落差全部来自新要求,而不是来自更难的语言现象。这就是为什么它在讨论"模型会不会该弃权时不弃权"时被反复引用:它提供了一个把"识别可否回答"单独剥离出来的差分测量。
4.3 一个具体案例
把 Normans 那道不可答题和一个普通可答题并排放:
| 项 | 可答题 | 不可答题 |
|---|---|---|
| 问题 | In what country is Normandy located? | Who gave their name to Normandy in the 1000’s and 1100’s |
| 问句指向 | 明确指向地点实体 | 明确指向人名 |
| 段落里有没有线索 | 有,且直接写明 France | 有诱饵,段落开头就是 Normans 这个词 |
| 正确答案 | 原文片段 France | 不存在于本段 |
| 诱饵答案 | 无 | plausible answer 为 Normans |
| 模型的失败形式 | 找错位置 | 被诱饵勾住,输出 Normans |
一个只会做字符串匹配的模型在第二道题上输出 Normans 时,它的内部状态和它答对一道真实题时几乎一样。这正是 2.0 想抓住的东西——不是"不会答",而是"不知道自己不会"。也正因为如此,1.1 时代的评测脚本在这里完全失效:它只管预测对不对,不管该不该预测。
4.4 标注粒度:两个整数就是全部监督
模型要学的输出只有两个整数——答案在上下文中的起始字符与结束字符。answer_start 给的是起点,长度由答案文本本身决定。这种监督形式的三个后果值得记下来:
| 后果 | 说明 | 应对 |
|---|---|---|
| 与分词器耦合 | 偏移按字符计,子词切分必须重算 | 用 tokenizer 的 offset mapping 而不是自己算 |
| 边界含糊会稳定丢分 | 限定词带不带影响 EM | 同时报告 EM 与 F1,别只报一个 |
| 无法表达多个不连续答案 | 一段答案只能是一处连续区间 | 需要列表式答案的任务另找资源 |
第三条边界最容易被忽略。SQuAD 的监督形式决定了它只能回答"答案是一段话"的问题,凡是需要列出多个实体、或需要跨段拼合答案的任务,它从标注层就回答不了。
4.5 边界条件:只保留可定位的文本答案
出题时就定下一条筛选规则:答案必须能用一段原文文字直接回答。这条规则直接把几类问题挡在门外——计数类(“文中提到了几种”)、是非类(“这件事有没有发生”)、比较类(“两者哪个更早”)、以及需要结合段落之外的常识才能回答的问题。它换来的是评测完全自动化,代价是任务形状比"人读文章回答问题"要窄。
§5 怎么拿到
5.1 目录结构:根本没有目录
官方没有做目录树。所谓"下载"就是取两个文件:
SQuAD-explorer/
└── dataset/
├── train-v2.0.json #-- 训练集,官方标注 40 MB
└── dev-v2.0.json #-- 开发集,官方标注 4 MB
没有 README、没有 LICENSE 文件、没有校验和。许可写在官网页面的下载段落里(“distributed under the CC BY-SA 4.0 license”),使用时要把这句话连同 URL 一起抄进自己的文档。
5.2 批量下载
#-- 官方下载按钮直接指向这两个路径
curl -O https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json
curl -O https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json
#-- dev 文件完整为 4,370,528 字节,train 为 42,123,633 字节
python3.11 -c "import json;json.load(open('dev-v2.0.json'));print('ok')"
wc -c dev-v2.0.json train-v2.0.json
第二条命令是最好的完整性检查之一。因为官方不提供校验和,只有文件被彻底取回(4,370,528 字节)时 json.load 才会通过;网络一旦中断,字节数对不上,解析立刻抛异常。想在团队协作里省事,可以把这一步的通过与否写进测试数据里,而不是靠人记得住。
官方页面上的 Evaluation Script v2.0 按钮指向 worksheets.codalab.org 上的外部文件,需要额外一次跳转;脚本本体不放在 dataset 目录里,也不随两个 JSON 一起发布。官方给出的命令显示它只接收开发集与预测文件两个入参,因此在自己的环境里留存一份脚本副本,比每次临时去下载更稳妥。
5.3 流式读取:按段落去重
import json
def iter_qas(path):
#-- 上下文按段落共享,因此上下文缓存要以段落为单位去重
with open(path, encoding='utf-8') as f:
d = json.load(f)
for art in d['data']:
title = art['title']
for para in art['paragraphs']:
ctx = para['context']
for q in para['qas']:
yield {
'title': title,
'context': ctx,
'id': q['id'],
'question': q['question'],
'is_impossible': q.get('is_impossible', False),
'answers': q['answers'],
'plausible_answers': q.get('plausible_answers', []),
}
rows = list(iter_qas('dev-v2.0.json'))
print(len(rows)) #-- 11873
print(sum(1 for r in rows if r['is_impossible'])) #-- 5945
生成器写法的好处是上下文对象在同一段落的多道题之间只存在一份,处理全量 train 时内存压力明显更小。
5.4 转成扁平表
import json
import pandas as pd
def to_frame(path):
d = json.load(open(path, encoding='utf-8'))
rows = []
for art in d['data']:
for para in art['paragraphs']:
ctx = para['context']
for q in para['qas']:
ans = q['answers']
rows.append({
'title': art['title'],
'id': q['id'],
'question': q['question'],
'context': ctx,
'is_impossible': q['is_impossible'],
'answer': ans[0]['text'] if ans else '',
'start': ans[0]['answer_start'] if ans else -1,
})
return pd.DataFrame(rows)
dev = to_frame('dev-v2.0.json')
print(dev.shape) #-- (11873, 7)
print(dev.head(2))
注意 ans[0] 的取法:这是"训练时取第一份参考"的常用做法,但严格来说 dev 集的多份参考答案应并行保留用于评测。把 dev 也压成单答案列,会在评测环节丢掉官方脚本原本支持的那份信息。
5.5 评测:脚本、预测文件与隐藏测试集
官方页面给出的评测命令只有一行,两个参数分别是开发集与自己的预测文件:
#-- 第一个参数是开发集,第二个是模型预测文件
python evaluate-v2.0.py dev-v2.0.json predictions.json
预测文件是一个以题目 id 为键、以答案字符串为值的扁平 JSON:
import json
preds = {
'56ddde6b9a695914005b9628': 'France', #-- 可答题给答案
'5ad39d53604f3c001a3fe8d1': '', #-- 不可答题给空串,即弃权
}
json.dump(preds, open('predictions.json', 'w'))
空字符串代表弃权。这一点是 2.0 评测的核心:不可答题必须输出空串,输出任何非空文本都会被判错。
关于隐藏测试集,官方页面的措辞很清楚——“To preserve the integrity of test results, we do not release the test set to the public”,成绩必须在 dev 上调好后按官方提交教程提交,由官方代为运行。因此:
| 阶段 | 用什么 | 能不能写成论文里的表 |
|---|---|---|
| 调参与中期验证 | dev 集 + evaluate-v2.0.py |
能,但必须写明是 dev |
| 最终成绩 | 提交后由官方跑 hidden test | 能,须注明"提交获得" |
| 直接拿 dev 当 test 报 | 不推荐 | 不该,口径与榜单不一致 |
5.6 五个坑
| 坑 | 现象 | 错在哪 | 怎么做 |
|---|---|---|---|
| 偏移当 token 用 | 监督位置整体错位 | answer_start 按字符计 |
用 tokenizer 返回的 offset mapping 换算 |
| 默认答案必存在 | 取 answers[0] 抛异常 |
2.0 里一半左右的 dev 题答案为空数组 | 先判空,训练时保留空答案类 |
| 只看总分 | 弃权能力被掩盖 | 可答与不可答两堆混在一起平均 | 分别报告 HasAns 与 NoAns 上的成绩 |
| 只报 F1 | 边界含糊没有被暴露 | EM 与 F1 看的东西不同 | 两个榜单也双列,论文里跟着双列 |
| 用 1.1 脚本跑 2.0 | 分数偏高且不可比 | 两版评测口径不同 | 版本与脚本严格配对 |
第五个坑之外还有一条隐性陷阱:把 1.1 榜上的数字和 2.0 榜上的数字放在同一张表里做比较,会被直接挑出来。这两个榜单上的人类表现基线都不同(1.1 为 EM 82.304 / F1 91.221,2.0 为 EM 86.831 / F1 89.452),本身就说明它们不可互换。
§6 与库内条目的关系
6.1 关系图谱
SQuAD 在本库的位置是"通用域抽取式"的那一极。它左边是更早的完形构造,右边是医学领域的抽取式问答,再往右是纯生成式或多选式的医学问答基准。
| 层级 | 定位 | 代表资源 |
|---|---|---|
| 通用域抽取式 | 给定上下文以片段作答 | 本词条 SQuAD |
| 医学域抽取式 | 给定病历或文献以片段作答 | emrqa、clicr、radqa |
| 医学文献推理 | 长文本结论判断 | pubmedqa、bioasq |
| 医学考试多选 | 选项式压力测试 | medqa、headqa |
| 消费者健康问答 | 真实提问自由文本答复 | medquad、healthsearchqa、cmedqa2 |
| 多跳 / 跨文档 | 需要串联多个来源 | medhop |
6.2 检索路径
如果你是从"我要一个能用的问答数据集"开始检索的,本库的路径建议是这样走:先确定答案形态是"片段"还是"自由文本",再确定领域是通用还是医学,最后确定是否需要多跳。
| 你的第一步选择 | 落点 |
|---|---|
| 通用 + 片段 + 单段 + 十万级 | SQuAD(本词条) |
| 医学 + 片段 + 病历 | emrqa / clicr / radqa |
| 医学 + 结论判断 + 文献摘要 | pubmedqa / bioasq |
| 医学 + 四选一 + 考试难度 | medqa / headqa |
| 医学 + 真实患者问法 | medquad / healthsearchqa / cmedqa2 |
| 需要跨文档串位 | medhop |
6.3 分工判据
| 判据 | SQuAD | 站内医学问答类资源 |
|---|---|---|
| 语言 | 英文通用维基 | 以英文与中文为主,视具体资源而定 |
| 答案形态 | 原文片段 | 片段、多选、自由文本各有分布 |
| 上下文依赖 | 每题必配一段上下文 | 部分资源允许无上下文检索式问答 |
| 是否评测弃权 | 是,2.0 有一整个评测分支 | 视具体资源,多数不专门设计 |
| 规模量级 | 十万级 | 从数百到数百万不等,如 huatuo-26m 为千万级对话语料 |
| 能不能直接上线到医疗场景 | 不能 | 多数亦不能直接上线,需另做临床校验 |
| 适合扮演的角色 | 通用域能力对照与体检 | 领域训练与领域评测 |
需要提醒的是,把 SQuAD 上的高分当成"医学问答也能做好"的间接证据是不成立的。差距不在模型而在领域:医学问句包含大量缩写、否定与隐含的时序假设,这些在百科文本里基本不出现。用 huatuo-26m 一类大规模医学对话语料补输入侧,再用 emrqa 一类抽取式资源测试输出形态,是比直接用 SQuAD 更合理的组合。
§7 质量评估与局限性
7.0 前置校正:先说清楚"质量"指什么
评价一份基准数据,不能只看能跑到什么分。对 SQuAD 而言,质量至少有三个面:标注层是否干净(答案是否真的落在给的段落里、偏移是否自洽)、任务假设是否稳定(题目是否暗示了可回答性)、评测本身是否可重复(脚本公开、基线明确、test 隐藏)。前两面已经在前文用文件清点核对过,第三面取决于提交制度,也取决于官方愿不愿意继续维护榜单。
7.1 五维评价
| 维度 | 评价 | 依据 |
|---|---|---|
| 规模 | 充足,通用抽取式问答范畴内很少对手 | 官方口径十万余问答对、五百余篇文章 |
| 结构清晰度 | 高,两层嵌套、字段少、无冗余文件 | version/data/title/paragraphs/context/qas 六层可穷举 |
| 标注一致性 | 较高,偏移回切逐字符一致 | dev 集全部题目回切核对无错位 |
| 许可友好度 | 中等,可商用但要署名且具传染性 | 官方标注 CC BY-SA 4.0 |
| 可复现性 | 强,评测脚本公开、人类基线明确 | 官方提供 evaluate-v2.0.py 与样例预测文件 |
7.2 标注的两层:问题层与答案层
两层由不同的工序产生,质量风险也不同:
| 层 | 谁产生 | 主要风险 | 证据与缓解 |
|---|---|---|---|
| 问题层 | 众包读完段落自主提出 | 提问可能重复、可能过于表面 | 官方没有公开去重规则,使用时按段落去重是保守做法 |
| 答案层 | 众包在同一段落标出片段 | 边界不唯一(限定词带不带) | 官方用多份参考答案 + 词级 F1 吸收这类差异 |
| 不可答层 | 众包按可答题反向改写 | 诱饵答案可能被人工校对者误判成可答 | dev 的 plausible_answers 字段就是为此而设 |
答案层的多参考设计是官方对"边界不唯一"的正面承认。它没有强行规定唯一标准答案,而是让模型与任意一份参考答案比对取最高分。写自己的评测脚本时如果丢掉这个机制,分数会系统性偏低——同一个模型、同一套预测,用单版本参考答案重算出来的 F1 会硬生生矮一截。
7.3 可枚举的偏差
| 偏差来源 | 机制 | 影响 |
|---|---|---|
| 单语言 | 仅英文 | 结论不能直接迁移到其他语言 |
| 单一语体 | 维基百科的百科文体,句子完整、指代清晰 | 面对口语、病历、法律条文时的表现需另行验证 |
| 单段锚定 | 答案永远在同一段内 | 无法反映开放域检索 + 阅读的完整链路 |
| 可答性先验 | 1.1 假设全可答,2.0 才打破 | 用 1.1 训出的模型天然倾向"必答" |
| 时间截面 | 语料为发布时的维基快照 | 事实随时间变化,旧的"正确答案"今天未必成立 |
| 提问者群体偏差 | 问题由众包提出而非真实用户 | 与真实搜索或临床提问的分布不一致 |
最后一条在用于医学场景时尤其要紧:真实临床提问往往含糊、带情绪、缺主语,而 SQuAD 的问句语法完整、指代明确。用 SQuAD 估算出来的模型能力,在真实问诊入口上会系统性偏高。
7.4 外部验证:榜单是一条看得见的曲线
官方两个榜单把人类表现与机器表现同列,这本身就是一种少见的可解释性:
| 榜单 | 人类 EM / F1 | 榜首 EM / F1 | 榜首记录日期 |
|---|---|---|---|
| SQuAD 1.1 | 82.304 / 91.221 | 90.622 / 95.719({ANNA},单模型,LG AI Research) | 2021-07-24 |
| SQuAD 2.0 | 86.831 / 89.452 | 90.939 / 93.214(IE-Net,集成,RICOH_SRCB_DML) | 2021-06-04 |
两个榜单都呈现出"机器先越过人类、且 F1 的超越幅度大于 EM"的格局,而榜前列多为 ensemble 标注的集成模型。集成串起来的修正在本任务上尤其明显,因为 EM 是个对边界极其敏感的量:单个模型常常只是在边界词上差一两个字,投票之后反而能把边界平均到与多数参考答案一致的切法。
7.5 为什么它在 2026 年仍被反复引用
三个理由互相独立,缺一不可:任务形状足够窄以至于可以干净地解释分数;评测完全自动化以至于任何人都能跑;版本更迭(1.1 → 2.0)提供了一个天然的前后对照,让"弃权"这种本来很难量化的能力被单独测了出来。第四条理由是历史性的:它定义了整整一代人在"抽取式问答"这个词下面所指的东西,后来的资源多数都要和它对表。
§8 生态位与历史
8.1 沿革
| 阶段 | 特征 | 局限 |
|---|---|---|
| 完形填空式 | 自动生成、可无限放大、全自动评测 | 问句不承担语义,模型不必理解就能得分 |
| 多选式 | 真实问句、批改可机械化 | 答案空间压缩,可被排除法绕过 |
| SQuAD 1.1(2016) | 人工提问 + 原文片段 + 十万级规模 | 假设全部可答,模型养成"必答"习惯 |
| SQuAD 2.0(2018) | 增加不可答题与弃权评测 | 仍是单语言单领域、仍依赖给定上下文 |
| 此后 | 各类多跳、开放域、长上下文基准 | 各自解决一部分,没有一个同时具备上述三件套 |
8.2 与挑战赛生态的关系
SQuAD 本身不是挑战赛,但它扮演了同样甚至更强的角色:公开 dev、隐藏 test、官方评测脚本、持续更新的榜单,这套组合事实上就是挑战赛的标准配置,只是没有奖金与截止日期。它的稳定运行也依赖一个制度设计——不发布测试集。这既是它分数可信的原因,也是使用者必须提交才能得到官方成绩的原因。
| 环节 | 挑战赛通常怎么做 | SQuAD 怎么做 |
|---|---|---|
| 数据发布 | 训练与开发公开 | 训练与开发公开(两个 JSON) |
| 最终评分 | 组织方在隐藏集上跑 | 组织方在隐藏集上跑 |
| 时间窗 | 有报名与截止 | 长期开放,随时可提 |
| 排行 | 每届一次 | 同一张榜单持续叠加记录 |
| 激励 | 奖金与名次 | 无可报的激励,靠社区惯例 |
这张表的意思是:用它的时候不必纠结"要不要报名",但也不能享受挑战赛那套统一的数据 Split 与评测环境。同一份榜单上的两个系统,训练语料、算力、 trick 都可能完全不同,横向比较时要留意这一点。
8.3 生态位
| 它占据的位置 | 被什么限定 | 谁能替代它 |
|---|---|---|
| 通用抽取式问答的默认跑道 | 单语言、单任务、答案必为片段 | 需要同等解释力的复合基准时会被替代 |
| 预训练模型能力体检项目 | 任务窄,体检结果不等于上线能力 | 各类多任务套件作为补充而非替代 |
| 弃权能力的差分测量工具 | 仅 2.0 提供不可答设计,且仅英文 | 目前没有同量级的通用对照 |
| 教学示范用的最简问答语料 | 只有两个 JSON,结构可穷举 | 教学场景下很难找到更干净的替代品 |
8.4 谁在用
| 使用者类型 | 用它做什么 | 关心哪个数字 |
|---|---|---|
| 机器阅读理解研究者 | 训练跨度预测模型并投稿对比 | dev 上的 EM/F1 与提交后的 test 成绩 |
| 预训练语言模型团队 | 把它作为微调的标准下游任务 | 与人类表现的差值 |
| 做检索 + 阅读两段式系统的工程师 | 只取其中的阅读器模块评测 | 单步阅读阶段的定位准确率 |
| 教学与入门学习 | 用它讲解起止预测与 EM/F1 算法 | 结构本身是否易于解释 |
| 需要处理"不知道就说不知道"的产品方向 | 用 2.0 的不可答分支 | 可答与不可答两组分开的成绩 |
§9 使用指引
9.1 三种角色的最短路径
| 你是谁 | 第一步 | 第二步 | 第三步 |
|---|---|---|---|
| 研究者 | 下两个 JSON,跑通 evaluate-v2.0.py |
在 dev 上调参,分别看 HasAns / NoAns | 按官方教程提交拿 test 成绩 |
| 工程师 | 只用 2.0,把空答案当第一类公民 | 在数据层把上下文按段落去重 | 上线前换成自己领域的语料重测 |
| 学生 / 入门 | 读 dev 的第一篇文章 Normans |
手写一个起止指针网络并在 dev 上跑通 | 用 EM 和 F1 各算一遍,体会两者差异 |
9.2 最短流程
| 步骤 | 操作 | 校验点 |
|---|---|---|
| 1 | curl -O 取 dev 文件 |
json.load 通过 |
| 2 | 清点文章 / 段 / 题数 | 35 / 1,204 / 11,873 |
| 3 | 按 answer_start 回切原文 |
与答案文本逐字符一致 |
| 4 | 构造 id → 答案 的预测文件 |
不可答题对应空串 |
| 5 | 跑 evaluate-v2.0.py |
输出里同时出现 EM 与 F1 |
9.3 引用方式
两篇论文分别对应两个版本,引用时不能混用:
@inproceedings{rajpurkar2016squad,
title = {SQuAD: 100,000+ Questions for Machine Comprehension of Text},
author = {Rajpurkar, Pranav and Zhang, Jian and Lopyrev, Konstantin and Liang, Percy},
booktitle = {Proceedings of the 2016 Conference on Empirical Methods in Natural Language Processing},
year = {2016},
eprint = {1606.05250},
archivePrefix = {arXiv}
}
@inproceedings{rajpurkar2018know,
title = {Know What You Don't Know: Unanswerable Questions for {SQuAD}},
author = {Rajpurkar, Pranav and Jia, Robin and Liang, Percy},
booktitle = {Proceedings of the 54th Annual Meeting of the Association for Computational Linguistics},
year = {2018},
eprint = {1806.03822},
archivePrefix = {arXiv}
}
除论文之外,发布物的许可条款要求同时标注来源 URL 与许可名称。完整的三件套写法是:引用对应版本的论文、写明 https://rajpurkar.github.io/SQuAD-explorer/ 、注明 CC BY-SA 4.0。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑把关结构与事实 |
| 数字来源 | 规模、结构、边界三类数字来自官方站点 SQuAD-explorer 页面与其标注的文件体积、两篇论文摘要、官方两个榜单 |
| 文件核验 | dev-v2.0.json 下载后经脚本清点文章数、段落数、题数、不可答题数,并按 answer_start 逐条回切核对偏移一致性 |
| 不一致说明 | 官方称 2.0 有"五万余道"不可回答题,而公开的两个文件里可点清的为 train 43,498 加 dev 5,945;差额来自不公开的测试集,本文一律标明口径 |
| 论文信息 | 仅核对 arXiv 摘要页与官方主页引用,未读全文 |
| 未核验内容 | 每题参考答案的具体份数、文章主题构成、众包工作者的规模与报酬机制、隐藏测试集的规模 |
| 图像 | 无配图;封面为生成式提示词,不含真实数据截图 |
| 免责 | 本文不构成任何产品选型与临床建议;数据使用须遵守 CC BY-SA 4.0 的署名与相同方式共享要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它是医学 / 临床问答数据集」 | 通用英文维基百科语料,与医学无关 | 官方页面写明 questions posed by crowdworkers on Wikipedia articles |
| 「答案是人工改写的摘要」 | 答案是原文中的连续片段,由字符偏移定位 | answers[].answer_start 回切与 context 完全吻合 |
| 「2.0 只是 1.1 的增量,老代码能直接跑」 | 多了 is_impossible 与 plausible_answers,评测脚本不同 |
1.1 上 86% F1 的系统在 2.0 只有 66% F1 |
| 「dev 就是测试集」 | test 隐藏,须提交由官方运行 | 官方页面明确不发布测试集 |
| 「只有两个文件所以很小」 | 训练文件官方标注 40 MB,含十万余题 | 官方下载按钮标注 |
| 「CC BY-SA 4.0 等同公有领域」 | 需署名且再分发时要沿用相同方式共享 | 官方下载段落的许可声明 |
| 「看 F1 就够了」 | EM 惩罚边界差错,F1 允许词级重叠,两个榜单都双列 | 官方榜单 EM 与 F1 两列并列 |
| 「超过人类就是会读了」 | 榜单只证明单任务上的跨度定位强 | 1.1 榜首 EM 90.622 / F1 95.719,人类 82.304 / 91.221 |
| 「每题只有一份标准答案」 | dev 集可答题的 answers 是数组,示例题含三份相同参考答案 |
dev-v2.0.json 第一篇第一题 |
| 「机翻成中文就能当中文基准」 | 官方发布物只有英文;许可仅管辖原文发布物 | 官方仅提供 train-v2.0.json 与 dev-v2.0.json |
「plausible_answers 只在 dev 集里」 |
train 集里 43,498 道不可答题同样带该字段 | train-v2.0.json 清点 |
| 「官方说五万余道不可答题,就等于 43,498」 | 43,498 只是训练集一笔;官方口径含隐藏测试集 | train 43,498 + dev 5,945,官方称 over 50,000 |
FAQ
Q1:SQuAD 1.1 和 2.0 该选哪个?
除非你明确在复现 2016 到 2018 年间的工作,否则一律用 2.0。它包含了 1.1 的全部题目,只多不少,并且多出来的一半不可答题正是现在做抽取式问答必须处理的能力。唯一的例外是:你要和某篇只报告了 1.1 分数的老论文做严格对比,这时必须把两个版本分开跑,不能拿 2.0 的数字去替代。
Q2:为什么官方不把测试集放出来?我的论文只报 dev 分数行不行?
官方页面给的理由是保护测试结果的完整性,成绩必须由官方代跑。只报 dev 分数的做法是常见的,但它与榜单口径之间存在一段无法消除的距离:dev 公开、可以被反复调试,而榜单数字来自从未公开的那一份。稳妥做法是 dev 用来做消融与选型,最终成绩走提交,论文里把两套数字分开标注清楚。
Q3:EM 和 F1 到底差在哪?
EM(精确匹配)要求预测串与某一参考答案逐字符相同,差一个冠词就是零分;F1 在词一级算重叠,预测多带或少带一个词只扣一部分分。前者尖锐反映边界习惯,后者反映大致找对了没有。官方榜单双列给出是有道理的:只看 EM 会低估"答对位置但边界略差"的系统,只看 F1 又会掩盖边界不稳的问题。
Q4:CC BY-SA 4.0 能不能商用,能不能翻译后再发布?
商业使用本身不禁止,这意味着把它作为训练语料构建商业模型是允许的。真正要谨慎的是二次发布:CC BY-SA 的"相同方式共享"要求在向外界分发基于它的演绎作品时沿用同一许可,并保留署名。翻译、增补、重组并公开都需要按此处理;仅在组织内部使用、不对外分发演绎作品,通常不触发该条款,具体仍需按许可全文判断。
Q5:它是抽取式的,那我能不能用它训练生成式问答?
可以做中间步骤,但不能直接当作目标形态。它的监督信号是"起止两个整数",用久了会让模型习惯性地从原文摘一句话作答,这在需要归纳、比较或解释的场景里明显不够。更合理的用法是:把它当作编码器—阅读器那一段的能力对照,另外配生成侧的语料(站内 medquad、healthsearchqa 一类自由答复资源)来训练输出形态。
Q6:站内在架的医学抽取式资源里,哪个最接近它?
最接近其任务形状的是 emrqa 与 clicr 那一类:给定一段医学文本,以片段作答。差异在两端——语言社团与文本体裁不同,以及医学文本大量依赖缩写与时态隐含。SQuAD 在这两者之间扮演的是"通用对照"的角色,而不是"领域替代"。
Q7:我只模仿它的 JSON 结构、不用它的数据,还要遵守 CC BY-SA 4.0 吗?
两种情况要分开说。只包含问句、answers 与 context 原文的分发物属于演绎作品,官方对两个 JSON 已明确声明按 CC BY-SA 4.0 分发,那么二次公开就要署名并沿用相同方式共享。而任务的形状与字段命名通常不被当作受版权保护的内容,模仿 schema 建自己的数据一般不受该许可约束;具体判断仍要按自己所在地的法律与执业意见来。保守做法是:用了原始发布物就照许可办,只学了结构就在文档里写清结构出处。
术语表
| 术语 | 解释 |
|---|---|
| SQuAD | Stanford Question Answering Dataset,斯坦福发布的维基百科抽取式阅读理解数据集 |
| 阅读理解 / 机器阅读理解 | 给文本与问题,要求机器产出答案的任务家族 |
| 抽取式答案 / span | 答案直接取自原文的一段连续文本,而非另行生成 |
| EM / 精确匹配 | Exact Match,预测答案与参考答案逐字符相同才得分 |
| 词级 F1 | 按词的重叠计算准确率与召回率的调和平均,允许部分正确 |
| 弃权 / abstention | 无法回答时不给答案,而非猜一个 |
| 不可回答题 | 段落中不含有答案的问题,2.0 由众包刻意构造 |
| 对抗样本(本题语境) | 与可答题表面相似但无答案的问题 |
| plausible answer | 不可答题的"似是而非"答案,用于诱捕模型是否会被勾住 |
| answer_start | 答案首字符在上下文中的偏移,按字符计数 |
| 字符偏移 | 以 Unicode 字符为单位的起至位置,与分词后的 token 序号不同 |
| 跨度指针网络 | 输出起止位置而非固定标签的答案预测结构 |
| 众包 | 由大量在线工作者分工完成标注任务 |
| 多份参考答案 | 同一道题保留多份人工答案,评测时取最优 |
| dev / hidden test | 公开的开发集与不公开的测试集 |
| CC BY-SA 4.0 | 署名—相同方式共享 4.0 国际许可,具传染性 |
| Wikipedia / 维基百科 | 自由内容的在线百科,本数据集的文本来源 |
| 集成模型 | 多个模型结果合并后的系统,榜单上多以 ensemble 标注 |
| hasAns / noAns | 评测脚本区分可答题与不可答题的两个分支 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 1.1 问答对 | 100,000+ | 官方主页描述段 | 官方页面 |
| 1.1 文章数 | 500+ | 官方主页描述段 | 官方页面 |
| 2.0 不可答题(官方口径) | over 50,000 | 官方主页描述段 | 官方页面 |
| train 字节数 | 42,123,633 | 下载后 wc -c |
官方文件 |
| dev 字节数 | 4,370,528 | 下载后 wc -c |
官方文件 |
| train 文章数 | 442 | train-v2.0.json 清点 | 官方文件 |
| train 段落数 | 19,035 | train-v2.0.json 清点 | 官方文件 |
| train 题数 | 130,319 | train-v2.0.json 清点 | 官方文件 |
| train 不可答题 | 43,498 | train-v2.0.json 清点 | 官方文件 |
train id 唯一性 |
130,319 个互不重复 | train-v2.0.json 清点 | 官方文件 |
| dev 文章数 | 35 | dev-v2.0.json 清点 | 官方文件 |
| dev 段落数 | 1,204 | dev-v2.0.json 清点 | 官方文件 |
| dev 题数 | 11,873 | dev-v2.0.json 清点 | 官方文件 |
| dev 不可答题 | 5,945 | dev-v2.0.json 清点 | 官方文件 |
dev id 唯一性 |
11,873 个互不重复 | dev-v2.0.json 清点 | 官方文件 |
| dev 文件体积标注 | 4 MB | 官方下载按钮 | 官方页面 |
| train 文件体积标注 | 40 MB | 官方下载按钮 | 官方页面 |
| 偏移一致性 | 两个文件全部题目回切与答案文本一致 | train/dev 两个 JSON 逐条核对 | 官方文件 |
| 1.1 人类表现 | EM 82.304 / F1 91.221 | 官方 1.1 榜单 | 官方页面 |
| 2.0 人类表现 | EM 86.831 / F1 89.452 | 官方 2.0 榜单 | 官方页面 |
| 1.1 榜首 | EM 90.622 / F1 95.719(2021-07-24) | 官方 1.1 榜单 | 官方页面 |
| 2.0 榜首 | EM 90.939 / F1 93.214(2021-06-04) | 官方 2.0 榜单 | 官方页面 |
| 版本更迭落差 | 1.1 上 86% F1 → 2.0 上 66% F1 | 2.0 论文摘要 | 论文摘要 |
| 首个基线 | 逻辑回归 F1 51.0%,简单基线 20% | 1.0 论文摘要 | 论文摘要 |
| 许可 | CC BY-SA 4.0 | 官方下载段落 | 官方页面 |
| 首次发布 | 2016-06-16(arXiv:1606.05250) | arXiv 摘要页 | 论文摘要 |
| 2.0 发布 | 2018-06-11(arXiv:1806.03822) | arXiv 摘要页 | 论文摘要 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 1.1 的十万余问答对与五百余篇文章、2.0 的"五万余道"不可答题、两个文件的标注体积、CC BY-SA 4.0 许可、两个榜单的全部成绩,都来自 SQuAD-explorer 站点。train 与 dev 的文章数、段落数、题数、不可答题数、id 唯一性、偏移一致性以及两个文件的实际字节数,来自对下载文件的脚本清点。
第二层:论文摘要。 逻辑回归基线的 51.0% F1、简单基线的 20%、以及"1.1 上 86% F1 的系统在 2.0 上只有 66% F1"这条对照,来自两篇论文的 arXiv 摘要页。摘要只能支撑"官方如何陈述",不能支撑超出摘要范围的技术细节。
第三层:未核验。 每题参考答案的具体份数、文章主题构成、众包工作者的规模与报酬机制、隐藏测试集的题目数量。这些需要查阅官方的众包执行说明或提交后才能获知,超出本篇核验范围;正文中凡涉及之处只作定性表述。
一处口径差异需要单独说明。 官方说 2.0 加入了"五万余道"不可回答题,而能实际点清的公开文件只有 train 的 43,498 与 dev 的 5,945 两笔。这不是官方说错,而是因为隐藏测试集同样包含一批不可回答题,而它从未公开。引用时应当写"官方口径五万余道(公开文件中可清点者不足此数)",而不是直接把 43,498 当成总数。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | The Stanford Question Answering Dataset(官方主页) | https://rajpurkar.github.io/SQuAD-explorer/ | 规模、许可、下载、评测、榜单的全部来源 |
| 2 | Training Set v2.0(官方文件) | https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json | 训练数据本体 |
| 3 | Dev Set v2.0(官方文件) | https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json | 结构清点与偏移核对 |
| 4 | SQuAD: 100,000+ Questions for Machine Comprehension of Text | https://arxiv.org/abs/1606.05250 | 1.0/1.1 的提出论文与基线数字 |
| 5 | Know What You Don’t Know: Unanswerable Questions for SQuAD | https://arxiv.org/abs/1806.03822 | 2.0 的提出论文与 86→66 对照 |
| 6 | SQuAD-explorer 仓库(含 Explore 1.1 与 2.0 的在线浏览) | https://github.com/rajpurkar/SQuAD-explorer | dev 集文章标题的在线对照 |
| 7 | 站内 emrqa(医学抽取式问答对照) | https://www.qianfanghub.com/ai-ready-dataset/emrqa/139 | §6.1 与 §6.3 的领域对照 |
| 8 | 站内 clicr(病例报告阅读理解对照) | https://www.qianfanghub.com/ai-ready-dataset/clicr/150 | §6.1 的领域对照 |
附录 D:任务代码
任务一:一次跑通结构清点
import json
#-- 读入官方开发集
d = json.load(open('dev-v2.0.json', encoding='utf-8'))
print('version', d['version'])
arts, paras, qs = 0, 0, 0
#-- id 集合用于检查唯一性
seen = set()
mismatch = 0
for art in d['data']:
arts += 1
for para in art['paragraphs']:
paras += 1
ctx = para['context']
for q in para['qas']:
qs += 1
seen.add(q['id'])
#-- 可答题与似是而非答案都要能回切出原文片段
pool = q['answers'] + q.get('plausible_answers', [])
for a in pool:
seg = ctx[a['answer_start']:a['answer_start'] + len(a['text'])]
if seg != a['text']:
mismatch += 1
print('articles', arts, 'paragraphs', paras, 'questions', qs)
print('unique ids', len(seen))
print('mismatch', mismatch)
任务二:构造预测文件的最小骨架
import json
d = json.load(open('dev-v2.0.json', encoding='utf-8'))
preds = {}
for art in d['data']:
for para in art['paragraphs']:
for q in para['qas']:
ans = q['answers']
#-- 不可答题必须输出空串,这才算弃权
preds[q['id']] = ans[0]['text'] if ans else ''
json.dump(preds, open('predictions.json', 'w'))
print(len(preds))
第二段代码给出的只是最小可跑骨架,它把标准答案原样喂回去,跑出来的分数应该接近满分。它的用途不是得到成绩,而是验证评测脚本、路径与格式都对。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 答案是原文的一段连续文字,靠字符偏移 answer_start 定位 |
这一条决定了任务形状、模型输出形式与所有 bug 的来源 |
| 2 | 2.0 有一半左右的 dev 题不可回答,模型必须会弃权 | 同样的模型从 86% F1 掉到 66% F1,跌的正是这个能力 |
| 3 | test 隐藏,dev 成绩不等于榜单成绩 | 官方为保住分数可信度不公开测试集 |
| 4 | EM 与 F1 必须同报 | 两者惩罚的东西不一样,只报一个会掩盖问题 |
| 5 | CC BY-SA 4.0 具传染性 | 再发布演绎作品要沿用同一许可并署名 |
编辑说明
本文的核验时间为 2026 年 10 月 30 日。核对方式为直接访问官方站点 SQuAD-explorer 主页、两个版本的在线探索页、两篇论文的 arXiv 摘要页,以及完整下载 train-v2.0.json 与 dev-v2.0.json 后用脚本清点。train 的 442 篇文章、19,035 个段落、130,319 道题、43,498 道不可答题,dev 的 35 篇文章、1,204 个段落、11,873 道题、5,945 道不可答题,均为文件清点所得;两个文件的 id 唯一性与答案偏移回切一致性亦经逐条核对,未发现错位。官方"五万余道"不可答题的口径包含不公开的测试集,与可点清的两笔数字存在差额,正文已在 §10 与附录 B 各说明一次。未覆盖的内容包括:每题参考答案的具体份数、文章主题构成、众包工作者的规模与报酬机制、隐藏测试集的题目数量。这些需要查阅官方的众包执行说明或提交后才可得知,本文按要求只写规模、结构、边界三类数字。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- alma-archive — 共享标签:评测基准
- i2b2-n2c2-nlp — 共享标签:评测基准
- cblue — 共享标签:评测基准
- blurb — 共享标签:评测基准
- tus-rec — 共享标签:评测基准
- biosses — 共享标签:评测基准
- tg3k — 共享标签:评测基准
- qmugs — 共享标签:评测基准
- openpros — 共享标签:评测基准
- ai4life-mdc24 — 共享标签:评测基准
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

