guog算法笔记

V1

2023/04/06阅读:17主题:默认主题

基于Brat标注数据集的python包network网络构建和搜索

@

    一、前言

      在知识图谱的文本标注任务中,需要将数据按照事先决定的标注规则进行人工标注。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 )

    分类:

    人工智能

    标签:

    人工智能

    作者介绍

    guog算法笔记
    V1