事件抽取:Doc2EDAG论文梳理

2,856 阅读8分钟

1、二大件

2、概念梳理

  • DEE:Document-level Event table filling,文档级别的事件表充填。
  • EDAG:Entity-based directed acyclic graph,基于实体的有向无环图的路径扩展。
  • 实体(entity):实体对象的文本跨度
  • 事件角色(entity role):对于事件表的预定义字段
  • 事件参数(event argument):事件参数是扮演特定事件角色的实体
  • 事件记录(event record):一个事件记录对应于事件表的一个条目,并包含几个具有所需角色的参数

3、什么是事件抽取

事件抽取由两个子任务构成:事件检测和事件元素充填

  • 事件检测
    • 根据设定好的事件类型和事件角色(也可以认为是实体类型),基于触发词,确定事件中是否有对应的事件
  • 事件元素充填
    • 将文档中抽取出的实体,填充到对应事件角色的栏位中

image-20200608150308543.png

4、论文整体结构图

根据论文模型架构使用了三次Transformer(搞得模型有点偏大,训练起来资源非常吃紧),这里按运行流程把它分成三个部分来介绍

  • 第一部分,实体识别
  • 第二部分,文档级实体编码及事件检测(重点部分)
  • 第三部分,基于有向无环图的事件元素充填

image-20200608151722904.png

4.1、实体识别

  • 第一个Transformer用于实体识别

  • 在以往的实体识别中,通常把一个句子当作一个字的序列来处理,具体表示如下:

    si=[wi,1,wi,2,wi,3,wi,4,wi,5,]s_i=[w_{i,1},w_{i,2},w_{i,3},w_{i,4},w_{i,5},···]

  • 基于此,更进一步,可以把一篇文档当作一个句子的序列来处理,具体表示如下:

    d=[s1,s2,s3,s4,s5,]d=[s_1,s_2,s_3,s_4,s_5,···]

  • 利用Transformer进行字符级的实体抽取,同时进行句子级的向量化编码。

    • hi=Transformer(si)h_i=Transformer(s_i)
    • 其中c1,c2,c3,c4c_1,c_2,c_3,c_4即为句子级的向量化编码
    • 其中e1,e2,e3,e4,e5,e6e_1,e_2,e_3,e_4,e_5,e_6即为字符级实体的向量化编码
  • 这里抽取时确实的实体类型,就是上述所讲的事件角色

image-20200608160230578.png

4.2、文档级实体编码及事件检测(重点部分)

  • 第二个Transformer有用于获取文档级特征向量。
  • 这一步首先对上一步获取的cic_ieie_i进行维度上的统一。
    • 获取cic_i的方式有三种,分别是平均池化,最大池化和[CLS]的特征向量
  • 之后将维度统一后cic_ieie_i和句子位置(Sentences Position)向量进行拼接,作为第二个Transformer的输入。
    • hi=Transformer(si)h_i=Transformer(s_i)
    • 道理和字符级的Transformer一致,只不过把字符的位置向量换成了句子的位置向量
  • 基于获取的文档级特征向量,进行事件类型的分类。
    • 这里是一个多分类操作,一篇文档只有一个特征向量,但一篇文档内可能含有多个事件。

4.3、基于有向无环图的事件元素充填

4.3.1 元素充填难点
  • 元素充填分为单事件元素充填和多事件元素充填

    • 单事件元素充填,简单理解,就是对文档进行事件类型分类后,这个事件类型会带有一系列的事件角色等待被充填,这个时候,会从前面抽出来的一堆实体中选择合适的实体放到对应的位置完成充填,没有合适的,就填None(举个个人感觉比较恰当的例子,就行当年做英语阅读的完形填空一样。)
    • 多事件元素充填,其实就是,一篇文档实体抽取出来就这么多,但需要完成N个单事件的元素充填。
  • 显而易见,元素充填的难点在多事件元素充填上。

    • 在多元素充填的方式上有很多可讨论的点,以下图中的内容为基础进行说明,右下”Sentences“那个表可以当做是一篇文档(被拆分成一句话一句话),左侧”Entity Mark Table"这个表是从文档中抽取出来的实体,右上“Event Table of Equity Pledge”这个表可以看做是事件表,它的第一行是事件角色,然后下面是充填进去的事件元素,一行为一个事件。

image-20200608173043562.png

  • 在充填方式上,“Event Table of Equity Pledge”表中的待充填位置,可以放一个元素,理论上也可以放多个元素,因此,怎样准确而合适放置实体元素,这是一个很需要思考的问题。
