图1.private test榜排名
01
背 景
财务报表数量巨大,使得人们很难获取并分析公司的财务状况,对财报自动化分析并得到稳健的、可解释性强的数值推理面临着独特的挑战。FinQA论文为此提出了一个针对金融财报的数值推理问答数据集,数据集中包含异构的(表格和文字说明)公司财报,并招募专家编写关于数值推理的问答对,答案中既包含了计算结果,也有可解释的计算过程,可以点击此处查看数据样例。竞赛主办方根据上述数据集举办了FinQA竞赛,参赛选手需要训练模型预测计算过程与计算结果来回答针对公司财报提出的一些需要数值推理计算的问题。
02
数据集
2.1 介绍
FinQA数据集包含带有表格(结构化数据)与文字说明(非结构化数据)的公司财报,计算的操作包括六种数值操作和四种表格聚合操作,一个计算过程可包含多步计算操作。比赛提供了包含正确答案的train(6251)、valid(883)、test(1147)数据集和用于比赛排名且不带正确答案的private test数据集。
FinQA数据集中,23.42%的问题仅需要财报的文字叙述即可回答,62.43%的问题仅需要财报的表格即可回答,剩余14.15%的问题需要结合二者回答。同时,46.30%的问题仅涉及财报中的一句文本或者一行表格中的数值,42.63%的问题涉及两行文本或者表格,剩余11.07%则需要更多。在计算过程中,divide、subtract、add、multiply分别占据了45.29%、28.20%、14.98%、5.82%,59.10%的计算过程仅有一步。
图2.FinQA数据示例
图3.FinQA数据统计
2.2 DSL
FinQA论文中定义了Domain Specific Language,由数值操作和表格操作组成,定义program由多步操作组成:
每个操作有一个参数列表
2.3 评估
根据计算结果是否相等定义了execution accuracy,但有时模型可能“误碰”正确数值结果,此时存在高估的可能。
根据计算过程是否相等定义了program accuracy,但有时问题可使用不同的计算过程(仅指不同的解题思路,类似于加法的两个参数互换位置等属于相同的计算过程),同一个问题会存在多个正确的计算过程,此时存在低估的可能。
因此,模型的真正性能会在execution accuracy和program accuracy之间。
代码中使用sympy包的simplify函数判断两个数学符号表达式是否相等,因此如下的两个program是相等的:
2.4 分布不一致
我们使用adversarial validation技术对FinQA数据集进行分析,我们将train、valid、test混合到一起,训练一个分类器去区分数据的来源,分类器在train上达到了0.91的AUC,在test上达到了0.85的AUC,这意味着test和其他数据之间的分布不一致,我们重新划分train与valid减少valid与test的gap。
03
模 型
我们的模型分为两部分:从全文中召回包含计算所需数值的句子的retriever和根据问题与召回句子生成计算过程的program generator。
因为回答大部分的问题涉及的文本或表格数量都很少,因此我们首先用retriever来缩小program generator的查询范围。retriever由baseline模型、prompt learning模型和context模型三个模型集成而得到。财报由多句文本和表格组成,使用模版将表格转换为文本(同FinQA论文),retriever根据数值推理问题从所有文本中召回计算所需数值所在的文本,缩小查询计算所需数值的范围,降低program generator生成计算过程的难度。
3.1.1 baseline模型
同FinQA论文,baseline模型在训练阶段将问题与单句文本拼接,然后输入BERT做二分类任务,计算所需数值所在的文本视为正样本,其余文本视为负样本,正负样本采样比例为1:3,每个epoch都对负样本重新采样。在预测阶段,模型对所有文本输出其正样本类别对应的分数,按照分数从高到低将这些文本排序,召回分数高的文本(表格)。
3.1.2 prompt learning模型
本文数据量较少,因此我们使用经常被用在few shot的prompt learning来解决问题。实验中使用OpenPrompt实现prompt learning训练模型,我们选择了MixedTemplate和ManualVerbalizer,混合模版见下文示例,ManualVerbalizer将回答yes和no映射到二分类标签,微调的语言模型使用T5-large,正负样本采样比例为1:3,每个epoch都对负样本重新采样。预测阶段同baseline模型,召回预测分数高的文本(表格)。
{"placeholder":"fact"} Question: {"placeholder":"question"} {"soft": "Is the relevant data of the problem in the previous article ?"} The answer was {"mask"} .
3.1.3 context模型
上述两种模型每次都只能考虑一句文本,无法充分利用文本的上下文信息,为此我们提出了一个新的context模型,该模型每次按照财报中的文本顺序将问题与n句话拼接,不同语句之间使用[SEP]连接,示例如下(为方便下文说明,对[SEP]进行编号):
[CLS] (Question) [SEP 0] Sentence 1 [SEP 1] Sentence 2 [SEP 2] ...... [SEP n-1] Sentence n [SEP n]
每一句文本对应两个[SEP],类似于roberta-base for QA模型预测问题答案的开始位置与结束位置,我们使用句子前的[SEP]与句子后的[SEP]来预测这句话是否包含回答问题所需的数值。在训练时,使用两个网络层分别对[SEP 0]、[SEP 1]......[SEP n-1]和[SEP 1]、[SEP 2]......[SEP n]做二分类,前者针对每句文本前的[SEP]预测,后者针对每句文本后的[SEP]预测,包含回答问题所需数值的文本前后的[SEP]对应正分类,否则分类为负。在我们的实验中 n=8,为减少文本位置对模型推理的影响,我们设置了步长为4的滑动窗口来生成训练样本。
在预测阶段,我们不设置滑动窗口(或可认为滑动窗口步长为8),对每一句文本前后的[SEP]分别预测其正类别分数,得到start_score和end_score,按照两者分数之和对所有文本从高到低排序,召回预测分数高的文本(表格)。
3.1.4 集成
在图4的venn图中,绿色表示三个模型均正确预测的文本,蓝色表示仅一个或两个模型正确预测,橘黄色表示三个模型均未正确预测,可以看到三个模型虽然使用同样的数据训练,但是其预测能力仍有不同,这为集成模型提供了基础。上述三个模型均对每一句文本输出其正类别分数,利用valid数据集可以基于这些分数训练一个逻辑回归分类器来达到集成的效果。
我们为program generator生成两种模式的训练数据,第一种(stack)根据逻辑回归分类器预测的分数排序,召回top k个高分文本;第二种(stack positive)根据逻辑回归分类器的分类结果召回分为正类别的文本。前者对每个问题召回的文本数量固定,召回率较高;而后者召回数量不固定,召回率略低,但平均召回数量较少。
3.2 program generator
在retriever缩小了回答问题所需数值的查询范围之后,我们使用program generator来生成具体的计算过程。program generator由baseline模型、transformer decoder模型和remove redundancy模型集成而得到。program generator每一步预测计算符号及其参数,计算的参数可为先前的计算结果或召回文本(表格)中的数值,直到预测EOF符号结束计算过程。
3.2.1 baseline模型
模型结构同FinQA论文,模型使用attention和LSTM来捕获各种输入(文本、计算符号等)及历史的信息,然后在一定的规则(确保生成的计算过程合法)之下生成计算过程。但在训练原文的模型时会遇到收敛速度慢和loss突然大幅增加的问题,因此我们做了如下改动:
冻结BERT(roberta)参数,先训练其余参数几个epoch,然后解冻BERT参数一起训练。
使用梯度裁剪、warm up、linear scheduler和带有weight decay的AdamW优化器。
图5.generator baseline模型
下面简单介绍baseline模型:
首先做如下定义:
question和retriever检索到的文本经过token化后得到{
DSL中的特殊符号token{
表示每一步计算结果#
接下来使用预训练模型对{
baseline模型使用LSTM解码,在第T步,将经过更新的program token embeddings H输入到LSTM中得到输出
step memory tokens 对应的{
在推理阶段,baseline模型通过使用多种MASK来保证生成的program的结构正确性。
3.2.2 remove redundancy模型
相比于其他常见的NLP数据集,FinQA数据集所含的数据数量较少,为减少需要训练的参数数量、降低训练的难度,我们提出了remove redundancy模型。baseline模型需要将全部文本输入和计算符号一同输入decoder作预测,remove redundancy模型则仅将文本中的数值和表格行名(对应表格聚合计算)与计算符号一同输入decoder,remove redundancy意味着仅对文本中的数值和表格行名做预测。
3.2.3 transformer decoder模型
该模型使用与baseline模型相同的encoder编码输入,但为更好地捕获历史信息,我们使用4层的transformer做decoder替代LSTM,decoder输出的向量与输入做attention,根据attention权重来预测下一步,同时该模型简化了baseline模型的部分attention计算。为加快训练速度,我们使用了transformer并行化训练方法。
3.2.4 集成
program generator采取投票(vote)的方式做集成,每个模型使用其在private test上得到的execution accuracy作为投票权重。program generator的投票方式有两种:对整个program投票、对每个program的每一步step投票。经过实验对比,我们最终选择了对整个program投票的方式。
图6. 不同模型的预测差异
04
实验结果
4.1 retriever
我们在train上训练,在valid上挑选最优模型并训练逻辑回归分类器集成模型,在test上测试,retriever召回率表现见下表:
召回率计算方式:先计算单例召回率然后平均
stack由3个模型集成得到,使用全部文本数据训练分类器,根据分类器预测的分数召回固定top k个高分文本;stack positive正负样本采样比例2:1训练分类器,根据分类器预测的类别最多召回top k个文本。第二个表格统计了stack与stack positive在test上的召回率与预测准确率,stack positive相比于stack以召回率的下降为代价召回更少的文本。
4.2 program generator
program generator的模型均使用stack和stack positive生成的训练数据进行训练,我们使用valid挑选最优模型,在valid和private test上的实验结果如下:
从表中可以看到,对整个program投票的方式相对于单模型可以提升4.14%的execution accuracy和3.37%的program accuracy。上表中三个单模型的结果均基于stack生成的数据,但vote模型基于多个以stack或stack positive生成的数据训练的program generator模型。
4.3 消融实验
针对前文提到的消除数据不一致的方法,我们做了消融实验证明其作用,我们分别在原数据集和重新划分后的数据集上训练baseline模型,然后利用相应的valid来选取最优模型在private test上测试,结果见下表:
从表中可以看到,使用adversarial validation重新划分数据集,可以比较有效地消除valid和private test数据分布之间的gap。
05
实验结果
从此次比赛的结果来看,我们使用NLP预训练模型与集成的方法虽然以execution accuracy 71.93%和program accuracy 67.03%取得了第一名的成绩,但是与人类专家的execution accuracy 91.16%和program accuracy 87.49%相比仍然有很大差距,这说明当前的NLP预训练模型与常见方法仍然无法很好地解决数值推理问题,这一领域仍然需要NLPer们更为深入的研究与探索。
本文分享自微信公众号 - 支付宝技术(Ant-Techfin)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。