EasyNLP带你实现中英文机器阅读理解

作者:施晨、黄俊

导读

机器阅读理解是自然语言处理(NLP),特别是自然语言理解(NLU)领域最重要的研究方向之一。自1977年首次被提出以来,机器阅读理解已有近50年的发展史,历经“人工规则”、“传统机器学习”、“深度学习”、“大规模预训练模型”等多个发展阶段。机器阅读理解旨在帮助人类从大量文本中,快速聚焦相关信息,降低人工信息获取成本,增加信息检索有效性。作为人工智能在自然语言理解方向上的“集大成者”,机器阅读理解任务考察了从 “词” 到 “句” 乃至 “篇章”,每一个语言粒度的理解能力,这使得在人工智能发展的每个阶段,它都是非常困难、也颇为重要的“兵家必争之地”。以SQuAD为代表的阅读理解数据集,见证了深度学习大发展时代里,各大公司刷榜创新方案的你方唱罢我登场,随后又在大规模预训练时代,成为BERT等预训练模型的评测基准。可以说近十年里,机器阅读理解极大促进与见证了自然语言处理领域的繁荣与发展。

形式化来讲,机器阅读理解任务的输入为一段篇章文本(context),与一个问句(question),通过学习模型,输出预测的答案文本(answer)。根据获取答案方式的不同,当前业界主流将阅读理解任务分为四大类:完型填空式(Cloze tests)、多项选择式(Multi-choice)、片段抽取式(Span extraction)及自由生成式(Free answering)。其中片段抽取式根据问句(question),直接从篇章文本(context)中预测答案文本(answer)的起止位置(start/end positions),从而抽取出答案。由于其与真实场景接近,难度适中,易于评测,且有SQuAD等高质量数据集支撑,因此成为当前的主流阅读理解任务。随着预训练语言模型的发展,近年来片段抽取式阅读理解的效果屡创新高。在英文场景下,传统的BERT、RoBERTa、ALBERT等模型都能取得超越人类的效果;而在中文场景下,MacBERT等模型(Pre-Training with Whole Word Masking for Chinese BERT)通过引入一种纠错型掩码语言模型(Mac)预训练任务,缓解了“预训练-下游任务”不一致的问题,也更好地适配了中文场景,在包括机器阅读理解在内的多种NLP任务上取得了显著的性能提升。因此,我们在EasyNLP框架中集成了MacBERT算法和模型,配合EasyNLP中原有的BERT、RoBERTa等模型,使用户能够方便地使用这些模型进行中英文机器阅读理解任务的训练和预测。

