如何利用Bert处理长文本
1 前言
预训练模型Bert能处理最大序列长度为512,当面对长文本(文档级别)时候,通常是采用text truncation或者sliding window方式,让输入模型的序列长度符合预设值,但这种处理方式会导致丢失与任务相关的全局信息。如下图,在做QA任务中,与问题相关的答案在Bert处理的长度范围外,这样难以让模型回答正确。为了解决该问题,本次分享NeurIPS 2020年的一篇paper《CogLTX: Applying BERT to Long Texts》,作者来自清华与阿里团队。论文的核心思想是,模仿人的理解记忆力机制,使用Bert处理长文本,提出MemRecal机制,识别长文本中的关键句子,然后经过排序、抽取、融合,形成新的文本用于下游任务。本篇论文开放了源码,地址为https://github.com/Sleepychord/CogLTX。
2 模型
上图为CogLTX面向三种不同任务的处理流程:
(1) 将输入的长文本x,通过动态的方式切成连续的短句子(x[0],....,x[n]);
(2) 通过MenRecall模块,从(x[0],....,x[n])中识别与任务相关的关键片段(key text),组成语块z;
(3) 依据不同任务类型,将关键语块z组成满足任务需求的输入格式,然后输入BERT模型(文中称为:reasoner)进行下游任务处理;
看上图其实很好理解,跟正常用BERT处理流程是一致的,关键是部分是MenRecall,如何从long text中抽取与任务相关的key text,将key text代替long text作为输入,这便是本篇论文的核心。
关于MenRecall,作者是基于这样的假设的:
上述公式的意思:长文本输入任务模型与关键文本块输入任务模型得到的效果是差不多的,是一致的;另一层面意思为长文本中是有很多跟任务不相关的句子,删掉也是不会影响任务处理效果的。这个假设是很合理的。
基于上述的假设,作者就设定了一个judge()模型,来判断是否是关键语块;其判断计算方式如下:
具体操作是按照judge([])的方式遍历,若输出为1,就表明与任务相关,是关键语句,将其加入中,接着判断,依次下去,当len()超过输入BERT的最大长度时,可以作为终止判断的条件。
如此,就会引出下面的问题:通过judge()从长文本中抽取出关键语块,这是一个新的任务,那在训练该任务时,它的损失函数是什么?
针对上面的问题,文中设计两种损失函数方式,一种面向监督学习,一种面向无监督学习,如下:
公式(3),(4)显示将判断的语块与真实的语块做下交叉熵比较;公式(5),(6)表示减少或增加一个句子,看原任务损失值变化来判断该片段是否是关键语块。显然,这是个逐步迭代的过程。下图为MenRecall详细计算过程示意图。
3 Experiments
本文利用自己的方法在多个任务下进行实验,具体包括Reading comprehension,Multi-hop question answering,Text classification,Multi-label classification,下面是部分任务的实验结果。
Reading comprehension results Text classification results Multi-label classification results显示模型测试效果特别明显,每个任务下的数据集上都有近4%~5%的提升。也说明捕捉长文中更多有用的信息进行学习,是对任务肯定有利的。
4 结语
关于长文本的处理相关的paper很多,其共性做法都是要将长文本变成短文本来处理,而如何来处理,便产生了不同的想法。本人之前是采用KMeans聚类的方式来识别关键语块,但这个方式对具体做什么任务关系很大,因为在某些任务中很多句子是否是关键句并不明显,用向量表征的方式聚类,效果并不太好。看了本篇paper的思路,觉得值得借鉴试试,同时也就分享出来~
更多文章可关注笔者公众号:自然语言处理算法与实践