Nguyen, Thien Huu, Kyunghyun Cho, and Ralph Grishman. “Joint Event Extraction via Recurrent Neural Networks.” ACL 2016
基础知识:RNN – LSTM – GRU – wdmad的文章 – 知乎
1 介绍
事件抽取(EE)分成 pipeline 和 joint 的方法,这篇文章是第一次用 DNN 的 joint 方法。整个算法分成两个部分,先用双向 RNN 做句子级的提取,然后对 trigger 和 argument 进行预测。在预测的过程里,还设计了不同的记忆矩阵 $G$,用来更新 event triggers 和 argument roles 的依存关系。(具体见 2 部分)
JRNN 的方法在 trigger 和 argument 的识别和分类上 F1 都是 SOTA,在整体性能上由于之前离散特征的 joint 方法,在一句话多件事的情况里,更是大 margin 的 SOTA。
2 相关工作
当时(2016 年),EE 的 SOTA 是有两类方法,一个是上一篇文章的 DMCNN,另一个是基于多层感知机的 joint 方法。前者的优点可以学到连续特征,后者是 joint,就是不用分成 trigger 和 argument 两步,所以 ① 可以避免误差积累,② 可以找出 event triggers 和 argument roles 的关系。
关于这个 ② 我详细说一下我的理解:这个意思就是 trigger 与 argument 之间可以互相优化。得到 trigger 的 event type 之后,能据此找到 argument 符合这个 type 的 最好的 role;得到 role 之后,又能据此更新 trigger 的更好的 event type。而 pipeline 的方法只能先 trigger event type 再 argument role,然后就没了。
另外,这篇文章还提出了 joint 方法的一个优点。还以这个句子举例:
In Baghdad, a cameraman died when an American tank fired on the Palestine hotel.
对于 die 这个 trigger,pipeline 的方法可以找到 cameraman 这个 argument;但是对于 fire 这个 trigger,就很难找到 cameraman 这个 trigger。这是因为 fire 和 cameraman 太远了,之前的 DMCNN 毕竟是 CNN,只能提取 localize 的特征。joint 的方法可以利用句子级的特征,找到 fire 的 cameraman。这个句子的特征实际上就是句法分析(dependency tree),比如通过句法分析可以知道,在一句话里,victim 的 argument 通常也就是 die 的 argument。在这篇文章的算法中,这个句子级的特征(或者说句法)就用 $G$ 表示。
这篇文章的方法同时拥有了上述的三个优点。DNN(本文题目是 RNN,实际是用的 GRU)可以得到连续特征,记忆矩阵 $G$ 可以找出 trigger 和 argument 之间双向的、句子级的关系。
3 方法

