关系抽取比赛:pipeline方法实践

1.写在前面

  • 寒假开始看RE,3月正好看到百度的比赛,在导师的支持下报名参加。
  • 看论文学习和动手实践还是有区别的,第一次参加NLP的比赛,第一次使用bert,动手能力还是比较捉急,看代码,跑模型,摸爬滚打花了好多时间。
  • 本次比赛还是有许多不足,会一一总结。一开始对于任务数据理解不够深刻,选用了pipeline方法,就决心一路走到底吧
  • 从结果来看不是很理想,由于时间设备关系,也没怎么炼丹,去追求最好的结果。过程来说动手能力得到了锻炼。
  • 本文档单纯做个记录

2.数据部分

  • 数据存在关系类别不平衡长短句数量不平衡实体类型数量不平衡的问题
  • 实体中存在一些生僻字,通用的bert不是很契合。

针对以上两个问题,使用了数据增强以及语言模型深度预训练的做法。

数据增强:EDA

深度预训练:How to Fine-Tune BERT for Text Classification?

未能处理好的问题

数据中存在噪声,具体体现:

  • 在实体标注不全
  • 句子中三元组标注不完整
  • 文本中有许多特殊字符、表情

三元组标注不完整,其实可以考虑在训练集上做类似于交叉验证的做法。比如5份数据集,每次用4份训练,得到5个模型,在训练集上跑5份结果,然后进行投票,5份都预测到却没在训练集中的实体进入模型。

实体标注不全文本中的噪声则需要一些文本清洗,正则表达式的做法,碍于捉急的动手能力,等到发现的时候,已经没时间,只能标注时全部丢掉。

  • 反思:对于数据理解不够充分。虽然是NLP任务,也需要进行描述性分析,也需要用肉眼看数据,才能更好地理解数据,这部分工作没做到位。

3.解决方案

Pipeline的思路应该是有两种做法:

  • 先预测句子可能的类别(多分类多标签),再对该类别下的句子抽取头尾实体。
    P ( s , p , o ∣ s e n t e n c e ) = P ( p ∣ s e n t e n c e ) P ( s , o ∣ p , s e n t e n c e ) P(s,p,o| sentence) = P(p | sentence) P(s,o|p,sentence) P(s,p,osentence)=P(psentence)P(s,op,sentence)
  • 先标注实体,再进行关系分类
    P ( s , p , o ∣ s e n t e n c e ) = P ( s , o ∣ s e n t e n c e ) P ( p ∣ s , o , s e n t e n c e ) P(s,p,o| sentence) = P(s,o|sentence)P(p | s,o,sentence) P(s,p,osentence)=P(s,osentence)P(ps,o,sentence)

对于前者,参考的是:bert实践:关系抽取解读
后者是自己做的方案。选用的框架是:Kashgari

NER部分

Bert + BiLSTM + CRF
由于对NER任务没太多了解,就选了框架中自带的模型。

主要说说标注的设计。

数据集中实体是带类型信息的,比如人物、地点、歌曲等等,一共有26个类别。标注设计方式:B-1,B-2,…B-26,I,O。

之所以这样设计,是因为如果类别识别的相当精准,那其实相当于已经基本做完了,因为根据实体类型,就能大致确定关系(除了人物-人物有四种关系)。但有误差,也能大致确定头尾实体,以及哪些可能是无关的实体。

如果不考虑类型的信息,那如果一个句子中有6个实体,输入关系分类模型时,就需要穷举6*5 =30 个实体对,这显然是不好的。不仅浪费计算资源,同时,大量无关实体对也对关系分类模型数据标注造成了困难。

所以,标注设计的目的是,希望把实体类型信息运用充分,利用标注的信息做初步召回。但这样因为标签类别多自然错误率会增多,同时误差也在模型间传播【深刻体会】。

在验证集上,NER模型f1-score = 0.83

关系分类部分

参考方法:《Enriching Pre-trained Language Model with Entity Information for Relation Classification》

这篇文章从学术角度,没有多大的贡献,只是发现了一种标注实体的方式,十分契合bert。

模型结构如下:
在这里插入图片描述
简单来说,头尾实体前后分别加上 $ 与 # 。然后构建两个mask向量,只有实体所在位置是1,非实体部分mask掉。输出层两个mask向量分别去与bert的sequence_output做内积,得到的两个向量与bert的pool_output拼接,输入进全连接网络做一个softmax,输出类别。

这部分我的工作量主要在基于Kashgar包的复现模型上。自行设置了一个类,这是一个多输入,单输出的模型。

具体坑概括如下:

  • 多输入的部分是一个元组,传入到base_model.py里需要改data_generator部分(原框架只适应于单输入,虽然说支持,但其实不太行)
  • 自定义的模型会少些属性,用callback时,在callback.py中也要稍作修改。

关系分类单模型的f1-score达到了0.93。就是说,在知道实体信息的情况下,预测实体间关系的效果是相当不错的。

4.预测部分

首先进行NER:
Input:sentence
output:【(e1,t1)(e2,t2)(e3,t3)(e4,t4)】
e是实体,t是实体类型。

假设实体类型预测是对的。
根据给定的schema,我可以知道哪些是头实体,哪些是尾实体,哪些类型的尾实体匹配相应的头实体。
即,我可以得到(e1:e2,e4)(e2:e3) (e3:e4)【subject:object】的形式。
同时,还可以知道他们可能的关系,即4个候选的label_list。

这样在关系分类阶段:
只需预测e1,e2 ; e1,e4 ; e2,e3 ; e3,e4 这四组实体对的关系。

召回策略:

  • 假设四组预测得到的关系是p1,p2,p3,p4。
  • 如果 p i p_i pi在候选的 l a b e l l i s t i label list_i labellisti中,那召回这个三元组 ( s i , p i , o i ) (s_i,p_i,o_i) (si,pi,oi)
  • 如果不在,则进入第二轮候选的list。
  • 第二轮候选list通过观察预测结果,通过一些模板的做法召回

这样的做法,十分依赖NER的标注结果。可惜NER这部分做的比较粗糙,也没有调参,只有0.83的f1值,所以最终结果不是特别理想。而且出现了少部分句子(1/12)预测出单实体、零实体的情【这种情况这套方案没法解决】。

所以只能用关系分类+实体抽取的方法(上述链接)做填充与召回(类似于融合的办法吧,但没有投票,是以该结果为基准)

后面为了提升效果,又把官方baseline的预测结果做投票,最终f1为0.7392。

5.总结

遗憾

反思

  • 首先,要对数据进行比较深入的探索与了解;
  • 其次,要对于相应的模型与方法调研充分,侧重于其适应于什么数据,解决什么问题,有哪些缺陷。
  • 再者,要想自己去改进方法与模型,更应该从数学的角度出发,将具体问题抽象成数学的形式,模型是形式的一个表达。如果形式不变,那只是在这种框架下找最好的模型与参数。形式改变,是解决思路的改变,更有可能对于一些方法进行改进。
  • 最后,时间安排应该更加紧凑,要对于模型训练、调参、融合有个预估。

6.有用的链接

nlp中的实体关系抽取方法总结
基于DGCNN和概率图的轻量级信息抽取模型

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值