知识图谱最简单的demo实现

news2024/11/22 15:14:31

一、简介

知识图谱整个建立过程可以分为以下几点:

数据处理
创建三元组
可视化展示

其中:

  • 数据预处理:分词、命名实体识别、语义角色识别、句法依存分析等
  • 创建三元组:需要根据命名实体识别、语义角色识别结果进行处理,建立规则生成三元组
  • 用用图数据库或者接触可视化工具进行展示

二、数据预处理

这里我们使用哈工大的开源工具包LTP进行展示

本文主要介绍整体流程,中间的技术细节,会在后面分章节展开

2.1 数据

我们自己创建一段文本
当然也可以导入文本,或者批量导入csv等格式的数据,为了简便我们使用一段话来展示。

text="苏轼是宋朝的著名文学家,黄庭坚是他的好朋友。苏轼擅长写词,而黄庭坚擅长写诗。他在常州去世。"

2.2 数据处理

LTP支持将全部处理流程进行pipeline执行,当然我们也可以选择分布执行,在后面技术章节会详细展开

#  分词 cws、词性 pos、命名实体标注 ner、语义角色标注 srl、依存句法分析 dep、语义依存分析树 sdp、语义依存分析图 sdpg
output = ltp.pipeline(text, tasks=["cws", "pos", "ner", "srl", "dep", "sdp", "sdpg"])

我们把output展开看一下

output
LTPOutput(cws=['苏轼', '是', '宋朝', '的', '著名', '文学家', ',', '黄庭坚', '是', '他', '的', '好', '朋友', '。', '苏轼', '擅长', '写', '词', ',', '而', '黄庭坚', '擅长', '写', '诗', '。', '他', '在', '常州', '去世', '。'], pos=['nh', 'v', 'nt', 'u', 'a', 'n', 'wp', 'nh', 'v', 'r', 'u', 'a', 'n', 'wp', 'nh', 'v', 'v', 'n', 'wp', 'c', 'nh', 'v', 'v', 'n', 'wp', 'r', 'p', 'ns', 'v', 'wp'], ner=[('Nh', '苏轼'), ('Nh', '黄庭坚'), ('Nh', '苏轼'), ('Nh', '黄庭坚'), ('Ns', '常州')], srl=[{'predicate': '是', 'arguments': [('A0', '苏轼'), ('A1', '宋朝的著名文学家')]}, {'predicate': '是', 'arguments': [('A0', '黄庭坚'), ('A1', '他的好朋友')]}, {'predicate': '擅长', 'arguments': [('A0', '苏轼'), ('A1', '写词')]}, {'predicate': '写', 'arguments': [('A1', '词')]}, {'predicate': '擅长', 'arguments': [('A0', '黄庭坚'), ('A1', '写诗')]}, {'predicate': '写', 'arguments': [('A1', '诗')]}, {'predicate': '去世', 'arguments': [('A0', '他'), ('ARGM-LOC', '在常州')]}], dep={'head': [2, 0, 6, 3, 6, 2, 2, 9, 2, 13, 10, 13, 9, 2, 16, 2, 16, 17, 16, 22, 22, 16, 22, 23, 2, 29, 29, 27, 2, 2], 'label': ['SBV', 'HED', 'ATT', 'RAD', 'ATT', 'VOB', 'WP', 'SBV', 'COO', 'ATT', 'RAD', 'ATT', 'VOB', 'WP', 'SBV', 'COO', 'VOB', 'VOB', 'WP', 'ADV', 'SBV', 'COO', 'VOB', 'VOB', 'WP', 'SBV', 'ADV', 'POB', 'COO', 'WP']}, sdp={'head': [2, 0, 6, 3, 6, 2, 2, 9, 2, 13, 10, 13, 9, 9, 16, 9, 16, 17, 16, 22, 22, 16, 22, 23, 22, 29, 28, 29, 22, 29], 'label': ['EXP', 'Root', 'TIME', 'mDEPD', 'FEAT', 'LINK', 'mPUNC', 'EXP', 'eSUCC', 'FEAT', 'mDEPD', 'FEAT', 'LINK', 'mPUNC', 'AGT', 'eSUCC', 'dCONT', 'CONT', 'mPUNC', 'mRELA', 'AGT', 'eCOO', 'dCONT', 'CONT', 'mPUNC', 'EXP', 'mRELA', 'LOC', 'eSUCC', 'mPUNC']}, sdpg=[(1, 2, 'EXP'), (2, 0, 'Root'), (3, 6, 'TIME'), (4, 3, 'mDEPD'), (5, 6, 'FEAT'), (6, 2, 'LINK'), (7, 2, 'mPUNC'), (8, 9, 'EXP'), (8, 10, 'eCOO'), (9, 2, 'eSUCC'), (10, 13, 'FEAT'), (11, 10, 'mDEPD'), (12, 13, 'FEAT'), (13, 9, 'LINK'), (14, 9, 'mPUNC'), (15, 16, 'AGT'), (16, 9, 'eSUCC'), (17, 16, 'dCONT'), (18, 17, 'CONT'), (19, 16, 'mPUNC'), (20, 22, 'mRELA'), (21, 22, 'AGT'), (22, 16, 'eCOO'), (23, 22, 'dCONT'), (24, 23, 'CONT'), (25, 22, 'mPUNC'), (26, 29, 'EXP'), (27, 28, 'mRELA'), (28, 29, 'LOC'), (29, 22, 'eSUCC'), (30, 22, 'mPUNC'), (30, 29, 'mPUNC')])

