中文信息学会和百度等举办的2020语言与智能技术竞赛,我对关系抽取赛道的题目比较感兴趣,报名并参加了该赛题,查阅相关资料,笔者决定基础模型为Model(Bert+Multi-Head selection),一是之前对bert有些学习和利用,二是利用Multi-Head selection范式解决在一个Text中,抽取多实体多关系问题,此博客记录一下比赛研究过程,在关系抽取领域学习研究不到一年,希望在这次测评比赛中有所收获。
论文链接:Joint entity recognition and relation extraction as a multi-head selection problem
代码链接: multihead joint entity relation extraction
Abstract
现最好的实体识别和关系的联合抽取模型依然较强的依赖现有的自然语言处理工具,例如POS(词性标记器)和(dependency parsers)依赖关系解析器。所以联合模型的性能就取决于这些NLP处理工具抽取出特征的质量。然而对于不用的上下文来说,这些特征并不是准确的。在此片论文里作者提出了一种不需要人工或工具提取特征并且同时进行实体识别和关系抽取的联合神经网络模型。具体来说,用CRF在实体识别层建模,并且将关系抽取视为多头选择问题,为每一个实体识别潜在的多种关系,该模型优于此前使用的自动抽取特征模型。
1. Introduction
实体识别和关系抽取的重要性:两者的目的是从非结构化的文本中发现实体和关系的结构(三元组),这是信息抽取的核心问题,对知识库的填充和问答系统有重要的价值。
之前的联合模型严重的依赖手工制作的功能。神经网络的出现缓解了这一问题,但是仍然存在对NLP工具的依赖。 Miwa & Bansal在2016年提出的循环神经网络模型,该模型利用双向LSTM在实体上进行建模,利用依赖树信息对两个实体进行关系建模。依赖关系信息是使用外部依赖关系分析器提取的......bala....ba...la......(说了一堆模型意思是都存在一些缺陷,一是仅考虑了两个实体之间的关系,没有利用好整个句子对关系的影响,二是,在给每一个实体分配一种对应关系的假设中,没有考虑到实体对应的多种关系和关系对应多种实体的复杂性问题。ps:个人观点)
这篇论文的着力点是研究一个通用的联合模型,该模型同时执行实体识别和关系抽取任务,而且同时处理多个关系。该模型的有点总结:a.不依赖现有的自然语言处理工具;b. 同时提取一个句子中的实体和关系;c. 一个实体可以涉及多种关系;最后说明了在不同的数据集,不同领域不同语言上,与之前的联合抽取模型相比,该模型取得了最好的成绩。
2. Related work
在相关工作部分,作者按照命名实体识别(NER),关系抽取(RE)和联合模型(Joint Model)三个部分来介绍的。这个部分我在之前的博客中已经写过(博客链接),不再赘述。这里说一下此论文中的模型介绍。
在本次工作中,将框架的问题作为多头选择的问题,通过sigmod损失函数获取多个关系,并且使用CRF损失函数获取NER部分(实体)。这样,我们就能够独立地预测不互斥的类,而不是在令牌之间分配相等的概率值。
3. Joint model
模型的结构如上图所示,该模型能够同时识别实体(类型和边界),以及他们之间的所有可能关系。论文将联合关系抽取的问题表述为多头选择问题。这里的多头是指任何一个特定的实体都可能设计与其他实体的多重关系。模型包括:Embedding Layer,BiLSTM Layer,CRF Layer,Label Embedings,Sigmoid Layer,Heads Relations;
模型的输入为一句话单词的向量表示,BiLSTM Layer能够基于RNN利用上下文信息为每一个单词提取出一个更复杂的向量表示。然后CRF层和Sigmod层能够产生两种任务的输出,输出包含两层,一个是实体识别标签(例如,I-PER意思是识别在PER类别中的部分),另一个是集合,这个集合包括三元组的头实体标记和两个实体之间的关系(例如 {(Center, Works for), (Atlanta, Lives in)}),这里注意:因为我们假设的是基于标记(单词)的编码,所以这里让一个实体的最后一个单词作为实体的头部,以消除冗余,例如:John Smith和Disease Control Center,不是链接所有实体的标记,而是链接Smith,Works for,Center。同样,对于没有关系的情况,我们引入“N”标签,预测令牌本身作为头部。
3.1 Embedding layer
给定序列,词嵌入层的作用是将每一个单词映射成一个单词词向量。论文中使用预训练模型Word2vec(在本次测评比赛中,使用bert自带的预训练模型)。
在文本中,使用字符级词嵌入,这种字符级词嵌入通用于神经网络,这种类型的嵌入能够捕获形态特征,例如前缀后缀的特征问题。之前的论文中有实验证明,使用字符级词嵌入在NER任务的F1值提高了3%,在该论文中的模型中,也提高了2%的F1值。
如上图所示,['M','a','n']这个词以字符级送入到BiLSTM,两个向量(前向和反向)被级联后,是前向和反向LSTM的字符级向量,最后拼接成。
3.2 Bidirectional LSTM encoding layer
RNN通常被用来在序列数据的建模,并且成功应用到各种NLP任务中。在本次论文中,使用多层的LSTM(特殊的一种RNN),能够很好的捕获较长的依赖关系。采用双向的LSTM(BiLSTM)从左到右和从右到左进行编码。通过这样的方式,可以得到双向的信息,包括前向向量和反向向量步长为的输出,描述为:
3.3 Named entity recognition
这里将命名实体识别问题作为一个序列标注问题,类似于之前的联合模型。命名实体识别使用BIO(Beginning,Inside,O utside)编码方案。在一句话中,为每一个单词都进行BIO编码,这样就可以识别实体开始和结束的位置和类型。这里需要解释一下,BIO编码方式,‘B’来编码实体开始的位置,‘I’分配给属于实体的其他单词,若不是实体部分,那么标记为O。
Jhon | Smith | headed | the | Disease | Control | Center | in | Atlanta | . |
B-PER | I-PER | O | O | B-ORG | I-ORG | I-ORG | O | B-LOC | O |
在BiLSTM层之上使用Softmax或者CRF来计算每一个单词最有可能的实体标记,计算每一个单词的实体对应所有标记的每一个得分:
上角标被用来标记NER任务,是激活函数(例如:relu,tanh),,,,其中,是LSTM隐藏层的大小,是实体识别标签数,是BiLSTM层的宽度。计算给定的所有候选标记的概率:
这里,在这次工作中,仅对实体分类任务使用softmax方法,在给定边界的情况下预测实体类型(例如PER), CRF方法用于包含实体类型和边界识别的NER任务(即在预测实体类型之后使用)。
在softmax中,使用贪恋算法为每一个token word分配实体标记类型,即分配分数最大的实体标记类型给token word。尽管说在独立标记表示的假设下,会有助于实体分类任务(例如POS tagging)但是,当标记之间有着很强的依赖性时,这种假设就不是很合适了。举个例子,比如一个标记B-LOC后面就不可能接上I-PER。softmax是允许所谓local decision(对每一个单词标记),因为利用BiLSTM可以捕捉相邻单词的特征信息。在实体“Jhon Smith”中,‘Smith’的标记‘PER’有助于确定Jhon的标签类型为‘B-PER’。为了达到利用这种标签之间依赖关系,在NER中,使用一个线性链的CRF,CRF的应用在F1值上有1%的效果提升;
假设的各实体标记分数向量为:,实体标签的预测向量为:,CRF后的分数定义为:
其中,是单词的预测的标签分数,是一个平方(正方形)转换矩阵,这里每一个位置表示从一个实体标记类型转换到另一个实体标记类型的概率,简单举例:
B-PER | I-PER | O | |
B-PER | 0 | 0.9 | 0.1 |
I-PER | 0.4 | 0.1 | 0.5 |
O | 0.6 | 0 | 0.4 |
例如上表,识别B-PER后下一个还是B-PER的概率为0(这里的数值是我写的,当然在试验中是要通过训练来不断更新优化的)表示概率很小,而到I-PER的概率就比较高,这样在做实体类型识别的时候有很大的帮助。注:这里的之所以(p+2)是因为表示句子的起始标记和结束标记,然后,给定句子的每一个单词在所有给定标记的预测概率定义为:
得到预测概率向量后,通过Viterbe算法得到最高分数预测,我们通过最小化交叉熵损失L来训练softmax(用于EC任务)和CRF层(用于NER)。通过学习标签的embedding,将实体类别标签作为关系抽取层的输入,这种方法在F1上提高了1%。下一层的输入有两个:LSTM的输出状态和学习到的标签嵌入表示。对于来说,下一层的输入包括LSTM层的输出向量和标签嵌入(embedding),;
3.4 Relation extraction as multi-head selection
在关系抽取部分中关系抽取任务被视为多头选择问题,在本论文的模型一般公式中,每一个单词(token)可以与其他的单词(token)有多种关系。这里预测二元组,其中是头向量,是和每一个单词(token)相关联关系的向量。与 (Zhang et al., 2017)模型不同之处是:a.拓展到可以多头选取;b.头部和关系的决策是同时进行的;
给定一个序列和一个关系标签集合,目的是为了证明对于每一个token序列,最有可能的头向量和最可能的相关关系标签,计算和给定分数的公式:
上角标表示关系抽取任务, 是激活函数(例如:relu,tanh),,,,;是LSTM隐藏层的大小,b是标签嵌入(label embedding)的大小,是LSTM层的宽度;定义:
该公式表示选中作为和关系的概率。在训练中,最小化交叉熵损失函数:
其中,(关系),是的真实头向量和关系标签向量。训练过后,在训练之后,我们保持头部和关系标签的组合超过基于前二(上上个等式)等式中定义的估计联合概率的阈值。与其他联合模型不同,论文中该方法可以预测多个关系,考虑到类是独立的,而不是相互排斥的(对于不同类,概率不一定总和为1)。因此,联合实体和关系抽取任务中,应该计算最终损失为:;
下文说道的 Edmonds’ algorithm是在DREC数据集上展示结果使用,所以可能不会用到这个,这里就不赘述啦,后期用到再加上。
---------------------------------------- 后面讲述代码部分,近期更新--2020.04.08----------------------------
代码实现:
代码部分是以train_es.py文件的主函数部分展开叙述的!!!
1.配置文件和前期数据处理
if __name__ == "__main__":
checkInputs() #对运行python命令进行检查,这里需要输入三个argv
config=build_data(sys.argv[1]) #加载配置文件参数
这里举例说明一下build_data()函数,在该函数中的代码:
#build_data.py
config_file=parsers.read_properties(fname) #fname 配置文件名
self.filename_embeddings = config_file.getProperty("filename_embeddings") #加载词嵌入文件路径
self.filename_train=config_file.getProperty("filename_train") #加载训练集路径
self.filename_test=config_file.getProperty("filename_test") #加载测试集路径
self.filename_dev=config_file.getProperty("filename_dev") #加载dev集路径
....
该函数,首先是加载了程序的配置文件参数,read_properties类写在自定义的parsers.py文件中,getProperty()也是该类中的函数,功能是加载给定字符串的对应值,在config文件中格式是这样的:
在加载了一系列的例如batch_size,nepoch,learning_rate等等参数之后,同时在build_data.py中引用了utils和parsers.py的处理函数,对数据进行了处理,注意这里对数据的处理不是值在训练的过程中,加载了数据集,而是一些对数据的预处理工作,例如将数据分离(文本,关系标签,BIO等等)、根据word embedding将单词映射为50维度的向量等等,这里有几个重要的数据元素,以及其代表的含义如下:
名称 | 意义 | 举例 |
data_set_bio_tags | BIO标签集合,共九种; | B-Loc,B-Org,B-Other,B-Peop,I-Loc,I-Org,I-Other,I-Peop,O |
data_set_characters | 出现的字符集合; | a,b,c......,!,@,#,&.......,1,2,3....... |
data_set_ec_tags | 实体子类型标签集合,五种; | Loc,Org,Other,Peop,O |
data_set_relations | 关系标签集合,共六中; | Kill,Live_In,Located_In,N,Orgbased_In,Work_For |
wordvectors | 词向量集合; | 50dim,浮点类型 |
wordindices | 单词对应的词典id; | '<empty>':0 |
train_id_docs | 训练集对应的数据元素集合; | BIO_ids,embedding_ids,token_idsd等等 |
dev_id_docs | dev集对应的数据元素集合; | BIO_ids,embedding_ids,token_idsd等等 |
test_id_docs | test集对应的数据元素集合; | BIO_ids,embedding_ids,token_idsd等等 |
这里,对train_id_docs,dev_id_docs,test_id_docs进一步划分为以下元素,供给训练时候使用:
名称 | 意义 | 举例 |
BIO_ids | 每一条句子的每一个单词对应的BIO标记转换成data_set_bio_tags中对应的id; | [8,3,7.......] |
char_ids | 句子中,每个单词的字母对应的data_set_characters中的id; | [1,3,5] #这是一个三个字母的单词 |
token_ids | 每个单词对应的位置标记; | [1,2,3,4,5,6,7,8.......] |
ec_id | 每个单词的BIO子集词性对应的data_set_ec_tags中的id; | [1,4,4,1,1.....] |
heads | 该单词是否与其他位置的单词有关系,若有此处标记为其他单词的位置,反之标记自己的位置; | [0,1,2,3,4,5,7,7]#6位置与7位置的单词有关系对应 |
joint_ids | 根据此公式算出 heads[relIdx] * len(setofLabels) + relationIds[relIdx],这个元素结合了实体和关系的运算,在之后的训练中应该很有用; | head[index]在此处与该单词有关系的位置单词*len(setofLabels)关系标签集合长度为6+relationIds[relIdx]该单词对应的关系id值 eg:0*6 + 3 = 3 |
-------------------------------------------------------------------------2020.04.015-----------------------