4.3.2 有向无环图
  • 基于上述问题,论文作者为了不遗漏所有可以作为事件元素的实体,提出了一个有向无环图的事件填充方法。
  • 首先,我们得给这些实体元素分类,看它们适不适合填入某个事件角色中,这里使用到了第三个Transformer,具体流程如下图。ede^d是上面第二个Transformer获取到的带有句子位置信息的实体向量,这里就不过多说明了,可以看到cidc^d_i上面标着一个mm,论文里将之称为记忆向量,即memory,这个记忆向量富含对应句子的语意信息(这里提供了多种池化方式以供选择),mmede^d如左下方那样叠到一起,然后拼接上事件角色信息的嵌入向量(这里的拼接在代码里坐着直接用的相加,可以理解成把实体类型的名称编码成一个向量然后加上对应实体的向量),最终会获得一个富含角色信息的实体嵌入向量

image-20200609093005408.png

  • 上述获得的富含角色信息的实体嵌入向量,会按照事件角色列表设定的顺序依次分类,然后填入到相应的事件角色中去,如同上图上部和右部的内容所示,第一步,先把所有句子向量作为记忆向量,每个记忆向量为一个Token,每个融合后的实体向量作为一个Token,这些向量都要加上的角色向量,做为第三个Transformer的输入,角色向量为当前步骤下所要寻找的目前角色的向量,比如此时为第一步,那需要寻找的角色为该事件下的第一个角色,对应上图的Role1,经Transformer编码后,对输出的所有实体向量进行二分类,判断其中哪些实体属于该角色,如果有一个实体符合就生成一个事件,如果有多个实体符合就生成多个事件,如果没有实体符合就填入NULL。之后进入第二步,此时有一个变化,前面第一步被填入事件槽位的实体也会被复制一份放入记忆向量中,如果同一类型的事件有多个,那就组成多份记忆向量,比如第一步生成了两个事件,即该事件类型有两个不同的Role1,那在第二步中有两份记忆向量,每个Role1都单独存在于一份记忆向量中,并以此为基础寻找Role2,整个过程可以参考上图右侧寻找Role3的示意图。简而言之,互相之间存在关联的实体元素才能组合为一个合理事件,所以在事件表填槽过程中,不仅要考虑事件角色,也要考虑该事件中已经存在的事件元素,从而使后面填入的事件元素能和前面的关联起来。这里描述的可能有点抽象,那么看看下图,可能会直观一点,这是作者绘制的事件填槽过程中的路径扩展图。

image-20200609095138262.png

5、实验那点事

5.1、Loss值的设计

  • 整体的Loss值的设计简单粗暴且清晰明了,用了三个Transformer,所以主要分为三部分

    • 第一部分,即第一个Transformer,实体识别的Loss值,记为LerL_er
    • 第二部分,即第二个Transformer,文档分类的Loss值,记为LtrL_tr
    • 第三部分,即第三个Transformer,事件充填的Loss值,记为LdagL_{dag}
  • 这三个部分的Loss函数加权求和下,就是最终的Loss函数了

image-20200609103613497.png

5.2、效果验证

6、总结

6.1、优点

  • 支持中文
  • 可多事件抽取
  • 效果确实不错,比现有其他方法强

6.2、缺陷

  • 用了三个Transformer,导致模型很大,训练时很吃显存资源,最大句长这个参数难以调高,不过,实验室或公司若配备单块32GB显存的GPU服务器就当我没说。
  • 效果有待优化,F1值仅徘徊在0.8附近,具有进一步提高的空间。

6.3、争议

  • 这篇文章最让我感到纠结的地方就是这个“有向无环图”的路径扩展方法。

  • 若说好用,它非常适用于论文所用的金融数据

  • 若说不好用,在有些场景下,这个路径扩展方法非常的鸡肋,下面是例子

    • 假设一个打架事件,“关羽给了武松一巴掌”,生成如下事件

    • 然后有这样一段打群架的文字,“赵云、夏侯惇、张飞、黄盖……(三国演义里436位英雄的名字)痛殴李逵、宋江、花荣……(梁山泊108好汉的名字)”
    • 你猜上面这段文字用这个“有向无环图”的路径扩展方法能抽取多少个事件?
    • 没错,是436×108=47008436×108=47008个事件,这很让我炸裂。
    • 所以遇到这个情况就得灵活应变,在对实体元素进行分类的时候,可设定一个阈值,当实体对于某个事件角色的分类高于设定阈值的时候,不管是一个还是多个元素都填入到对应的事件角色中去。这种方式我尚未测试过,不知道具体效果会如何,但猜测必然会出现事件的遗漏,毕竟鱼和熊掌不可兼得。

7、上述内容如有纰漏欢迎批评指正,或有其它想法见解,也欢迎一起探讨