当然,我们也可以使用字典分别返回其结果

# 使用字典格式作为返回结果
print(output.cws)  # print(output[0]) / print(output['cws']) # 也可以使用下标访问
print(output.pos)
print(output.sdp)
print(output.ner)
print(output.srl)

我们这里创建知识图谱主要使用命名实体识别和语义角色标注的结果

2.3 实体创建

实体创建主要是命名实体识别的结果

print(output.cws) 
print(output.ner)

['苏轼', '是', '宋朝', '的', '著名', '文学家', ',', '黄庭坚', '是', '他', '的', '好', '朋友', '。', '苏轼', '擅长', '写', '词', ',', '而', '黄庭坚', '擅长', '写', '诗', '。', '他', '在', '常州', '去世', '。']

[('Nh', '苏轼'), ('Nh', '黄庭坚'), ('Nh', '苏轼'), ('Nh', '黄庭坚'), ('Ns', '常州')]

LTP目前可以识别的实体类别主要有三种:

标记含义
Nh人名
Ni机构名
Ns地名

当然如果是复杂项目的数据,这个明显是不能支持的,后面我们会介绍如果训练自己的命名实体识别模型

从上面的结果我们可以看到,目前识别的结果只有人名和地名

正常来讲,北宋作为时间,应该也需要进行识别

接下来我们创建实体:

def entity_extraction(ner_result):
    ner_list_Nh=[]
    ner_list_Ni=[]
    ner_list_Ns=[]
    
    
    for i in  range(len(ner_result)):
        
        if output.ner[i][0] == "Nh":
            ner_list_Nh.append(ner_result[i][1])
        elif output.ner[i][0] == "Ni":
            ner_list_Ni.append(ner_result[i][1])
        elif output.ner[i][0] == "Ns":
            ner_list_Ns.append(ner_result[i][1])
            
    return list(set(ner_list_Nh)),list(set(ner_list_Ni)),list(set(ner_list_Ns))
    

根据不同的识别标签创建三个list,并且用set去重,最后得到实体

ner_list_Nh,ner_list_Ni,ner_list_Ns

(['苏轼', '黄庭坚'], [], ['常州'])

最终的实体有三个,两个人名,一个地名

2.4 三元组构建

我们使用角色标注的结果创建三元组

实际情况下,只使用角色标注创建是不行的,需要根据依存句法、语义依存等一起来进行构建,这样会更好的理解上下文和全局

print(output.cws)  
print(output.srl)

['苏轼', '是', '宋朝', '的', '著名', '文学家', ',', '黄庭坚', '是', '他', '的', '好', '朋友', '。', '苏轼', '擅长', '写', '词', ',', '而', '黄庭坚', '擅长', '写', '诗', '。', '他', '在', '常州', '去世', '。']

[{'predicate': '是', 'arguments': [('A0', '苏轼'), ('A1', '宋朝的著名文学家')]}, {'predicate': '是', 'arguments': [('A0', '黄庭坚'), ('A1', '他的好朋友')]}, {'predicate': '擅长', 'arguments': [('A0', '苏轼'), ('A1', '写词')]}, {'predicate': '写', 'arguments': [('A1', '词')]}, {'predicate': '擅长', 'arguments': [('A0', '黄庭坚'), ('A1', '写诗')]}, {'predicate': '写', 'arguments': [('A1', '诗')]}, {'predicate': '去世', 'arguments': [('A0', '他'), ('ARGM-LOC', '在常州')]}]

