- NLP
- 人工智能
- 深度学习
【免费下载链接】ParlAI
A framework for training and evaluating AI models on a variety of openly available dialogue datasets.
导读
本文围绕 ParlAI 框架内对 SQuAD(Stanford Question Answering Dataset)数据集的官方实现展开,系统讲解该任务在仓库中的注册方式、数据下载与校验流程、DefaultTeacher/IndexTeacher/SentenceTeacher等八种教师(Teacher)变体的设计动机与底层实现,并结合仓库中的测试样例与 YAML 快照给出可复现的验证方法。读完本文,你将掌握如何在 ParlAI 中加载 SQuAD、理解每种教师变体输出的消息字段差异,并能为抽取式问答 / 阅读理解实验选择合适的任务入口。
SQuAD 任务在 ParlAI 中的定位
SQuAD(Stanford Question Answering Dataset)是由 Rajpurkar 等人于 2016 年提出的开放域问答数据集:给定一段来自 Wikipedia 的段落(paragraph),模型需要回答针对该段落提出的问题,答案是从段落中抽取的连续文本片段。在 任务 README 中,官方将其描述为:
Open-domain QA dataset answerable from a given paragraph from Wikipedia, from Rajpurkar et al. '16.
该任务在仓库中被标记为#SQuAD、#All、#QA三个标签,并收录在parlai/tasks任务体系内,因此可以通过 ParlAI 统一的任务命令行参数直接加载,无需额外编写数据加载代码。
从仓库结构看,SQuAD 任务由以下文件构成:
- parlai/tasks/squad/agents.py:全部教师变体的核心实现;
- parlai/tasks/squad/build.py:数据下载、校验与构建;
- parlai/tasks/squad/test.py:教师自动测试;
- parlai/tasks/squad/test/:每个教师变体对应的 YAML 数据快照与统计信息。
数据下载与构建流程
SQuAD 任务的数据获取由 build.py 负责,其核心是一个RESOURCES资源列表,包含三个可下载文件:
| 资源 | 用途 | 是否压缩 |
|---|---|---|
train-v1.1.json | SQuAD v1.1 训练集(官方 SQuAD-explorer 发布) | 否 |
dev-v1.1.json | SQuAD v1.1 开发集 | 否 |
squad_fulldocs.tgz | "Fulldoc" 变体所需的整篇文档数据(由 ParlAI 下载服务器托管) | 是 |
构建函数build(opt)的逻辑值得注意:
- 在
opt['datapath']下创建SQuAD目录,先下载前两个 JSON 文件(RESOURCES[:2]),每个文件都带有 SHA-256 校验值,用于保证下载完整性; - 若
opt['task']字符串中包含fulldoc,则额外在SQuAD-fulldoc目录下载并解压squad_fulldocs.tgz; - 通过
build_data.built()/mark_done()机制记录构建状态,避免重复下载。
也就是说,默认的squad任务只依赖约 87K 训练样例的 JSON 文件;只有当你使用squad:fulldoc或squad:fulldocsentence变体时,才会触发整篇文档数据的下载。数据目录由 ParlAI 全局的--datapath参数控制(默认在用户数据目录下)。
快速上手:查看 SQuAD 数据
ParlAI 提供了统一的display_data脚本用于预览任何任务的数据。加载默认 SQuAD 教师:
python -m parlai.scripts.display_data -t squad在parlai/tasks/squad/test/squad_train.yml中可以看到真实的首批样例,默认教师的每条消息形如:
- episode_done: true id: squad labels: - Saint Bernadette Soubirous text: 'Architecturally, the school has a Catholic character. ... To whom did the Virgin Mary allegedly appear in 1858 in Lourdes France?'即text字段为"段落文本 + 换行 + 问题",labels为从段落中抽取的答案字符串。该 YAML 快照同时记录了num_episodes: 87599、num_examples: 87599,即默认 SQuAD 教师将每个"段落 + 问题"视作一个独立 episode,训练集共 87599 个样例。
教师(Teacher)变体全景
agents.py中为 SQuAD 提供了八种教师,分别继承自 ParlAI 核心的FixedDialogTeacher、DialogTeacher、ParlAIDialogTeacher与AbstractWrapperTeacher。任务名与教师类的对应关系如下:
| 任务参数 | 教师类 | 基类 | 文本格式 | 核心特性 |
|---|---|---|---|---|
squad | DefaultTeacher | DialogTeacher | 段落\n问题 | 标准抽取式 QA 格式 |
squad:index | IndexTeacher | FixedDialogTeacher | 段落\n问题 | 附带answer_starts答案起始索引 |
squad:opensquad | OpensquadTeacher | DialogTeacher | 仅问题 | 去掉上下文段落的开放问答 |
squad:title | TitleTeacher | DefaultTeacher | 标题\n段落\n问题 | 额外注入 Wikipedia 文章标题 |
squad:fulldoc | FulldocTeacher | ParlAIDialogTeacher | 整篇文档 + 问题 | 基于整篇文档而非单个段落 |
squad:sentence | SentenceTeacher | IndexTeacher | 段落\n问题或分离字段 | 标签改为包含答案的句子 |
squad:fulldocsentence | FulldocsentenceTeacher | FulldocTeacher | 整篇文档 + 问题 | 句子级标签 + 整篇文档 |
squad:squadqa | SquadQATeacher | AbstractWrapperTeacher | 仅段落 | 只保留段落、去掉问题 |
下面逐一展开每种变体的实现细节。
默认教师:DefaultTeacher
DefaultTeacher继承自核心的DialogTeacher,agents.py 中其实现非常精简:只需实现setup_data(path)迭代器即可自动获得act()、基础指标等能力。其关键逻辑:
def setup_data(self, path): with PathManager.open(path) as data_file: self.squad = json.load(data_file)['data'] for article in self.squad: for paragraph in article['paragraphs']: for qa in paragraph['qas']: question = qa['question'] answers = tuple(a['text'] for a in qa['answers']) context = paragraph['context'] yield (context + '\n' + question, answers), True- 数据结构按 SQuAD 原始 JSON 的三层嵌套遍历:
data → articles → paragraphs → qas; - 每个样例产出
(text, labels)二元组,episode_done恒为True(单轮 QA,无多轮对话); answers使用元组承载,因为 SQuAD 中一个问题通常有多个标注答案。
类注释中明确指出:默认教师"does not efficiently store the paragraphs in memory"(不将段落常驻内存),即采用流式生成方式,以节省内存为优先。数据文件路径通过opt['datafile']指向SQuAD/train-v1.1.json或SQuAD/dev-v1.1.json,取决于datatype是否以train开头。
手写 act() 的范例:IndexTeacher
IndexTeacher继承自FixedDialogTeacher,是仓库注释中明确标注的"手写 SQuAD 教师"范例——它不依赖核心DialogTeacher,而是自行实现act()与数据索引,并额外暴露答案在上下文中的起始位置:
action = { 'id': 'squad', 'text': context + '\n' + question, 'labels': answers, 'episode_done': True, 'answer_starts': answer_starts, }其数据准备在_setup_data()中完成:一次性读取全部 JSON,预先构建(article_idx, paragraph_idx, qa_idx)的三元组索引列表,get(episode_idx)再据此定位具体样例。answer_starts字段直接取自原始 JSON 中每个答案的answer_start字符偏移,为需要答案定位监督信号的模型(例如抽取式 span 预测)提供了便利。此外,num_examples()与num_episodes()均返回样例总数。
开放问答变体:OpensquadTeacher
OpensquadTeacher同样继承DialogTeacher,唯一区别是省略了上下文段落,每条消息只保留问题文本:
yield (question, answers), True对应数据快照 squad_opensquad_train.yml 中可以看到,text字段退化为纯粹的提问(如 "To whom did the Virgin Mary allegedly appear in 1858 in Lourdes France?")。这适合验证"没有段落时模型能否作答"的消融实验,或用于开放式问答场景。
带标题的变体:TitleTeacher
TitleTeacher继承DefaultTeacher,仅修改text的拼接方式,将 Wikipedia 文章标题置于段落之前:
yield ('\n'.join([title, context, question]), answers), True代码注释提醒:标题直接取自原始数据,包含下划线(作为 Wikipedia 链接的一部分),即文章实际位于https://en.wikipedia.org/wiki/{TITLE},使用方可根据需要决定是否去除下划线。该教师将id设为squad_title,便于在日志与指标中区分来源。
整篇文档变体:FulldocTeacher
FulldocTeacher继承自ParlAIDialogTeacher,数据不再来自官方 JSON,而是来自 build.py 中下载的squad_fulldocs.tgz。它通过parlaidialogteacher_datafile指向SQuAD-fulldoc/squad_fulldocs.{train|valid}:ordered文件。从 squad_fulldoc_train.yml 快照可见,其text字段包含以\n\n分隔的整篇文章多个段落,随后是问题——即"文档级"阅读理解:模型必须在跨越多个段落的整篇文档中定位答案,难度显著高于单段落版本。
句子级标签变体:SentenceTeacher 与 FulldocsentenceTeacher
这两个变体将监督信号从"答案片段"升级为"包含答案的句子",是 SQuAD 中最具特色的设计:
SentenceTeacher继承IndexTeacher(基于官方 JSON 的段落级数据);FulldocsentenceTeacher继承FulldocTeacher(基于整篇文档数据)。
两者共享一套处理管线,以SentenceTeacher为例:
- 加载 NLTK 的 punkt 英文句子切分器(
get_sentence_tokenizer(),若本地缺失会自动nltk.download('punkt')); - 为避免切分干扰,先将答案中的
.、?、!去除,并同步替换回上下文; - 对上下文切句后,找出包含任一答案的句子作为
labels,全部句子作为label_candidates; answer_starts记录每个标签句子在上下文中的起始字符位置。
两者均支持--include-context命令行参数(默认False):
agent.add_argument( '--include-context', type='bool', default=False, help='include context within text instead of as a separate field', )- 默认情况下,action 字典包含独立的
context字段,text仅为问题,label_candidates为全部句子,便于做"从候选中选择正确句子"的分类式任务; - 开启后,
context合并进text(context + '\n' + question)并从字典中移除,回归抽取式任务的输入形态。
从 squad_sentence_train.yml 快照可以看到该格式的实际效果:label_candidates列出段落的全部句子,labels只含包含答案的那一句,answer_starts给出句子起点偏移。
段落抽取变体:SquadQATeacher
SquadQATeacher是最后一个变体,继承AbstractWrapperTeacher,通过_edit_action()对默认教师的输出做后处理——将text中换行之前的第一行(即段落)抽取出来,丢弃问题部分:
def _edit_action(self, act: Message) -> Message: passage = act['text'].split('\n')[0] act.force_set('text', passage) return act该变体适用于只关心"段落本身"的任务(例如段落检索、表示学习等),其类注释明确说明"only the passage, and ignore the question"。
消息字段与数据格式总结
综合各变体,SQuAD 教师产出的 action 字典字段可归纳为:
| 字段 | 含义 | 出现于 |
|---|---|---|
id | 任务标识(squad/squad_title/squad-fulldoc) | 全部 |
text | 模型输入文本(段落/标题 + 问题,或仅问题) | 全部 |
labels | 标注答案(字符串列表) | 全部 |
label_candidates | 候选句子列表(句子级变体为全部句子) | sentence/fulldocsentence |
answer_starts | 答案/标签句子在上下文中的起始字符偏移 | index/sentence系列 |
context | 独立上下文字段(默认模式) | sentence系列 |
episode_done | 恒为True,单轮样例 | 全部 |
测试与质量保障
任务自带完整的自动化测试 parlai/tasks/squad/test.py,基于 ParlAI 的AutoTeacherTest工具类,为六种教师(squad、squad:index、squad:opensquad、squad:fulldoc、squad:sentence、squad:fulldocsentence)分别注册测试类。测试会加载parlai/tasks/squad/test/下的 YAML 快照(train/valid/test 三套齐全,如squad_train.yml、squad_index_valid.yml、squad_sentence_test.yml等),校验教师产出的消息格式与快照一致、样例数量正确。这套机制保证了后续任何对agents.py的修改都不会破坏数据格式兼容性,也为你自定义教师时提供了可参照的测试范式。
训练与评估实践
在 ParlAI 中,SQuAD 与其他任务共用同一套训练/评估入口,只需将任务名传给-t参数:
# 训练(以通用 seq2seq 模型为例,具体超参请按实验调整) python -m parlai.scripts.train_model -t squad -m seq2seq -bs 32 -lr 1e-3 --train-predict true # 评估已有模型 python -m parlai.scripts.eval_model -t squad -mf /path/to/model_file # 交互式对话(将问题作为输入,观察模型在给定段落上作答) python -m parlai.scripts.interactive -t squad -mf /path/to/model_file实践要点:
- 选择教师变体即选择任务形态:默认
squad适合标准的抽取式问答;squad:index为需要答案位置监督的模型提供answer_starts;squad:sentence将问题转化为句子选择;squad:fulldoc则面向文档级阅读理解; - 数据划分:
datatype以train开头时加载训练集 JSON,否则加载开发集,测试时同样遵循 ParlAI 的train/valid/test约定; - 依赖提醒:
sentence系列教师依赖 NLTK 的 punkt 分词器,首次运行需要联网下载;fulldoc系列会额外下载整篇文档数据包。
小结
SQuAD 任务是 ParlAI 任务生态中极具代表性的 QA 任务:一方面它演示了如何用DialogTeacher的最小实现接入真实数据集,另一方面通过IndexTeacher展示了不依赖继承、手写act()的教师写法,而SentenceTeacher系列则展示了如何将原始答案重构成句子级监督信号。理解这八种变体的数据流,你就能在阅读理解、开放问答、句子选择等不同实验设定间自由切换,并以此为模板接入自己的 QA 数据。
- NLP
- 人工智能
- 深度学习
【免费下载链接】ParlAI
A framework for training and evaluating AI models on a variety of openly available dialogue datasets.
相关推荐
快速解决Windows内存不足问题:Mem Reduct终极优化指南
快速解决Windows内存不足问题:Mem Reduct终极优化指南 你是否曾经遇到过电脑越用越慢,打开程序要等好几秒,多任务切换卡顿的情况?这很可能是Wind
NLP人工智能深度学习ParlAI 中的 HotpotQA 任务:多跳阅读理解数据集的加载、构建与评测实战指南
ParlAI 中的 HotpotQA 任务:多跳阅读理解数据集的加载、构建与评测实战指南 HotpotQA 是 ParlAI 内置的多跳问答(Multi hop
NLP人工智能深度学习lm-evaluation-harness 中的 squad_completion 任务:基于 SQuAD 变体的零样本阅读理解评测指南
lm evaluation harness 中的 squad_completion 任务:基于 SQuAD 变体的零样本阅读理解评测指南 导读 squad_co
人工智能模型评测AI 评测
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考