使用CNN或者双向RNN加Attention的深度学习方法被认为是现在关系抽取state of art的解决方案。已有的文献和代码,大都是针对英文语料,使用词向量作为输入进行训练。这里以实践为目的,介绍一个用双向GRU、字与句子的双重Attention模型,以天然适配中文特性的字向量(character embedding)作为输入,网络爬取数据作为训练语料构建的中文关系抽取模型。
代码主要是基于清华的开源项目thunlp/TensorFlow-NRE开发,感谢!
双向GRU加字级别attention的模型想法来自文章 “Attention-Based Bidirectional Long Short-Term Memory Networks for Relation Classification” [Zhou et al.,2016]。这里将原文的模型结构中的LSTM改为GRU,且对句子中的每一个中文字符输入为character embedding。这样的模型对每一个句子输入做训练,加入字级别的attention。
句子级别attention的想法来自文章 “Neural Relation Extraction with Selective Attention over Instances” [Lin et al.,2016]。原文模型结构图如下,这里将其中对每个句子进行encoding的CNN模块换成上面的双向GRU模型。这样的模型对每一种类别的句子输入做共同训练,加入句子级别的attention。
中文关系抽取的公开语料比较少。我们从distant supervision的方法中获取灵感,希望可以首先找到具有确定关系的实体对,然后再去获取该实体对共同出现的语句作为正样本。负样本则从实体库中随机产生没有关系的实体对,再去获取这样实体对共同出现的语句。
一个小问题是,相同的关系label在复旦知识工厂中可能对应着不同的标注,比如“夫妻”,抓取到的数据里有的是“丈夫”,有的是“妻子”,有的是“伉俪”等等,需要手动对齐。
得到实体对,获取实体对共同出现的语句,我们直接借助百度、搜狐、360等的新闻搜素功能,抓取实体对共同出现的新闻在搜索列表中的摘要。
我们还从一个开源项目Roshanson/TextInfoExp中获取了不少关系抽取语料。
AI项目体验地址 https://loveai.tech
1.所有数据准备在 origin_data/ 中, 包括了关系种类 (relation2id.txt), 训练数据 (train.txt), 测试数据 (test.txt) and 中文字向量 (vec.txt). 中文字向量是在中文wikipedia上训练的。训练数据和测试数据是将原始数据随机排序,然后按大概80%做训练,20%做测试的方法分开。更好的方法是再加入验证数据,但是训练一个epoch已经好长时间,就偷个懒不搞k-fold什么的了。。。
unknown, 父母, 夫妻, 师生, 兄弟姐妹, 合作, 情侣, 祖孙, 好友, 亲戚,
2.将所有数据通过字向量整理成numpy的形式,存储在 data/
python initial.py
3.进行训练,模型会存储在 model/。并没有怎么仔细调节超参数,模型结构除了字向量的输入以外,也是完全照搬英文版的模型。感兴趣的朋友们以这个结果为baseline可以尝试调出更好的模型参数。
python train_GRU.py
python test_GRU.py
代码中有两个main函数。第一个main函数是用测试数据来测试准确率的(我的实验大概70%左右),第二个则是供用户输入数据进行inference。程序会在command line中提示输入”name1 name2 sentence”格式的测试数据。
我们请来王大牛和李晓华两位同学来做角色扮演,测试了一些例子。
可以看到模型给出的结果还是蛮有趣的,有一些错误,但也是“情有可原”的合理。
回顾整个过程,对于中文关系提取这个比较复杂的任务,我们的方法完全没有构造n-gram、词性、依存句法等复杂特征,使用深度学习模型,甚至不需要中文分词,只依靠字向量和大量训练语料就得到了一个效果不错的端到端模型。