为了更好的展示,我们分别打印一下

for i in range(len(output.srl)):
    #if srl[i]
    print(output.srl[i])
{'predicate': '是', 'arguments': [('A0', '苏轼'), ('A1', '宋朝的著名文学家')]}
{'predicate': '是', 'arguments': [('A0', '黄庭坚'), ('A1', '他的好朋友')]}
{'predicate': '擅长', 'arguments': [('A0', '苏轼'), ('A1', '写词')]}
{'predicate': '写', 'arguments': [('A1', '词')]}
{'predicate': '擅长', 'arguments': [('A0', '黄庭坚'), ('A1', '写诗')]}
{'predicate': '写', 'arguments': [('A1', '诗')]}
{'predicate': '去世', 'arguments': [('A0', '他'), ('ARGM-LOC', '在常州')]}

语义角色类型可以在LTP官网上查看
在这里插入图片描述
我们这里筛选有A0角色的进行创建

从一般的结果看,一般A0会对应到命名实体识别的实体上,当然我个人觉得这里是有优化空间的

kg_list=[]
for i in range(len(output.srl)):
    judge_for_a0=[]
    for j in range(len(output.srl[i]["arguments"])):
        judge_for_a0.append(output.srl[i]["arguments"][j][0])
        #print((judge_for_a0))
    if "A0" in judge_for_a0:
        index_a0 = judge_for_a0.index("A0")
        if "A1" in judge_for_a0:
            index_a1 = judge_for_a0.index("A1")
        elif "ARGM-LOC" in judge_for_a0:
            index_a1 = judge_for_a0.index("ARGM-LOC")
        
        kg_list.append([output.srl[i]["arguments"][index_a0][1],output.srl[i]["predicate"],output.srl[i]["arguments"][index_a1][1]])

生成的结果就是:

[['苏轼', '是', '宋朝的著名文学家'],
 ['黄庭坚', '是', '他的好朋友'],
 ['苏轼', '擅长', '写词'],
 ['黄庭坚', '擅长', '写诗'],
 ['他', '去世', '在常州']]

2.5 数据整理

  • 如果在三元组中的A0没有在实体中的话我们直接去掉;
  • 对于三元组中的第三列,我们这里单独将其定义为一类实体为标签
#实体清洗,与ner结果匹配
def  kg_list_rule(kg_list,ner_list_Nh):
    for i in range(len(kg_list)):
        for j in ner_list_Nh:#如果A0角色,包含ner识别的实体,将其替换为实体名称
            if j in kg_list[i][0]:
                kg_list[i][0]=j
    
    for i in range(len(kg_list)):#如果语义角色识别的角色不再ner结果中则删除,此处需要优化
        if kg_list[i][0] in ner_list_Nh:
            continue
        del kg_list[i]

    predicate = []
    for i in range(len(kg_list)):#提取谓语
        predicate.append(kg_list[i][2])
    return kg_list,predicate
                

最终结果如下:

([['苏轼', '是', '宋朝的著名文学家'],
  ['黄庭坚', '是', '他的好朋友'],
  ['苏轼', '擅长', '写词'],
  ['黄庭坚', '擅长', '写诗']],
 ['宋朝的著名文学家', '他的好朋友', '写词', '写诗'])

3、创建图谱–neo4j

目前neo4j应该是最容易使用的图数据库,所以我们使用neo4j进行创建,如果大家不想用图数据库,我们下一节介绍一个工具来进行可视化

3.1 链接neo4j

from py2neo import Node, Graph, Relationship, NodeMatcher

graph = Graph("bolt://localhost:7687", 
			user="neo4j", 
			password='1qa2ws3ed',
            name="demo"
              )

3.2 创建节点

def node_create(ner_list_Nh,ner_list_Ni,ner_list_Ns,predicate):
    if len(ner_list_Nh)!=0:
        for i in range(len(ner_list_Nh)):
            graph.create(Node('人名', name=ner_list_Nh[i]))

    if len(ner_list_Ni)!=0:
        for i in range(len(ner_list_Ni)):
            graph.create(Node('机构名', name=ner_list_Ni[i]))

    if len(ner_list_Ns)!=0:
        for i in range(len(ner_list_Ns)):
            graph.create(Node('地名', name=ner_list_Ns[i]))

    if len(predicate)!=0:
        for i in range(len(predicate)):
            graph.create(Node('标签', name=predicate[i]))
            

