知识图谱关系抽取与总结展望

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识图谱关系抽取与总结展望相关的知识,希望对你有一定的参考价值。

实验介绍

在上一节的实验中【知识图谱】命名实体识别(NLP)我们学习了如何将实体文本中抽取出来,在实体抽取出来之后得到的是离散节点,为了构成网状的知识,还需要从文本中提取实体之间的关系。

因此,本实验中将学习如何从文本中抽取实体之间的关系

在本实验中,你将掌握:

  • 关系抽取任务的定义与理论解决方法
  • 关系抽取任务中数据集处理方法
  • 关系抽取模型——PCNN 的理论知识
  • 用 Keras 构建 PCNN
  • PCNN 的训练与预测方法

实验原理

关系抽取任务

在本实验中,我们关心的是有监督关系抽取任务,即已知所有文本中包含的关系种类。此时关系抽取的任务形式就是一个文本分类的问题——任务的输入是一句话以及这句话中包含的两个实体,输出是关系类别

如文本 “杨康,杨铁心与包惜弱之子,金国六王爷完颜洪烈的养子。” 中,一共有四个人名实体,要获得 “杨康”与“杨铁心” 的关系,那么就要把 “杨康”,“杨铁心”,“杨康,杨铁心与包惜弱之子,金国六王爷完颜洪烈的养子。” 这三个数据都输入到算法中。

数据预处理

首先对数据进行位置编码,按句子中各个词离实体的距离进行编码。 如 “杨康,杨铁心与包惜弱之子,金国六王爷完颜洪烈的养子。” 中,实体为“杨康”和“杨铁心”。然后记录句子中每个实体首字之间的距离。

杨	康	,	杨	铁	心	与	包	惜	弱	之	子	,	金	国	六	王	爷	完	颜	洪	烈	的	养	子	。
0	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18	19	20	21	22	23	24	25

pos_1=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],0 就是杨康的起始位置

杨	康	,	杨	铁	心	与	包	惜	弱	之	子	,	金	国	六	王	爷	完	颜	洪	烈	的	养	子	。
-3	-2	-1	0	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18	19	20	21	22

pos_2=[-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],0 就是杨铁心的起始位置

实验步骤

先安装需要的包

pip install tensorflow==1.13.1
pip install keras==2.1.6

Tensorflow 2.0 最新版(2.4.1) 安装教程

数据处理

原始文本和标签定义为:

# 对于 lists 中每一个子列表,第一个元素为实体1,第二个元素为实体2,第三个元素为实体1对实体2的关系,第四个元素为文本。
lists = [['杨康','杨铁心','子女','杨康,杨铁心与包惜弱之子,金国六王爷完颜洪烈的养子。'],
         ['杨康','杨铁心','子女','丘处机与杨铁心、郭啸天结识后,以勿忘“靖康之耻”替杨铁心的儿子杨康取名。'],
         ['杨铁心','包惜弱','配偶','金国六王爷完颜洪烈因为贪图杨铁心的妻子包惜弱的美色,杀害了郭靖的父亲郭啸天。'],
         ['杨铁心','包惜弱','配偶','杨康,杨铁心与包惜弱之子,金国六王爷完颜洪烈的养子。'],
         ['张翠山','殷素素','配偶','张无忌,武当七侠之一张翠山与天鹰教紫微堂主殷素素之子。'],
         ['小龙女','杨过','师傅','小龙女是杨过的师父,与杨过互生情愫,但因师生恋不容于世。'],
         ['黄药师','黄蓉','父','黄药师,黄蓉之父,对其妻冯氏(小字阿衡)一往情深。'],
         ['郭啸天','郭靖','父','郭靖之父郭啸天和其义弟杨铁心因被段天德陷害,死于临安牛家村。']]

relation2idx = {'子女':0,'配偶':1,'师傅':2,'父':3}

lists, relation2idx

首先,我们先将 lists 中的实体、关系与文本都单独拆分开来,并对文本进行位置编码。

datas, labels, pos_list1, pos_list2 = [], [], [], []
translation = 32
for entity1, entity2, relation, text in lists:
    # 找到第一个实体出现的下标
    idx1 = text.index(entity1)
    # 找到第二个实体出现的下标
    idx2 = text.index(entity2)
    sentence, pos1, pos2 = [], [], []
    for i, w in enumerate(text):
        sentence.append(w)
        # 计算句子中每个字与实体1首字的距离
        pos1.append(i-idx1+translation)
        # 计算句子中每个字与实体2首字的距离
        pos2.append(i-idx2+translation)
    datas.append(sentence)
    labels.append(relation2idx[relation])
    pos_list1.append(pos1)
    pos_list2.append(pos2)

