361. TensorFlow 2.0 Question Answering | tensorflow2-question-answering
最终提交的是一个基于BERT的单一模型。它在公开数据上的得分为0.71,在私有排行榜上的得分为0.69。看看其他人的解决方案,我的方案稍微有点复杂。
我去掉了基线脚本中引入的特殊标记(如 [ContextId=..][Paragraph=0] 等)。相反,我保留了简化的HTML标签(例如表格标签中包含的 colspan 信息被我移除了)。我还在每个片段的开头和结尾添加了 <*> 和 </*>。我保留了4%的负样本,同时也保留了那些不包含在单个片段中的超长答案。我还处理了整个文档文本,因此忽略了原始脚本中的 max_contexts 参数。
与基线类似,我使用了分类头,以及一个用于跨度起始和结束logits的头。通过掩码操作,这被用来获取长答案和短答案的logits。
我还添加了一个“交叉”头,它是BERT模型序列输出对的线性函数。短跨度logits是通过起始和结束logits以及交叉头的相应输出之和获得的。不可能的跨度被屏蔽掉,softmax 给出了跨度概率。对于长跨度,起始和结束logits都使用了交叉熵标准。对于短跨度,误差是正短跨度总概率的负对数。这些误差项仅针对具有长、短答案的样本计算。所以这里的目的是在给定答案的情况下学习位置,而存在答案的概率来自 answer_type 输出。
对于每个片段,计算具有最大概率的长和短跨度。从答案类型头计算片段中存在短答案或长答案的概率,并将这些概率分配给片段内最可能的跨度。这些投票在包含给定跨度的所有片段中最大化。然后考虑具有最高总分的跨度作为答案。阈值是使用NQ数据集的开发数据计算的。
我在TPU上训练了2个epoch,学习率为2.5e-5,批量大小为64。在NQ数据上训练之前,我使用相同的设置和预处理在SQuAD 2.0数据集上微调了BERT模型。