将所有实体,包括标签进行创建

3.3 创建边

def relationship_create(kg_list):
    for m in range(len(kg_list)):
        try:
            rel = Relationship(matcher.match("人名").where("_.name=" + "'" + kg_list[m][0]  + "'").first(),
                               kg_list[m][1],
                               matcher.match("标签").where("_.name=" + "'" + kg_list[m][2]  + "'").first())
            graph.create(rel)

        except AttributeError as e:
            print(e, m)

在这里插入图片描述
这里可以看到,其实这个结果有点不太理想,就是苏轼和黄庭坚之间没有建立关系,其实这个就是我们前面提到的,只使用语义角色标注创建三元组是不行的,后面我们可以结合其他方法进行优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1274294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java实现简单的王者荣耀游戏

一、创建新项目 首先创建一个新的项目,并命名为wangzherongyao。 其次在飞翔的鸟项目下创建一个名为img的文件夹用来存放游戏相关图片。详细如下图: 二、游戏代码 1、创建怪物类 1.bear: package beast;import wangzherogyao.GameFrame;…

代码随想录算法训练营第三十七天 _ 贪心算法_738.单调自增的数字、968.监督二叉树

学习目标: 60天训练营打卡计划! 学习内容: 738.单调自增的数字 听不懂的时候就到该动手了。必须要从后向前操作,才能把压力逐级传给最前面的这一位。入如:322 class Solution {// java中的String不能修改&#xf…

TQ2440开发板-LED全亮全灭控制程序设计

目录 什么是GPIOS3C2440的GPIO访问和控制方式:3种寄存器 TQ2440的LED灯底板原理图---LED测试部分核心板原理图----GPIO部分 LED控制---设计思想整体代码 && 代码研读配置GPIO端口为输出模式控制LED的全亮和全灭 真就是从零学起。 什么是GPIO GPIO&#xff…

SQL 金额数值转换成中文大写

需求:将金额转换成中文大写格式填入单据合计行: _佰_拾_万_仟_佰_拾_元_角_分 1234567.89 壹佰贰拾叁万肆仟伍佰陆拾柒元捌角玖分 1.函数转换 drop function n2C;CREATE FUNCTION n2C (num numeric(14,2)) RETURNS VARCHAR(20) AS BEGIN …

elementui中添加开关控制

<template><!-- 图层管理 --><div class"home-wrapper"><div class"table-list"><div class"list"><el-table :data"tableData" height"100%" style"width: 100%;" border>&…

系列十三、SpringBoot的自动配置原理

一、概述 我们知道Java发展到现在功能十分的强大&#xff0c;生态异常的丰富&#xff0c;这里面离开不了Spring及其家族产品的支持&#xff0c;而作为Spring生态的明星产品Spring Boot可以说像王者一般的存在&#xff0c;那么的耀眼&#xff0c;那么的光彩夺目&#xff01;那么…

BLP9H10-30GZ LDMOS 功率晶体管 Ampleon

BLP9H10-30GZ 30W塑料LDMOS 功率晶体管&#xff0c;适用于频率范围为616 MH 至960 MHz的基站应用。 BLP9H10-30GZ 特点和优势&#xff1a; 高效率 出色的耐用性 专为宽带操作而设计 出色的热稳定性 高功率增益 集成ESD保护 有关 RoHS 合规性 BLP9H10-30GZ应用程序&…

4.5-容器之间的link

我们在实际项目中可能会有种需求&#xff0c;假如我们有个后台项目&#xff0c;它要访问数据库&#xff0c;比如MySQL&#xff0c;它想要访问数据库&#xff0c;就需要数据库的ip和端口。如果有两个容器&#xff0c;一个容器启动的是数据库的MySQL服务&#xff0c;另一个容器启…

【滑动窗口】无重复字符的最长字串

无重复字符的最长字串 文章目录 无重复字符的最长字串题目描述算法思路思路一思路二 代码编写暴力解法滑动窗口 3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示…

vivado实现分析与收敛技巧1

智能设计运行 智能设计运行 (IDR) 是一种特殊类型的实现运行 &#xff0c; 它使用复杂流程来尝试达成时序收敛。由于 IDR 可能较为激进 &#xff0c; 因此预计编译时间可达标准运行的约 3.5 倍。 IDR 围绕复杂的时序收敛功能特性展示了一个简单的用户界面 &#xff0c; 对…

罐装葡萄酒会成为主流吗?

许多人认为罐装葡萄酒可能是葡萄酒行业的下一个大事件&#xff0c;一个有待提出的问题&#xff0c;罐装葡萄酒会成为主流吗&#xff1f;来自云仓酒庄品牌雷盛红酒分享还是这种形式的基础永远会限制它的吸引力&#xff1f;在这里&#xff0c;我们一起来探讨支持和反对罐装葡萄酒…

UG\NX二次开发 设置是否允许通过NXOpen锁定属性

文章作者:里海 来源网站:里海NX二次开发3000例专栏 感谢粉丝订阅 感谢 2301_80939425 订阅本专栏,非常感谢。 简介 在使用UF_ATTR_set_locked函数锁定属性前,需要先设置是否允许通过NXOpen锁定属性。使用下面的代码可以修改“用户默认设置”当 NX 启动时,客户默认值将读取…

ZPLPrinter Emulator SDK for .NET 6.0.23.1123​ Crack

ZPLPrinter Emulator SDK for .NET 适用于 .NET 的 ZPLPrinter 仿真器 SDK 允许您通过编写 C# 或VB.NET 代码针对任何 .NET Framework、.NET CORE、旧版 ASP.NET MVC 和 CORE、Xamarin、Mono 和通用 Windows 平台 (UWP) 作业。 适用于 .NET 的 ZPLPrinter 仿真器 SDK 允许您将…

王道数据结构课后代码题p40 4.在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值唯一) (c语言代码实现)

