语义角色标注
背景介绍¶
自然语言分析技术大致分为三个层面:词法分析、句法分析和语义分析。
语义角色标注是实现浅层语义分析的一种方式。
在一个句子中,谓词是对主语的陈述或说明,指出“做什么”、“是什么”或“怎么样,代表了一个事件的核心,跟谓词搭配的名词称为论元。
语义角色是指论元在动词所指事件中担任的角色。主要有:施事者(Agent)、受事者(Patient)、客体(Theme)、经验者(Experiencer)、受益者(Beneficiary)、工具(Instrument)、处所(Location)、目标(Goal)和来源(Source)等。
请看下面的例子,“遇到” 是谓词(Predicate,通常简写为“Pred”),“小明”是施事者(Agent),“小红”是受事者(Patient),“昨天” 是事件发生的时间(Time),“公园”是事情发生的地点(Location)。
语义角色标注(Semantic Role Labeling,SRL)以句子的谓词为中心,不对句子所包含的语义信息进行深入分析,只分析句子中各成分与谓词之间的关系,即句子的谓词(Predicate)- 论元(Argument)结构,
并用语义角色来描述这些结构关系,是许多自然语言理解任务(如信息抽取,篇章分析,深度问答等)的一个重要中间步骤。
在研究中一般都假定谓词是给定的,所要做的就是找出给定谓词的各个论元和它们的语义角色。
传统的SRL系统大多建立在句法分析基础之上,通常包括5个流程:
- 构建一棵句法分析树,例如,图1是对上面例子进行依存句法分析得到的一棵句法树。
- 从句法树上识别出给定谓词的候选论元。
- 候选论元剪除;一个句子中的候选论元可能很多,候选论元剪除就是从大量的候选项中剪除那些最不可能成为论元的候选项。
- 论元识别:这个过程是从上一步剪除之后的候选中判断哪些是真正的论元,通常当做一个二分类问题来解决。
- 对第4步的结果,通过多分类得到论元的语义角色标签。可以看到,句法分析是基础,并且后续步骤常常会构造的一些人工特征,这些特征往往也来自句法分析。
图1. 依存句法分析句法树示例
然而,完全句法分析需要确定句子所包含的全部句法信息,并确定句子各成分之间的关系,是一个非常困难的任务,目前技术下的句法分析准确率并不高,句法分析的细微错误都会导致SRL的错误。
为了降低问题的复杂度,同时获得一定的句法结构信息,“浅层句法分析”的思想应运而生。
浅层句法分析也称为部分句法分析(partial parsing)或语块划分(chunking)。
和完全句法分析得到一颗完整的句法树不同,浅层句法分析只需要识别句子中某些结构相对简单的独立成分,例如:动词短语,这些被识别出来的结构称为语块。
为了回避 “无法获得准确率较高的句法树” 所带来的困难,一些研究[1]也提出了基于语块(chunk)的SRL方法。
基于语块的SRL方法将SRL作为一个序列标注问题来解决。
序列标注任务一般都会采用BIO表示方式来定义序列标注的标签集。
我们继续以上面的这句话为例,图2展示了BIO表示方法。
图2. BIO标注方法示例
从上面的例子可以看到,根据序列标注结果可以直接得到论元的语义角色标注结果,是一个相对简单的过程。
这种简单性体现在:(1)依赖浅层句法分析,降低了句法分析的要求和难度;(2)没有了候选论元剪除这一步骤;(3)论元的识别和论元标注是同时实现的。
这种一体化处理论元识别和论元标注的方法,简化了流程,降低了错误累积的风险,往往能够取得更好的结果。
与基于语块的SRL方法类似,在本教程中我们也将SRL看作一个序列标注问题,不同的是,我们只依赖输入文本序列,不依赖任何额外的语法解析结果或是复杂的人造特征,利用深度神经网络构建一个端到端学习的SRL系统。
我们以CoNLL-2004 and CoNLL-2005 Shared Tasks任务中SRL任务的公开数据集为例,实践下面的任务:
给定一句话和这句话里的一个谓词,通过序列标注的方式,从句子中找到谓词对应的论元,同时标注它们的语义角色。
模型概览¶
这一篇中我们依然利用LSTM来解决SRL问题。
栈式循环神经网络(Stacked Recurrent Neural Network)¶
深层网络有助于形成层次化特征,网络上层在下层已经学习到的初级特征基础上,形成更复杂的高级特征。
尽管LSTM沿时间轴展开后等价于一个非常“深”的前馈网络,但由于LSTM各个时间步参数共享,t−1时刻状态到t时刻的映射,始终只经过了一次非线性映射,也就是说单层LSTM对状态转移的建模是 “浅” 的。
堆叠多个LSTM单元,令前一个LSTMt时刻的输出,成为下一个LSTM单元t时刻的输入,帮助我们构建起一个深层网络,我们把它称为第一个版本的栈式循环神经网络。
深层网络提高了模型拟合复杂模式的能力,能够更好地建模跨不同时间步的模式[2]。
然而,训练一个深层LSTM网络并非易事。
纵向堆叠多个LSTM单元可能遇到梯度在纵向深度上传播受阻的问题。
通常,堆叠4层LSTM单元可以正常训练,当层数达到4~8层时,会出现性能衰减,这时必须考虑一些新的结构以保证梯度纵向顺畅传播,这是训练深层LSTM网络必须解决的问题。
我们可以借鉴LSTM解决 “梯度消失梯度爆炸” 问题的智慧之一:在记忆单元(Memory Cell)这条信息传播的路线上没有非线性映射,当梯度反向传播时既不会衰减、也不会爆炸。
因此,深层LSTM模型也可以在纵向上添加一条保证梯度顺畅传播的路径。
一个LSTM单元完成的运算可以被分为三部分:
(1)输入到隐层的映射(input-to-hidden) :每个时间步输入信息x会首先经过一个矩阵映射,再作为遗忘门,输入门,记忆单元,输出门的输入,注意,这一次映射没有引入非线性**;
(2)隐层到隐层的映射(hidden-to-hidden):这一步是LSTM计算的主体,包括遗忘门,输入门,记忆单元更新,输出门的计算;
(3)隐层到输出的映射(hidden-to-output):通常是简单的对隐层向量进行**。
我们在第一个版本的栈式网络的基础上,加入一条新的路径:
除上一层LSTM输出之外,将前层LSTM的输入到隐层的映射作为的一个新的输入,同时加入一个线性映射去学习一个新的变换。
图3是最终得到的栈式循环神经网络结构示意图。
图3. 基于LSTM的栈式循环神经网络结构示意图
双向循环神经网络(Bidirectional Recurrent Neural Network)¶
在LSTM中,t时刻的隐藏层向量编码了到t时刻为止所有输入的信息,但t时刻的LSTM可以看到历史,却无法看到未来。
在绝大多数自然语言处理任务中,我们几乎总是能拿到整个句子。
这种情况下,如果能够像获取历史信息一样,得到未来的信息,对序列学习任务会有很大的帮助。
为了克服这一缺陷,我们可以设计一种双向循环网络单元,它的思想简单且直接:
对上一节的栈式循环神经网络进行一个小小的修改,堆叠多个LSTM单元,让每一层LSTM单元分别以:正向、反向、正向 …… 的顺序学习上一层的输出序列。
于是,从第2层开始,t时刻我们的LSTM单元便总是可以看到历史和未来的信息。
图4是基于LSTM的双向循环神经网络结构示意图。
图4. 基于LSTM的双向循环神经网络结构示意图
条件随机场 (Conditional Random Field)¶
使用神经网络模型解决问题的思路通常是:
前层网络学习输入的特征表示,网络的最后一层在特征基础上完成最终的任务。
在SRL任务中,深层LSTM网络学习输入的特征表示,条件随机场(Conditional Random Filed, CRF)在特征的基础上完成序列标注,处于整个网络的末端。
CRF是一种概率化结构模型,可以看作是一个概率无向图模型,结点表示随机变量,边表示随机变量之间的概率依赖关系。
简单来讲,CRF学习条件概率P(X|Y),其中 X=(x1,x2,...,xn) 是输入序列,Y=(y1,y2,...,yn) 是标记序列;解码过程是给定 X序列求解令P(Y|X)最大的Y序列,即Y∗=arg maxYP(Y|X)。
序列标注任务只需要考虑输入和输出都是一个线性序列,并且由于我们只是将输入序列作为条件,不做任何条件独立假设,因此输入序列的元素之间并不存在图结构。
综上,在序列标注任务中使用的是如图5所示的定义在链式图上的CRF,称之为线性链条件随机场(Linear Chain Conditional Random Field)。
图5. 序列标注任务中使用的线性链条件随机场
根据线性链条件随机场上的因子分解定理[5],在给定观测序列X时,一个特定标记序列Y的概率可以定义为:
其中Z(X)是归一化因子,tj 是定义在边上的特征函数,依赖于当前和前一个位置,称为转移特征,表示对于输入序列X及其标注序列在 i及i−1位置上标记的转移概率。
sk是定义在结点上的特征函数,称为状态特征,依赖于当前位置,表示对于观察序列X及其i位置的标记概率。
λj 和 μk 分别是转移特征函数和状态特征函数对应的权值。
实际上,t和s可以用相同的数学形式表示,再对转移特征和状态特在各个位置i求和有:fk(Y,X)=∑ni=1fk(yi−1,yi,X,i),把f统称为特征函数,于是P(Y|X)可表示为:
ω是特征函数对应的权值,是CRF模型要学习的参数。
训练时,对于给定的输入序列和对应的标记序列集合D=[(X1,Y1),(X2,Y2),...,(XN,YN)] ,通过正则化的极大似然估计,求解如下优化目标:
这个优化目标可以通过反向传播算法和整个神经网络一起求解。
解码时,对于给定的输入序列X,通过解码算法(通常有:维特比算法、Beam Search)求令出条件概率P¯(Y|X)最大的输出序列 Y¯。
深度双向LSTM(DB-LSTM)SRL模型¶
在SRL任务中,输入是 “谓词” 和 “一句话”,目标是从这句话中找到谓词的论元,并标注论元的语义角色。
如果一个句子含有n个谓词,这个句子会被处理n次。
一个最为直接的模型是下面这样:
- 构造输入;
- 输入1是谓词,输入2是句子
- 将输入1扩展成和输入2一样长的序列,用one-hot方式表示;
- one-hot方式的谓词序列和句子序列通过词表,转换为实向量表示的词向量序列;
- 将步骤2中的2个词向量序列作为双向LSTM的输入,学习输入序列的特征表示;
- CRF以步骤3中模型学习到的特征为输入,以标记序列为监督信号,实现序列标注;
大家可以尝试上面这种方法。
这里,我们提出一些改进,引入两个简单但对提高系统性能非常有效的特征:
- 谓词上下文:上面的方法中,只用到了谓词的词向量表达谓词相关的所有信息,这种方法始终是非常弱的,特别是如果谓词在句子中出现多次,有可能引起一定的歧义。从经验出发,谓词前后若干个词的一个小片段,能够提供更丰富的信息,帮助消解歧义。于是,我们把这样的经验也添加到模型中,为每个谓词同时抽取一个“谓词上下文” 片段,也就是从这个谓词前后各取n个词构成的一个窗口片段;
- 谓词上下文区域标记:为句子中的每一个词引入一个0-1二值变量,表示它们是否在“谓词上下文”片段中;
修改后的模型如下(图6是一个深度为4的模型结构示意图):
- 构造输入
- 输入1是句子序列,输入2是谓词序列,输入3是谓词上下文,从句子中抽取这个谓词前后各n个词,构成谓词上下文,用one-hot方式表示,输入4是谓词上下文区域标记,标记了句子中每一个词是否在谓词上下文中;
- 将输入2~3均扩展为和输入1一样长的序列;
- 输入1~4均通过词表取词向量转换为实向量表示的词向量序列;其中输入1、3共享同一个词表,输入2和4各自独有词表;
- 第2步的4个词向量序列作为双向LSTM模型的输入;LSTM模型学习输入序列的特征表示,得到新的特性表示序列;
- CRF以第3步中LSTM学习到的特征为输入,以标记序列为监督信号,完成序列标注;
图6. SRL任务上的深层双向LSTM模型
数据介绍¶
在此教程中,我们选用CoNLL 2005SRL任务开放出的数据集作为示例。
需要特别说明的是,CoNLL 2005 SRL任务的训练数集和开发集在比赛之后并非免费进行公开,目前,能够获取到的只有测试集,包括Wall Street Journal的23节和Brown语料集中的3节。
在本教程中,我们以测试集中的WSJ数据为训练集来讲解模型。
但是,由于测试集中样本的数量远远不够,如果希望训练一个可用的神经网络SRL系统,请考虑付费获取全量数据。
原始数据中同时包括了词性标注、命名实体识别、语法解析树等多种信息。
本教程中,我们使用test.wsj文件夹中的数据进行训练和测试,并只会用到words文件夹(文本序列)和props文件夹(标注结果)下的数据。
标注信息源自Penn TreeBank[7]和PropBank[8]的标注结果。
PropBank标注结果的标签和我们在文章一开始示例中使用的标注结果标签不同,但原理是相同的,关于标注结果标签含义的说明,请参考论文[9]。
原始数据需要进行数据预处理才能被PaddlePaddle处理,预处理包括下面几个步骤:
- 将文本序列和标记序列其合并到一条记录中;
- 一个句子如果含有n个谓词,这个句子会被处理n次,变成n条独立的训练样本,每个样本一个不同的谓词;
- 抽取谓词上下文和构造谓词上下文区域标记;
- 构造以BIO法表示的标记;
- 依据词典获取词对应的整数索引。
预处理完成之后一条训练样本数据包含9个域,分别是:句子序列、谓词、谓词上下文(占 5 列)、谓词上下区域标志、标注序列。下表是一条训练样本的示例。
句子序列 | 谓词 | 谓词上下文(窗口 = 5) | 谓词上下文区域标记 | 标注序列 |
---|---|---|---|---|
A | set | n't been set . × | 0 | B-A1 |
record | set | n't been set . × | 0 | I-A1 |
date | set | n't been set . × | 0 | I-A1 |
has | set | n't been set . × | 0 | O |
n't | set | n't been set . × | 1 | B-AM-NEG |
been | set | n't been set . × | 1 | O |
set | set | n't been set . × | 1 | B-V |
. | set | n't been set . × | 1 | O |
除数据之外,我们同时提供了以下资源:
文件名称 | 说明 |
---|---|
word_dict | 输入句子的词典,共计44068个词 |
label_dict | 标记的词典,共计106个标记 |
predicate_dict | 谓词的词典,共计3162个词 |
emb | 一个训练好的词表,32维 |
我们在英文维基百科上训练语言模型得到了一份词向量用来初始化SRL模型。
在SRL模型训练过程中,词向量不再被更新。
我们训练语言模型的语料共有995,000,000个token,词典大小控制为4900,000词。
CoNLL 2005训练语料中有5%的词不在这4900,000个词中,我们将它们全部看作未登录词,用<unk>
表示。
这里需要特别说明的是,参数 hidden_dim = 512
实际指定了LSTM隐层向量的维度为128,关于这一点请参考PaddlePaddle官方文档中dynamic_lstm的说明。