datas, labels, pos_list1, pos_list2
from collections import Counter
# 统计每个字出现的次数, sum(datas,[]) 的功能是将列表铺平
word_counts = Counter(sum(datas, []))
# 建立字典表,只记录出现次数不小于 2 的字
vocab = [w for w, f in iter(word_counts.items()) if f >= 2]
word_counts, vocab
# 构建词袋模型,和上一节实验相同,将字典从 2 开始编号,把 0 和 1 空出来,0 作为填充元素,1 作为不在字典中的字的编号
word2idx = dict((w,i+2) for i,w in enumerate(vocab))
word2idx
import numpy as np
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical

# 构建输入,即对于样本中每一个字,从词袋模型中找到这个字对应的 idx,出现频率过低的字,并没有出现在词袋模型中,此时将这些字的 idx 取为 1
train_x = [[word2idx.get(w, 1) for w in s] for s in datas]

max_len = 64

# 在输入的左边填充 0
train_x = pad_sequences(train_x, max_len, value=0)
## 填充位置编码
train_pos1 = pad_sequences(pos_list1, max_len, value=0)
train_pos2 = pad_sequences(pos_list2, max_len, value=0)
# one_hot 编码 label
train_y = to_categorical(labels, num_classes=len(relation2idx))

train_x.shape, train_y.shape, train_pos1.shape, train_pos2.shape

构建网络模型

因为网络有多个输入:文本与位置编码,属于复杂模型,因此我们这里使用 Keras 的函数式 API 来定义网络结构

from keras.layers import Input, Embedding, concatenate, Conv1D, GlobalMaxPool1D, Dense, LSTM
from keras.models import Model

# 定义输入层
words = Input(shape=(max_len,),dtype='int32')
position1 = Input(shape=(max_len,),dtype='int32')
position2 = Input(shape=(max_len,),dtype='int32')
#  Embedding 层将输入进行编码
pos_emb1 = Embedding(output_dim=16, input_dim=256)(position1)
pos_emb2 = Embedding(output_dim=16, input_dim=256)(position2)
word_emb = Embedding(output_dim=16, input_dim=256)(words)
# 分别拼接 文本编码与位置1 和文本编码与位置2
concat1 = concatenate([word_emb, pos_emb1])
concat2 = concatenate([word_emb, pos_emb2])
# 卷积池化层
conv1 = Conv1D(filters=128, kernel_size=3)(concat1)
pool1 = GlobalMaxPool1D()(conv1)
conv2 = Conv1D(filters=128, kernel_size=3)(concat2)
pool2 = GlobalMaxPool1D()(conv2)
# 拼接,最后接全连接层,激活函数为 softmax
concat = concatenate([pool1, pool2])
out = Dense(units=len(relation2idx),activation='softmax')(concat)