本题代码为 void deletemin(linklist* L)//找到最小值并删除 {lnode* p (*L)->next, * pre *L;lnode* s p,*sprepre;while (p ! NULL)//找到最小值{if (p->data < s->data){s p;spre pre;}p p->next;pre pre->next;}p s->next;spre->next p;…

Collection集合的遍历方式-迭代器,增强for循环,Lambda

集合体系概述 Collection是单列集合的祖宗&#xff0c;它规定的方法&#xff08;功能&#xff09;是全部单列集合都会继承的 public class Work1 {public static void main(String[] args) {//简单认识一下Collection集合的特点ArrayList<String> list new ArrayList&…

【前端】多线程 worker

VUE3 引用 npm install worker-loader 在vue.config.js文件的defineConfig里加上配置参数 chainWebpack: config > {config.module.rule(worker-loader).test(/\.worker\.js$/).use({loader: worker-loader,options: {inline: true}}).loader(worker-loader).end()}先在…

【开源视频联动物联网平台】写一个物联网项目捐献给Dromara组织

一、平台简介 MzMedia开源视频联动物联网平台&#xff0c;简单易用&#xff0c;更适合中小企业和个人学习使用。适用于智能家居、农业监测、水利监测、工业控制&#xff0c;车联网&#xff0c;监控直播&#xff0c;慢直播等场景。 支持抖音&#xff0c;视频号等主流短视频平台…

【开源威胁情报挖掘2】开源威胁情报融合评价

基于开源信息平台的威胁情报挖掘综述 写在最前面4 开源威胁情报融合评价开源威胁情报的特征与挑战4.1 开源威胁情报数据融合融合处理方法 4.1 开源威胁情报的质量评价4.1.1 一致性分析本体的定义与组成本体构建的层次 4.1.2 去伪去重4.1.3 数据融合分析 4.2 开源威胁情报质量及…

sqli-labs(9)

45. 不会显示报错信息通过or 1验证 在密码处输入)or(1 登录成功 )union select 1,2,3 # )union select 1,database(),3 # )union select 1,(select group_concat(table_name) from information_schema.tables where table_schemasecurity),3 # )union select 1,(select gro…

电脑桌面上带有日期提醒的便签工具用哪个

在电脑桌面上创建便签条目时&#xff0c;不少人后续复盘便签上整理的工作计划时&#xff0c;会想知晓当时是什么时间创建的工作计划&#xff0c;亦或者是该条工作计划需要什么时间触发提醒等&#xff0c;这时候电脑桌面便签就需要附带有相关的显示时间的功能&#xff0c;在电脑…