这篇文章的算法结构如图所示(这图画的不行,不用看)。算法分成两个部分,先是编码阶段,用双向 RNN 得到整句话每个 token 的特征表示;然后是预测阶段,用刚刚得到的表示同时预测 event trigger and argument role。
3.1 编码
这部分是用离散编码输入 RNN,得到连续的特征向量。是图中的下半部分。
3.1.1 句子编码
每个 token 的编码是三部分直接拼接而成的向量,这三部分分别是:
- token 的 embedding。这篇文章用的是改版 Word2Vec,就是 Word2Vec 本来是用 CBOW 或者 Skip-Gram 模型,这里用的是 concatenation-based variant of CBOW (C-CBOW)。CBOW 是输入邻居输出 token,Skip-Gram 是输入 token 输出邻居,C-CBOW 是输入 token + 邻居,输出与 CBOW 相似。C-CBOW 在最后实验结果里好于 CBOW 和 Skip-Gram,第四部分再说。
- entity type 的 embedding。查表得到的。
- binary vector。这部分长度是这句话的 dependency tree 里面,两两单词之间可能的关系的数量,即每个位置代表一种关系。当 dependency tree 里面,存在和当前 token 相连且是这种关系的词语时,这个位置就是 1,否则就是 0.
这里没有像 DMCNN 一样,使用相对关系。这是因为 JRNN 是一起预测 trigger 和 argument 的,在预测的过程里相对位置是可能一直更新的,所以一开始的编码没法用这个相对位置。正是因为没用相对位置,这使得 JRNN 在 argument role 的分类上要比 DMCNN 差,这个也第四部分再说。
3.1.2 RNN
RNN 详见基础知识。这篇文章输入刚才编码得到的序列 $X=(x_1,x_2,…,x_n)$,正向 RNN 输出特征向量序列 $(\alpha_1,\alpha_2,…,\alpha_n)$,逆向 RNN 输出特征向量序列 $(\alpha_n’,\alpha_{n-1}’,…,\alpha_1′)$。最后的特征表示 $(h_1,h_2,…,h_n)$ 的每项 $h_i = [\alpha_i,\alpha_i’]$ 即为俩结果拼一起。为防止梯度消失,本文使用 GRU。
3.2 预测
这篇文章的最大亮点就是设计了几种记忆矩阵 $G$,来表示 token 之间的依赖关系(原文是 dependency,直译是依赖关系,实际就是句法结构)。对于第 i 个 epoch,有:
- $G_i^{trg}\in R^{n_T}$ 是存 trigger 状态的向量,表示 trigger 之间的依赖关系,长度 $n_T$ 是 trigger 的种类数;
- $G_i^{arg}\in R^{k\times{n_A}}$ 是存 argument 状态的向量,表示 argument 之间的依赖关系,其中 $k$ 是 trigger 对应的那个 mention 的长度,$n_A$ 是 argument 的种类数
- $G_i^{arg/trg}\in R^{k\times {n_T}}$ 是存 trigger 和 argument 状态的向量,表示 trigger 和 argument 之间的依赖关系。
预测的过程是一个迭代更新的过程,每次迭代包含三个部分。
- 预测 trigger
- 预测 argument
- 更新 $G$
最终的输出是对于每个 token $w_i$ 的 trigger type $t_i$(若不是 trigger,$t_i$ = others),以及每个 token $w_i$ 在 mention 里每个 entity $e_j$(我觉得就是名词)的 argument role $a_{ij}$(若不是 trigger 或不是 这个 trigger 对应的 argument,$a_{ij}$ = others)。其中 $i=1…n$,$j=1…k$。
3.2.1 trigger 预测
这一步是先对于每个 token $w_i$,构建特征向量 $R_i^{trg} = [h_i,L^{trg}_i,G^{trg}_{i-1}]$,为三部分直接连接,分别如下:
- $h_i$ 是刚才得到的整句话关于 $w_i$ 的编码;
- $L^{trg}_i = [D[w_{i-d}],…,D[w_{i}],…,D[w_{i+d}]]$ 是 $w_i$ 跟它上下文的 embedding,就是 Word2Vec 得到的那个拼到一起;
- $G^{trg}_{i-1}$ 是上一步的记忆向量,具体是啥 3.2.3 再说。
得到特征向量 $R_i^{trg}$ 之后,再把一句话的 $n$ 个特征向量过一层全连接网络、过一层 softmax,就得到每个 token $w_i$ 是 $t$ 这种类型的 trigger 的概率分布 $P^{trg}_{i;t}$,每个 type 都选概率最大的,就得到了 trigger 及 event type 的预测。训练过程是 event type $t$ 作为标签,有监督训练。这篇文章用的是 mini-batch SGD。
3.2.2 argument role 预测
首先,对于 token $w_i$,如果它的 event type 是 others(不是 trigger),那么可以直接把 $a_{i1},…,a_{ik}$ 也全都设成 others。否则,就开始在句子里,遍历每个 entity $e_1,…,e_k$。
对于每个 $e_j$,都和 3.2.1 差不多,先搞一个特征向量 $R_{ij}^{arg}$,再过一个神经网络得到 $e_j$ 关于 trigger $w_i$ 的 argument role 是 $a$ 的概率 $P_{ij;a}^{trg}$,概率最大的,就表明 argument role 是 $a$,故不再赘述。
下面详细说明特征向量 $R_{ij}^{arg}$ 的建立,$R_{ij}^{arg} = [h_i,h_{i_j},L_{ij}^{arg},B_{ij},G_{i-1}^{arg}[j],G_{i-1}^{arg/trg}[j]]$,分别如下:
- $h_i$ 是编码时得到的整句话关于 $w_i$ 的编码;
- $h_{i_j}$ 是编码时得到的整句话关于 $e_j$ 的编码;
- $L_{ij}^{arg}= [D[w_{i-d}],…,D[w_{i}],…,D[w_{i+d}],D[w_{i_j-d}],…,D[w_{i_j}],…,D[w_{i_j+d}]]$ 是 $w_i$ 跟它上下文的 embedding,以及 $e_j$ 跟它上下文的 embedding 全部拼一起;
- $B_{ij}$ 是 $V_{ij}$ 过一层神经网络的结果(为了“further abstraction”,我理解就是降维、密集),这个 $V_{ij}$ 是 [1] 中提出的,是一个长度为 8 的 binary 向量,每个位置的意思如下面表格所示。
- $G_{i-1}^{arg}[j]$ 和 $G_{i-1}^{arg/trg}[j]$ 是上一步的记忆矩阵 $G_{i-1}^{arg}$ 和 $G_{i-1}^{arg/trg}$ 关于 $e_j$ 的那一行。