model = Model(inputs=[words, position1, position2],outputs=out)
# 编译模型
model.compile(optimizer='ADAM', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
# 训练 50 次
model.fit([train_x, train_pos1, train_pos2], train_y, batch_size=8, epochs=50)
model.save('model.h5')

模型预测

在这里我们使用训练集中的一个实例进行预测

test_instance = ['张翠山','殷素素','张无忌,武当七侠之一张翠山与天鹰教紫微堂主殷素素之子。']
test_ne1, test_ne2, test_text = test_instance
test_ne1, test_ne2, test_text
# 将预测数据转换为向量
pred_x = [word2idx.get(w, 1) for w in test_text]
idx1 = test_text.index(test_ne1)
idx2 = test_text.index(test_ne2)
pos1 = [i-idx1+translation for i in range(len(test_text))]
pos2 = [i-idx2+translation for i in range(len(test_text))]
pred_x = pad_sequences([pred_x], max_len, value=0)
test_pos1 = pad_sequences([pos1], max_len, value=0)
test_pos2 = pad_sequences([pos2], max_len, value=0)
pred_x, test_pos1, test_pos2
# 翻转 relation2idx 字典
idx2relation = dict(zip(relation2idx.values(),relation2idx.keys()))
# 使用模型进行预测
pred = model.predict([pred_x, test_pos1, test_pos2])
# 模型预测最大值的位置作为预测值
output_idx = np.argmax(pred)
# 找到 idx2relation 中实际的标签
output_label = idx2relation[output_idx]
pred, output_idx, output_label

总结展望

在本实验中,我们了解了关系抽取任务的定义,并使用了一个小型的神经网络来实现关系抽取任务中的数据处理、训练与预测

由于小型的神经网络的参数量较少,拟合能力有限,从而随着训练数据量的增加就会出现欠拟合的现象。因此,用少量数据集在小型网络上训练完成后,再逐渐增大数据量,同时将小型网络复杂化,如使用现有的 PCNNAttention-BiLSTM 等用于关系抽取经典神经网络结构,将任务的精度提升到我们想要的结果。

展望未来

在本课程中,我们采用了“知识图谱是什么”,“知识图谱怎么用”,“知识图谱是怎么生成的”的顺序进行学习。

  • 第一步介绍了知识图谱的基本知识与构成,然后通过《射雕三部曲》中的人物图谱,来掌握 Neo4j 的使用方法,在掌握使用方法后,再学习操作 Neo4jCypher 语言与 Python 驱动 py2neo

  • 第二步则是学习如何通过结构化数据生成知识图谱,在本实验中使用了两种方法,load csvneo4j-import

  • 第三步是构建知识图谱最基础的一步,即提取结构化数据

实际应用

在实际的项目中,构建知识图谱的顺序正好与本课程相反,先要提取结构化数据,然后构建知识图谱,最后用 Cypher 语法进行查询。

结构化数据

结构化数据的过程中,除了会使用到本课程中的命名实体识别关系抽取外,还可能用到的技术有:

  1. 属性抽取

属性抽取主要是针对实体,通过属性来形成对实体的完整刻画。由于实体的属性可以看成是实体与属性值之间的一种名称关系,因此也可以将实体属性的抽取问题转换为关系抽取问题。

  1. 实体消歧

实体消歧用于解决同名实体产生的歧义,如在金庸小说《神雕侠侣》中有位女性角色“林朝英”,是古墓派的开山祖师,同时在古龙的小说中有一位男性角色叫做“林朝英”,因此需要通过实体消歧,根据当前语境,准确地建立实体链接

  1. 共指消解

共指消解实体消歧相反,主要用于解决多个称呼对应于同一实体对象的问题,如“靖哥哥”,“靖儿”,“郭靖”等指称都指向同一个实体对象

知识推理

知识推理则是在已有的知识库的基础上进一步挖掘隐含的知识,从而丰富、扩展知识库,如在知识库中存在两个三元组(郭啸天,父亲,郭靖),(郭靖,父亲,郭襄),那么就可以推理出(郭啸天,祖父,郭襄)。

知识推理的主要方法有基于逻辑的推理基于图的推理

应用领域

  1. 智能搜索

传统的搜索引擎,在一定程度上解决了用户从互联网中获取信息的难题,但由于它们是基于关键词字符串的,并没有对查询的目标(通常为网页)和用户的查询输入进行理解。例如,用户用自然语言搜索“谁会降龙十八掌”,智能搜索引擎能够理解用户的意图,并结合知识图谱以图文并茂的形式把答案“乔峰,洪七公,郭靖,宋青书”呈现给用户。

  1. 社交网络

Facebook 于 2013 年推出了 Graph Search 产品,其核心技术就是通过知识图谱将人,地点,事情等联系在一起形成一张社交网络,在新角色加入时,给新角色推荐社交网络中最相似的节点。比如构建完金庸角色的知识图谱后,问到“你认为你最像金庸武侠小说中哪一个人物?”时,就可以将自己转换为一个知识图谱,再去金庸角色的知识图谱中进行匹配,找到最相似的子图。

  1. 垂直行业应用
  • 金融行业
    金融知识图谱,可以为风险评估、预测、反欺诈、精准营销、智能搜索和数据可视化等提供技术支撑。越来越多的金融机构及企业在探索构建金融领域的知识图谱研究,将海量非结构化信息自动化利用起来,为金融领域应用决策提供更精准、更可靠的依据。

  • 医疗行业
    随着医疗大数据时代的到来,如何从海量的数据中提取有用的医学知识,是医疗大数据分析的关键。知识图谱技术提供了一种从海量文本图像中抽取结构化知识的手段,如病历结构化,临床决策支持系统,全科机器人医生等。

知识图谱的重要性不仅在于它是一个全局知识库,是支撑智能搜索深度问答等智能应用的基础,而且在于它是一把钥匙,能够打开人类的知识宝库,为许多相关学科领域开启新的发展机会。从这个意义上来看,知识图谱不仅是一项技术,更是一项战略资产。本课程的主要目的是介绍和宣传这项技术,希望吸引更多人重视和投入这项研究工作。

参考文献

刘峤,李杨,段宏,刘瑶,秦志光.知识图谱构建技术综述[J].计算机研究与发展,2016,53(03):582-600.

徐增林,盛泳潘,贺丽荣,王雅芳.知识图谱技术综述[J].电子科技大学学报,2016,45(04):589-606.

医疗-开放知识图谱

All Link

【知识图谱】构建射雕三部曲人物关系

【知识图谱】Linux安装Neo4j图数据库

【知识图谱】neo4j.conf 配置文件解读说明

【知识图谱】Neo4j基本操作及数据库文件导入

【知识图谱】Neo4j Cypher查询语言详解

【知识图谱】Python.py2neo操作Neo4j

【知识图谱】构建《射雕三部曲》图谱(CSV文件)

【知识图谱】深度学习:Keras 初探

【知识图谱】命名实体识别(NLP)

【知识图谱】关系抽取与总结展望

以上内容摘自蓝桥云课,感谢其带领我初识知识图谱,希望随着学习的深入,我可以有更大的理解与进步。

加油!

以上是关于知识图谱关系抽取与总结展望的主要内容,如果未能解决你的问题,请参考以下文章

知识图谱抽取总结

小麦知识图谱三元组构建

知识图谱关系抽取

知识图谱关系抽取

KG美团知识图谱问答技术实践与探索

利用关系抽取构建知识图谱的一次尝试