EasyNLP(​​https://github.com/alibaba/EasyNLP​​)是阿⾥云机器学习PAI 团队基于 PyTorch 开发的易⽤且丰富的中⽂NLP算法框架,⽀持常⽤的中⽂预训练模型和⼤模型落地技术,并且提供了从训练到部署的⼀站式 NLP 开发体验。EasyNLP 提供了简洁的接⼝供⽤户开发 NLP 模型,包括NLP应⽤ AppZoo 和预训练 ModelZoo,同时提供技术帮助⽤户⾼效的落地超⼤预训练模型到业务。机器阅读理解作为自然语言理解的集大成者,同时也是文本问答、信息抽取等领域的基础任务,具有较高的研究价值。因此,EasyNLP增加了对中英文机器阅读理解任务的支持,希望能服务更多的NLP/NLU算法开发者和研究者,也希望和社区一起推动NLU相关技术的发展和落地。

本⽂将提供对MacBERT模型的技术解读,以及如何在EasyNLP框架中使⽤MacBERT及其他预训练语言模型,进行中英文机器阅读理解任务的训练与预测。

MacBERT模型解读

主流的大规模预训练语言模型(如BERT、RoBERTa等)主要针对英语语言设计,将其直接迁移到中文场景时,会面临中英文语言本身的差异,如:中文词间无空格、无需切分子词、多个单字组成具有完整意义的词语等。例如下图中原始语句“使用语言模型来预测下一个词的概率”,按单字切分后,某些单字由于会组成完整的词语(如:语言模型、预测、概率),此时若只mask掉其中一个字,会影响掩码与语言模型预训练的效果。此外,传统语言模型在预训练时会采用 [MASK] 字符进行mask,而在下游任务文本中却并不存在 [MASK] 标记,这在两阶段中天然引入了gap。为缓解上述问题,MacBERT等模型修改传统MLM任务,引入了一种纠错型掩码语言模型(Mac)预训练任务,包括wwm (whole word masking)、NM(n-gram masking)、相似词替换等mask方案,更好地适配了中文的语言场景,减少了“预训练-下游任务”不一致的问题,提升了预训练模型在多种NLP任务上的效果。另外,由于MacBERT的主要框架与BERT完全一致,可在不修改现有代码的基础上进行无缝过渡,这为开发者的代码迁移带来了很大的便利。

EasyNLP带你实现中英文机器阅读理解

具体来讲,MacBERT等模型在MLM时,对中文整词中所有单字同时进行mask,并采用n-gram mask策略,从unigram到4-gram对应的mask概率分别为40%-10%。在mask时不再采用 [MASK] token,而改为使用词语的近义词,近义词采用基于word2vec相似度计算的Synonyms toolkit获取,在极少数情况没有近义词时,使用随机词进行替换。模型总体对输入15%的词进行mask,mask时80%的概率替换为近义词、10%的概率替换为随机词、10%的概率保留为原始词。此外,BERT原版的NSP模型长期为研究者们所诟病,MacBERT模型中将NSP修改为SOP (Sentence Order Prediction),其正例为连续文本,负例为交换原始文本顺序,这样很好提升了模型在多句篇章型任务上的效果。模型的实验结果表明,去除上述MLM中任一改进都会导致平均性能下降,这表明几处掩码修改都有助于语言模型学习;同时去除SOP任务后,在机器阅读理解任务上的效果会明显下降,这也表明句子级预训练任务在篇章学习中的必要性。

EasyNLP带你实现中英文机器阅读理解

机器阅读理解模型使用教程

以下我们简要介绍,如何在EasyNLP框架中使用MacBERT及其他预训练语言模型,进行机器阅读理解任务的训练及预测。

安装EasyNLP

用户可以直接参考GitHub(​​https://github.com/alibaba/EasyNLP​​)上的说明安装EasyNLP算法框架。

pipeline接口快速“尝鲜”体验效果

为了方便开发者使用,我们在EasyNLP框架内实现了Inference Pipeline功能。用户可以在不需要自己训练或微调模型的情况下,直接“尝鲜”,使用pipeline接口一步调用finetune好的中英文机器阅读理解模型。只需执行如下命令即可:

from easynlp.pipelines import pipeline

# 输入数据
data = [{
"query": "杭州什么时候发布了《杭州市亚运城市行动计划纲要》?",
"answer_text": "2020年4月",
"context": "新华社杭州9月22日电(记者商意盈 夏亮)竞赛场馆全部竣工并完成赛事功能验收,“迎亚运”城市基础设施建设迈入快车道,亚运场馆提前开放掀起全民健身热潮……23日,延期后的杭州亚运会将迎来倒计时一周年,各项筹备工作也结出累累硕果,“天堂之城”再次蓄势待发。办好一个会,提升一座城。2020年4月,杭州发布了《杭州市亚运城市行动计划纲要》,其中包括基础设施提升、绿水青山守护、数字治理赋能等八项具体行动。随着亚运的脚步日益临近,杭州西站、萧山国际机场三期、合杭高铁湖杭段、机场轨道快线(19号线)等“两点两线”重大项目正式投运。根据杭州市城乡建设委员会发布的信息,预计到今年9月底全市快速路总里程将达到480公里。住在这里的人们正切身体会到悄然发生的变化——交通方便了,道路变美了,城市基础设施也愈发完善。",
"qas_id": "CN_01"
},
{
"query": "今年9月底全市快速路总里程将达到多少?",
"answer_text": "480公里",
"context": "新华社杭州9月22日电(记者商意盈 夏亮)竞赛场馆全部竣工并完成赛事功能验收,“迎亚运”城市基础设施建设迈入快车道,亚运场馆提前开放掀起全民健身热潮……23日,延期后的杭州亚运会将迎来倒计时一周年,各项筹备工作也结出累累硕果,“天堂之城”再次蓄势待发。办好一个会,提升一座城。2020年4月,杭州发布了《杭州市亚运城市行动计划纲要》,其中包括基础设施提升、绿水青山守护、数字治理赋能等八项具体行动。随着亚运的脚步日益临近,杭州西站、萧山国际机场三期、合杭高铁湖杭段、机场轨道快线(19号线)等“两点两线”重大项目正式投运。根据杭州市城乡建设委员会发布的信息,预计到今年9月底全市快速路总里程将达到480公里。住在这里的人们正切身体会到悄然发生的变化——交通方便了,道路变美了,城市基础设施也愈发完善。",
"qas_id": "CN_02"
}]

# pipeline的参数为finetune好的模型
# 当前EasyNLP支持中英文机器阅读理解的pipeline快速体验,分别集成了finetune好的中文macbert模型和英文bert模型
# 如想体验英文阅读理解,只需将模型名改为 'bert-base-rcen' 即可
generator = pipeline('macbert-base-rczh')

results = generator(data)

for input_dict, result in zip(data, results):
context = result["context"]
query = result["query"]
answer_gold = result["gold_answer"]
answer_pred = result["best_answer"]
print('n context: {} n query: {} n gold_answer: {} n pred_answer: {} n'.format(context, query, answer_gold, answer_pred))

如代码中所示,输入的data为一个list,其中每条instance为一个dict,包含其query、answer、context、id信息。pipeline的参数为finetune好的模型,当前EasyNLP支持中英文机器阅读理解的pipeline快速体验,分别集成了finetune好的中文macbert模型和英文bert模型,中文机器阅读理解的模型为 'macbert-base-rczh',如想体验英文阅读理解,只需将上述代码pipeline参数中的模型名改为 'bert-base-rcen' 即可。

以上代码的执行结果如下所示,可以看出,机器准确地理解了文本与问句的含义,并给出了正确的结果。

 context: 新华社杭州9月22日电(记者商意盈夏亮)竞赛场馆全部竣工并完成赛事功能验收,“迎亚运”城市基础设施建设迈入快车道,亚运场馆提前开放掀起全民健身热潮……23日,延期后的杭州亚运会将迎来倒计时一周年,各项筹备工作也结出累累硕果,“天堂之城”再次蓄势待发。办好一个会,提升一座城。2020年4月,杭州发布了《杭州市亚运城市行动计划纲要》,其中包括基础设施提升、绿水青山守护、数字治理赋能等八项具体行动。随着亚运的脚步日益临近,杭州西站、萧山国际机场三期、合杭高铁湖杭段、机场轨道快线(19号线)等“两点两线”重大项目正式投运。根据杭州市城乡建设委员会发布的信息,预计到今年9月底全市快速路总里程将达到480公里。住在这里的人们正切身体会到悄然发生的变化——交通方便了,道路变美了,城市基础设施也愈发完善。 
query: 杭州什么时候发布了《杭州市亚运城市行动计划纲要》?
gold_answer: 2020年4月
pred_answer: 2020年4月

context: 新华社杭州9月22日电(记者商意盈夏亮)竞赛场馆全部竣工并完成赛事功能验收,“迎亚运”城市基础设施建设迈入快车道,亚运场馆提前开放掀起全民健身热潮……23日,延期后的杭州亚运会将迎来倒计时一周年,各项筹备工作也结出累累硕果,“天堂之城”再次蓄势待发。办好一个会,提升一座城。2020年4月,杭州发布了《杭州市亚运城市行动计划纲要》,其中包括基础设施提升、绿水青山守护、数字治理赋能等八项具体行动。随着亚运的脚步日益临近,杭州西站、萧山国际机场三期、合杭高铁湖杭段、机场轨道快线(19号线)等“两点两线”重大项目正式投运。根据杭州市城乡建设委员会发布的信息,预计到今年9月底全市快速路总里程将达到480公里。住在这里的人们正切身体会到悄然发生的变化——交通方便了,道路变美了,城市基础设施也愈发完善。
query: 今年9月底全市快速路总里程将达到多少?
gold_answer: 480公里
pred_answer: 480公里

下面,我们将详细介绍中英文机器阅读理解模型的详细实现过程,从数据准备,到模型的训练、评估、预测,并给出基于EasyNLP的几种方便快捷的一步执行方法。

数据准备

采用预训练好的语言模型,进行机器阅读理解任务的finetune时,需要用户提供任务相关的训练与验证数据,均为tsv格式文件。文件中每行包含以制表符t分隔的多列,包含阅读理解训练所需的所有信息,从左至右依次为:样例ID、篇章文本(context)、问句(question)、答案文本(answer)、答案文本在篇章文本中的起始位置、篇章题目。样例如下:

DEV_125_QUERY_3   乙二醛是一个有机化合物,化学式为OCHCHO,由两个醛基-C相连。它是最简单的二醛,室温下为黄色液体。工业上,乙二醛可由乙二醇在银或铜催化下的气相氧化,或用硝酸溶液氧化乙醛制得。实验室中,乙二醛是通过用亚硒酸氧化乙醛制取。无水乙二醛可由固态水合物与五氧化二磷共热制得。乙二醛的应用有:of通常乙二醛以40%溶液的形式出售。它与其他小分子醛类似,可以形成水合物,而且水合物缩合生成一系列的“寡聚体”,结构尚不清楚。目前出售的至少有以下两种水合物:根据估计,乙二醛水溶液浓度低于1M时,它主要以单体或水合物的形式存在,即OCHCHO、OCHCH(OH)或(HO)CHCH(OH)。浓度大于1M时,主要为二聚体型,可能为缩醛/酮结构,分子式为[(HO)CH]OCHCHO。   工业上乙二醛是怎么制得的?   由乙二醇在银或铜催化下的气相氧化,或用硝酸溶液氧化乙醛制得。    59    乙二醛

下列文件为已经完成预处理的中英文机器阅读理解的训练和验证数据,可用于模型训练与测试:

# 中文机器阅读理解数据
http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/machine_reading_comprehension/train_cmrc2018.tsv
http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/machine_reading_comprehension/dev_cmrc2018.tsv

# 英文机器阅读理解数据
http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/machine_reading_comprehension/train_squad.tsv
http://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/tutorials/machine_reading_comprehension/dev_squad.tsv

中文机器阅读理解

在Python 3.6环境下,我们首先从刚刚安装好的EasyNLP中引入模型运行需要的各种库,并做初始化。我们只需指定 pretrain_model_name_or_path=hfl/macbert-base-zh,即可使用集成好的MacBERT模型。EasyNLP中集成了丰富的预训练模型库,如果想尝试其他预训练模型,如BERT、RoBERTa等,也可以在user_defined_parameters中进行相应修改,具体的模型名称可见​​模型列表​​。EasyNLP当前同时支持中英文的阅读理解,只需要在user_defined_parameters中指定language=zh,即可指定中文文本预处理的相应配置。

import torch.cuda
from easynlp.appzoo import MachineReadingComprehensionDataset
from easynlp.appzoo import get_application_predictor, get_application_model, get_application_eval()
args = get_args()
user_defined_parameters = parse_user_defined_parameters('pretrain_model_name_or_path=bert-base-uncased language=en qas_id=qas_id answer_name=answer_text start_position_name=start_position_character max_query_length=64 max_answer_length=30 doc_stride=128 n_best_size=10 output_answer_file=dev.ans.csv')

载入数据时,可以使用EasyNLP内置的MachineReadingComprehensionDataset。需要注意的是,由于描述文本可能过长,从而可能导致答案片段在超出max_seq_length后被截断的部分中。因此机器阅读理解中通常采用“滑窗法”,当描述文本过长时,使用滑动窗口将完整的描述文本拆成几段,将一个输入case拆成多个case分别处理。使用user_defined_parameters中的doc_stride参

数即可控制滑动窗口大小。
train_dataset = MachineReadingComprehensionDataset(pretrained_model_name_or_path=get_pretrain_model_path("bert-base-uncased"),
data_file="train_squad.tsv",
sequence_length=384,
input_schema="qas_id:str:1,context_text:str:1,question_text:str:1,answer_text:str:1,start_position_character:str:1,title:str:1",
first_sequence="question_text",
second_sequence="context_text",
user_defined_parameters=user_defined_parameters,
is_training=True
)

模型训练时,使用EasyNLP中封装好的get_application_model函数,并指定app_name="machine_reading_comprehension",便可进行训练时的模型构建。由于滑动窗口机制的存在,训练时batch_size设置不宜过大,否则容易引起OOM。

model = get_application_model(app_name="machine_reading_comprehension",
pretrained_model_name_or_path=get_pretrain_model_path("bert-base-uncased"),
user_defined_parameters=user_defined_parameters
)
发表评论

相关文章