3.2.3 更新记忆矩阵 $G$
三个记忆矩阵 $G_i^{trg}$、$G_i^{arg}$、$G_i^{arg/trg}$ 都是 binary 的(每个位置不是 0 就是 1),更新方式分为如下:
- $G_i^{trg}\in R^{n_T}$,存储 trigger 之间的依赖关系。$G^{trg}[t_i]=1$ 表示 $t_i$ 的这种 trigger 在这句话里存在。如果这一轮预测出 trigger 的 event type 是 $t_i$,则把对应位置 $G_i^{trg}[t_i]$ 改成 1。为啥要这样设计呢?因为事实上,不同 type 的 trigger 之间是有一定关系的,比如如果出现 die 这件事,那么也非常有可能出现 attack 这件事。
- $G_i^{arg}\in R^{k\times {n_A}}$,存储 argument 之间的依赖关系。$G^{arg}[j][a] = 1$ 表示 $w_i$ 是 trigger,且 $e_j$ 是 $w_i$ 的 argument,且 $e_j$ 的 argument role 是 $a$。同理,如果这一轮预测出 argument role 是 $a$,就把相应位置改成 1。为啥要这样设计呢?作者在设计的时候只是为了凑数,或者说把可能有用的都搞一下而已。事实上这是没有的,这个将在第四部分详述。
- $G_i^{arg/trg}\in R^{k\times {n_T}}$,存储 trigger 和 argument 之间的依赖关系。$G^{arg/trg}[j][t] = 1$ 表示 $e_j$ 是 argument,且其所属的 trigger 的 type 是 $t$。如果这一轮预测出 trigger type 是 $t$,就把所有的 $G_i^{arg/trg}[j][t],j=1…k$ 都设成 1。这个我感觉设计的比较奇怪,但是事实证明这样是最好的(…?)
4 实验及结果
- 对于不同的 $G$,作者对比了三种 $G$ 用不用排列组合的 $2^3=8$ 种情况,发现只用 $G^{arg/trg}$ 的效果是最好的,其次是啥都不用,其他的两个不管怎么排列组合,都是负作用。只用 $G^{arg/trg}$ 和比啥都不用在 trigger 任务上差不多,在 argument 任务上 大幅提升。作者就得出结论,trigger 和 argument 之间的依赖关系是非常强的。(可是我寻思,你这直接把整行都置 1 了,也没体现 argument 和 trigger 的关系哇?)
- 对于一开始不同的 embedding,具体来说就说 CBOW、Skip-Gram 和 C-CBOW 之间相比,C-CBOW 最好。作者大胆推测,这是因为它输入的更多了,提供的信息更多就让结果更好。我觉得更精确地来讲,就是如果只是 CBOW,那输出只跟邻居有关,C-CBOW 使得在邻居一样的情况下,中心词不也一样,embedding 也不太一样,就更精确一点?
- 跟之前的 SOTA 相比,JRNN 只在 f1 上是 SOTA。不过要比之前的 joint 方法有很大的提升。作者就得出结论,RNN 很有用。
- 在一句话有多个 event 的情况里,JRNN 比其他所有方法都强得多,trigger 任务比 DMCNN 高出 14%,argument 任务比 DMCNN 高出 6.5%。可惜在单 event 的argument 任务不敌 DMCNN,作者说这是因为没引入相对位置,而且 $G^{arg/trg}$ 在这种情况也没用上。
5 总结
这是我精度的第二篇事件抽取论文,这样我就大概了解了事件抽取的 pipeline 和 joint 方法。我感觉 trigger 和 argument 的双向关系是 pipeline 方法无法企及的,因此 joint 方法更有前途?这俩就跟深度聚类里 AE + fine-tune 和 基于特定损失 这两类方法类似,还是有一个全局的优化目标好啊!
6 引用
[1] Qi Li, Heng Ji, Liang Huang, “Joint Event Extraction via Structured Prediction with Global Features”, ACL 2013
[mathjax]
我认为$G^{arg/trg}$本质上是指明了句子中的argument属于哪个trigger,而那些other words就缺少了这个约束,所以可以提高效果。