@TOC
一、前言
在知识图谱的文本标注任务中,需要将数据按照事先决定的标注规则进行人工标注。Brat是一种比较著名的标注工具,但是目前不支持Windows系统,你可以安装虚拟机使用该工具。本文已经完成了一项基于Windows、Python3.7的标注软件制作工作,你可以点击 实体关系文本标注工具 进行查看。
倘若你是使用的Brat标注工具, 并且对于Neo4j图数据库不是很熟悉,那你可以考虑使用Python中的network第三方库,在初步学习阶段实现demo,在下一篇文章中,将会介绍Neo4j的使用案例。
本文将使用Brat工具标注的数据集,利用network第三方库构建图网络,并且实现对节点的多级检索。
二、数据准备
本文从知网下载了一些关于医学文章的摘要,提前设置了标注规则,例如实体类别、关系等。通过Brat工具标注该文本数据并得到输出标注好的结果文件,该文件共有1314行,以T开头表示实体,以R开头表示关系,该文件是对网络图结构的文本表述。
三、网络构建
1、准备好一些必备的包,本文使用的是python3.7版本。
import re
import networkx as nx
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
2、读取数据
txtfile = open(r'E:数据1-70.ann', 'r', encoding='utf-8').readlines()
# print(txtfile[:3])
3、将文件中的实体、关系区分开
#将实体与关系数据分开
entity = []
relation = []
for i in txtfile:
if i[0] == 'T':
entity.append(i)
else:
relation.append(i)
# print(relation)
#将实体名称、类别与编号提取出来
entity = [i.strip('n').split('t') for i in entity]
entity = [[i[0],i[1].split(' ')[0], i[-1]] for i in entity]
# print(entity[:5])
#在实体表中插入数据
# #提取实体名,去重;需要提前查看数据库已有的实体名称 需要表名称
entitymin = [i[-1] for i in entity]
entitymin = list(set(entitymin))
# print(entitymin[:5])
4、利用区分开的实体、关系,将三元组提取出来,构建三元组。
#将三元组提取出来
relation = [re.split("[tA:' ']",i) for i in relation]
relation = [[i[1],i[4],i[7]] for i in relation]
# print(relation[:5])
dicen = dict([('病症',1),('病名',2),('诊断方案',3),('治疗方案',4),('药名',5),('其它',6)])
dicre = dict([('包含',1),('治疗',2),('危险因素',3),('辅助诊断',4),('特征',5),('并发',6),('别名',7),('作用',8),('条件',9)])
# print(dicre['包含'])
# #将三元组中的实体编号替换成实体名称
for r in relation:
# r[0] = dicre[r[0]]
for e in entity:
if r[1] == e[0]:
r[1] = e[-1]
# r.insert(0,e[1])
if r[-1] == e[0]:
r[-1] = e[-1]
# r.append(e[1])
r.append(r[0])
# print(relation[:5])
relation = [tuple(r[1:]) for r in relation]
# print(relation[:5])
lista = []
for i in relation:
if i[-1] == '别名':
lista.append([i[1], i[0], i[-1]])
relation += lista
# print(lista)
# print(relation[:5])
5、利用network绘制图网络,并且将图网络保存到本地。
plt.figure(3, figsize=(48, 27)) # 这里控制画布的大小,可以说改变整张图的布局
plt.subplot(111)
M = nx.DiGraph()
M.add_weighted_edges_from(relation)
#传入数据,格式[('甲状腺疾病', '甲状腺功能亢进症', '包含'), ('甲状腺疾病', '甲状腺功能减退', '包含')]
edge_labels = nx.get_edge_attributes(M, 'weight') #取出实体之间的关系
pos = nx.random_layout(M)
# pos = nx.spring_layout(G, iterations=30) #设置画图的样式
nx.draw(M, pos,edge_color="grey", node_size=80) #设置点的位置
nx.draw_networkx_edge_labels(M,pos, edge_labels=edge_labels, font_size=10) #边的格式设置
nx.draw(M,pos, node_size=120, with_labels=True,font_size = 10) #节点设置
plt.savefig("imag.png")
plt.show()
生成结果,自动保存在本地,需要放大观看:
四、多级节点搜索
基于上面第5步绘制的网络,接下来本文需要从这个网络中,对感兴趣的节点和邻近节点,以及邻近节点的邻近节点到任意深度的节点进行检索。
1、定义查找函数
def get_neigbors(g, node, depth=1):
output = {}
output1 = []
layers = dict(nx.bfs_successors(g, source=node, depth_limit=depth))
nodes = [node]
for i in range(1,depth+1):
output[i] = []
for x in nodes:
output[i].extend(layers.get(x,[]))
output1.extend(layers.get(x,[]))
nodes = output[i]
print('这是节点:',output)
return output1##print(get_neigbors(M, '990', depth = 4))#[23,12,14,23,45,65,78]
def newlist(M, a, alist):
alist.insert(0,a)
newlistcon = list()
for index, name in enumerate(alist[:-1]):
for name1 in alist[index+1:]:
if M.get_edge_data(name,name1) != None:
relation = M.get_edge_data(name,name1)['weight']
newlistcon.append([name, name1, relation])
lista = []
for i in newlistcon:
if i[-1] == '别名':
lista.append([i[1], i[0], i[-1]])
newlistcon += lista
return newlistcon#print('这是新数据',newlist(M, '990', get_neigbors(M, '990', depth = 4)))
2、设置查找参数,例如:查找以“甲状腺疾病”节点,并且设置深度为2,返回所有与甲状腺疾病为邻近节点的节点,以及该邻近节点的邻近节点。
node,depth = '甲状腺疾病',2
3、绘图展示和结果输出
liststrnewcon = newlist(M, node, get_neigbors(M, node, depth = depth))
G = nx.DiGraph()
plt.figure(3, figsize=(32,18)) # 这里控制画布的大小,可以说改变整张图的布局
plt.subplot(111)
G.add_weighted_edges_from(liststrnewcon) #传入数据
edge_labels = nx.get_edge_attributes(G, 'weight') #取出实体之间的关系
# pos = nx.spring_layout(G, iterations=30) #设置画图的样式
pos = nx.random_layout(G)
# pos = nx.spectral_layout(G)
nx.draw(G, pos,edge_color="grey", node_size=80) #设置点的位置
nx.draw_networkx_edge_labels(G,pos, edge_labels=edge_labels, font_size=15) #边的格式设置
nx.draw(G,pos, node_size=1500,node_color = 'skyblue',node_shape = 's', with_labels=True,font_size = 15,edge_color = 'red') #节点设置
plt.savefig("imag_jia1.png")
plt.show()
对检索结果生成网络图,自动保存本地,方便放大观看:
输出结果:
这是节点: {1: [‘甲状腺功能亢进症’, ‘甲状腺功能减退’, ‘甲状腺炎’, ‘咽异常感觉’, ‘脏器’, ‘Graves病’, ‘桥本甲状腺炎’, ‘甲状腺功能减退症’, ‘自身免疫性甲状腺疾病’, ‘许特莱细胞瘤’, ‘甲状腺腺瘤’, ‘结节性甲状腺肿’, ‘甲状腺囊性变病’, ‘甲状腺功能’, ‘甲状腺过氧化物酶抗体’, ‘TPOAb’, ‘甲状腺球蛋白抗体’, ‘TGAb’, ‘甲状腺瘤’, ‘原发性甲状腺机能亢进症’, ‘甲状腺癌’, ‘甲状腺良性疾病’, ‘咽异感症’, ‘TRAb’, ‘TMAb’, ‘桥本病’, ‘甲亢’, ‘桥本’, ‘甲减’, ‘晚期妇女’, ‘妊娠中’, ‘孕中晚期’, ‘桥本氏甲状腺炎’, ‘单纯性甲状腺肿’, ‘甲状腺乳头状癌’, ‘甲状腺恶性肿瘤’, ‘重症肌无力’, ‘MG’], 2: [‘急性化脓性甲状腺炎’, ‘亚急性甲状腺炎’, ‘慢性淋巴细胞性甲状腺炎’, ‘甲状腺上皮细胞’, ‘AITD’, ‘钙化’, ‘砂粒体’, ‘肿瘤样病变’, ‘甲状腺功能异常’, ‘TPO-Ab’, ‘原发性甲减’, ‘甲状腺结节’, ‘多灶性癌’, ‘乳头状腺癌’, ‘滤泡癌’, ‘未分化和癌髓样癌’, ‘乳头状癌’, ‘TSH受体抗体’, ‘甲状腺微粒体抗体’, ‘特异性抗体’, ‘病率较高’, ‘TSH’, ‘FT3’, ‘FT4’, ‘LP(a)’, ‘血脂’, ‘CHO’, ‘LDL’, ‘ApoB’, ‘亚临床甲亢’, ‘甲状腺功能亢进’, ‘亚临床甲减’, ‘腺瘤’, ‘微小乳头状癌’]}
五、完整项目数据和代码
以下方式均可:
1、私信留言、文末评论你的邮箱,博主定期回复。
2、点击: GitHub-network 进行下载(或者访问:https://github.com/chenyiadam/network.git )
本文由mdnice多平台发布
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net