共计 18812 个字符,预计需要花费 48 分钟才能阅读完成。
常识图谱之《海贼王 -ONEPICE》畛域图谱我的项目实战(含码源):数据采集、常识存储、常识抽取、常识计算、常识利用、图谱可视化、问答零碎 (KBQA) 等
实体关系 可视化页面 可视化页面尝鲜
1. 我的项目背景 & 我的项目内容
《海贼王》(英文名 ONE PIECE) 是由日本漫画家尾田荣一郎创作的热血少年漫画,因为其巨大的世界观、丰盛的人物设定、精彩的故事情节、草蛇灰线的伏笔,受到世界各地的读者欢送,截止 2019 年 11 月 7 日,寰球销量冲破 4 亿 6000 万本1,并被吉尼斯世界纪录官网认证为“世界上发行量最高的繁多作者创作的系列漫画”2。
《海贼王》从 1997 年开始连载至今,以及将近 22 年,在 900 多话的漫画中大量性情显明的角色相继退场,故事产生的地点也在一直变动,这既给咱们带来浏览的乐趣,同时也为咱们梳理故事脉络带来了挑战。
本次工作试图为《海贼王》中呈现的各个实体,包含人物、地点、组织等,构建一个常识图谱,帮忙咱们更好的了解这部作品。
本我的项目内容包含数据采集、常识存储、常识抽取、常识计算、常识利用五大部分
-
数据采集
本次我的项目次要采集构建了两个常识图谱和一个关系抽取数据集
- 人物常识图谱:次要蕴含各个人物的信息
- 关系抽取数据集:标注出自然语言中存在的实体以及他们之间的关系
- 实体关系常识图谱:构建《海贼王》中各个实体之间关系的常识图谱
-
常识存储
尝试应用了三元组数据库 Apace Jena 和原生图数据库 Neo4j,并别离应用 RDF 结构化查询语言SPARQL 和属性图查询语言Cypher,在常识图谱上进行查问。
-
常识抽取
基于之间构建的关系抽取数据集,利用 deepke 中提供的工具进行关系抽取实际,测试了包含 PCNN、GCN、BERT 等模型在咱们构建数据集上的成果
-
常识计算
- 图计算:在 Neo4j 上对实体关系常识图谱进行了图开掘,包含最短门路查问、权威结点发现、社区发现等
- 常识推理:在 Apache Jena 上对关系常识图谱进行了常识推理,补全了一部分的数据
-
常识利用
- 智能问答:基于 REfO 实现一个对于《海贼王》中人物的知识库问答零碎(KBQA)。
- 可视化图片:通过 D3 对实体关系图片进行可视化,并整合了人物常识图谱中的信息,进行展现。
码源下载见文末跳转
码源下载见文末跳转
2. 数据采集
- 数据起源
本次我的项目中所应用的数据次要起源为两个:一个是从别的常识图谱中获取曾经存在的常识信息,另一个是从相干网页中爬取解析半结构化的自然语言文本信息
2.1 人物常识图谱构建
2.1.1 抽取通用常识图谱中已有的指标域常识
常识图谱技术近些年来疾速倒退,一些公司机构曾经构建了许多通用常识图谱,咱们能够从中抽取出咱们指标畛域内相干的实体常识信息,作为咱们常识图谱的冷启动数据。
CN-DBpedia3是由复旦大学常识工场 4 实验室研发并保护的大规模通用畛域结构化百科,咱们抉择其作为通用常识图谱起源。
整个解决流程如下:
- 构建《海贼王》实体词汇库
- 获取实体列表
- 筛选实体列表
- 获取图谱中对应实体的三元组常识
构建《海贼王》实体词汇库
次要通过畛域 WiKi 获取《海贼王》中的实体词汇库。在这里,咱们在萌娘百科的相干页面 5 中获取由粉丝爱好者整顿的词条名信息,作为词汇库。
咱们将原始的半结构化词条数据保留在 cndbpedia/data/raw_moegirl_onepiece_entries.txt
中,并利用正则表达式对其进行解析
python cndbpedia/parse_raw_moegirl_onepiece_entries.py
输入的后果保留在 cndbpedia/data/processed_moegirl_onepiece_entries.txt
中,一共提取了509 个词条名
获取实体列表
咱们利用常识工厂提供的 API6,将词条名作为输出实体指称项名称 (mention name),获取返回对应实体(entity) 的列表。
python cndbpedia/get_onepiece_cndbpedia_entities.py
总共获取了 1014 个 不同的实体名,并输入了两个文件,输入的后果保留在 cndbpedia/data
文件夹中。
-
cndbpedia_onepiece_entities_list.txt
:保留了所有辨认出的 CN-DBpedia 中的实体名,例如爱德华·纽盖特(《航海王焚烧意志》游戏角色)爱德华·纽盖特(日本漫画《海贼王》中的角色)爱莎(《弑神者!》中的弑神者之一)爱莎(《海贼王》中的角色)爱莎(艾尔之光游戏人物)
-
moelgirl_cndbpedia_entities_mapping.json
:保留着从 moegirl 的的条目作为实体指称项名称,在 api 上查找到的对应的实体列表,例如"夏奇": [ "夏奇(日本动漫《海贼王》角色)", "夏奇(福建人民艺术剧院主持人)", "夏奇(深圳市夏奇实业有限公司)", "夏奇(《永嘉诗联》主编)" ], "布拉曼克": ["布拉曼克"], "艾佛兰德拉": ["艾佛兰德拉"], "顶上和平": ["大事件(漫画《海贼王》中顶上和平)"], "堪十郎": ["堪十郎"],
筛选实体列表
因为自然语言和事实世界的多义性,往往一个 mention name 可能对应着常识图谱中的多个不同实体。就拿 布鲁克
这个名字来说,在 api 返回的实体列表中,就有好多不同的实体
布鲁克
布鲁克(奥地利城市穆尔河畔布鲁克缩写)布鲁克(广告策划师)布鲁克(日本动漫《海贼王》中的人物)布鲁克(温力铭演唱歌曲)布鲁克(游戏《赛尔号》中的精灵)布鲁克(西班牙 2010 年拍摄电影)
而其中第四个才是咱们须要的。
因而咱们能够设置一些筛选条件,只有当实体名中 蕴含:海贼王,航海王,海贼,航海,onepiece,one piece,动漫,漫画
这些关键词之一时,才认为是咱们须要的实体
python cndbpedia/filter_moelgirl_cndbpedia_entities_mapping_file.py
输入的后果保留在 cndbpedia/data
文件夹中
筛选后果:在 509 个词条中
- 有 162 个词条在 CN-DBpedia 没有对应的实体名,这些词条被保留在
moelgirl_cndbpedia_api_no_results_mention_name_list.txt
; - 有 11 个词条尽管有实体名,但所有对应实体名中都没有蕴含下面提到的关键词,这些词条被保留在
filter_out_entities_mapping.json
- 残余 336 个词条中,都有对应符合条件的实体名,一共有 357 个。这些词条被保留在
query_avpair_entities_list.txt
,此外query_avpair_entities_mapping.json
中保留着这些非法词条名和实体名对应的字典。
获取图谱中对应实体的三元组常识
咱们利用常识工厂提供的 API6,依据后面筛选的实例列表,获取图谱中对应实体的三元组常识
python cndbpedia/get_onepiece_cndbpedia_avpair.py
输入后果保留在 cndbpedia/data
文件夹中
-
query_avpair_cndbpedia_onepiece_results.json
:保留着每个实体对应的三元组常识的字典,采纳两级索引构造,第一级索引是 mention name,第二级索引是实体名字,示例如下"砂糖": { "砂糖(《海贼王》人物)": { "性别": "女", "配音": "詹雅菁(台湾)", "中文名": "砂糖", "退场作品": "海贼王", "首次退场": "漫画第 682 话、动画 608 话", "恶魔果实": "超人系童趣果实", "职位": "唐吉诃德家族梅花军特地干部", "外文名称": "Sugar", "年龄": "外貌年龄 10 岁,实在年龄 22 岁", "CATEGORY_ZH": "人物", "DESC": "砂糖是日本动漫《海贼王》中的人物,童趣果实能力者。唐吉诃德家族干部,附属梅花军托雷波尔。被家族视为重要的干部,多弗朗明哥为此特地安顿家族最高干部托雷波尔负责她的贴身保镖。" } },
query_avpair_keys_list_file.txt
:保留在所有属性名称的列表
2.1.2 抽取网页中半结构化的常识
生命卡 (vivre card)7 是海贼王官网整顿公布的角色材料图鉴,蕴含着丰盛的角色信息。国内的粉丝爱好者也将其翻译成了中文版本,并公布在了网页上8。这部分就是心愿抽取 Talkop 论坛中相干网页中存在的半结构化信息,构建对应人物的常识图谱。
抽取流程
因为格局较为固定,因而采纳 模板匹配 的形式来抽取常识,整个流程如下:
- 从网页中获取原始文本信息
- 人工删除不相干的文本
-
利用代码以模板匹配的形式,主动抽取人物属性信息
cd talkop python parse_processed_manual_talkop_vivre_card.py
输入的文件保留在
talkop/data/processed_manual_talkop_vivre_card
文件夹中,每个网页对应着三个输入文件xxx-predicate_key_list.txt
:所有解析失去的 predicatexxx-entities_id_name_list.txt
:所有解析失去的 id 和实体名xxx-entities_avpair.json
:抽取到所有实体的属性常识,以 json 的格局保留
- 人工校验:例如:查看是否抽取到了所有的实体、通过查看抽取的 predicate 后果来调整模板。整个过程中是代码主动抽取和人工校验形成闭环的过程,在闭环过程中一直补充模板信息,改善抽取后果
在整个过程中,2、3、4 是一直周而复始的过程,直至抽取的常识满足咱们的须要。
汇总后果
在下面局部中,咱们别离抽取了各个网页中人物实体的属性信息,当初将这些信息进行进一步的汇总
cd talkop
python summary_talkop_vivre_card.py
从汇总的后果能够看到,一共蕴含660 个不同的实体,164 个不同的 predicate
输入的文件保留在 talkop/data/processed_manual_talkop_vivre_card
文件夹中,一共有两个文件:
summary_predicate_set.txt
:所有 predicate 的汇总summary_entities_id_name_list.txt
:所有抽取失去的实体名以及对应 ID 的汇总
2.2. 关系抽取数据集构建
- 标注数据起源 :在后面构建的人物常识图谱中,有一项重要的属性是 历史信息 ,记录着每个人物在故事中的工夫线以及对应的故事。每个人的历史信息记录着其 与其余实体之间交互的信息,咱们能够利用它来构建咱们垂直畛域内的关系抽取数据集
- 标注工具:精灵标注助手8
- 构建办法:自底向上构建,在构建过程中逐渐构建整个图谱的 schema
-
数据标注格局:精灵标注助手提供导出 json 格局,其具体模式如下所示,其中
T
和E
别离示意标注出的实体信息和关系信息{ "content": "xxxx" "labeled": true, "outputs": { "annotation": {"A": [""],"E": [""], "R": ["",{"arg1":"Arg1","arg2":"Arg2","from": 1,"name":" 到过 ","to": 2}, ], "T": ["",{"attributes": [],"end": 7,"id": 1,"name":" 人 ","start": 0,"type":"T","value":" 蒙其·D·路飞 " }, ] } }, "path": "D:\\annot\\fuseki_vivrecard_sentence_item.txt", "time_labeled": 1578072175246 }
-
数据存储地位: 被标注的原始数据被保留在
deepke-master/data/vivrecard/rawfuseki_vivrecard_sentence_item.txt
原始标注后果被保留在deepke-master/data/vivrecard/annot/outputs/fuseki_vivrecard_sentence_item.json
。为了不便后续关系抽取模型解决,咱们将标注数据转为合乎 deepke 我的项目格局的数据
并保留在
deepke-master/data/vivrecard/origin
,具体详情参见常识抽取局部
2.3 数据集统计信息
- 实体类型:一共 7 种 实体:’ 事件 ’, ‘ 组织 ’, ‘ 船只 ’, ‘ 地点 ’, ‘ 职务 ’, ‘ 恶魔果实 ’, ‘ 人 ’
-
关系类型:一共 22 种 关系
head_type tail_type relation index freq None None None 0 0 人 事件 参加 1 36 人 人 同盟 2 1 人 人 夫妻 3 3 人 人 战斗 4 38 人 人 母亲 5 3 人 人 父亲 6 4 人 人 老师 7 6 人 人 遇见 8 100 人 地点 出生地 9 3 人 地点 到过 10 145 人 恶魔果实 领有果实 11 10 人 组织 创立 12 23 人 组织 退出 13 66 人 组织 属于 14 38 人 组织 战斗 15 20 人 组织 来到 16 18 人 组织 遇见 17 14 人 组织 领导 18 15 人 职务 负责 19 70 人 船只 建造 20 2 组织 组织 战斗 21 1 这些关系的频数柱状图如下图所示,能够看到这些关系展现出显著的 长尾散布
- 训练正样本个数:616 个
2.4 实体关系常识图谱构建
在进行关系抽取数据集的标注过程中,咱们将标注的实体和关系独自导出,构建《海贼王》实体关系数据集
在上述过程中,一共标注了 307 个 不同的实体,569 个 不同结点间的关系
cd deepke-master
python utils/convert_vivrecard2deepke.py
输入的实体关系数据保留在 deepke-master/data/vivrecard/summary/vizdata_vivrecard_relation.json
,可用于后续进行常识图谱可视化,具体参见常识图谱可视化局部
3. 常识存储
3.1. 基于 RDF 三元组数据库:Apache Jena
3.1.1 Jena 简介 & 我的项目实际
Jena9是 Apache 顶级我的项目, 其前身为惠普实验室开发的 Jena 工具包.Jena 是语义 Web 畛域次要的开源框 架和 RDF 三元组库, 较好地遵循了 W3C 规范, 其性能包含:RDF 数据管理、RDFS 和 OWL 本体治理、SPARQL 查询处理等.Jena 具备一套原生存储引擎, 可对 RDF 三元组进行基于磁盘或内存的存储管理. 同时, 具备一套基 于规定的推理引擎, 用以执行 RDFS 和 OWL 本体推理工作.
avpair to triple
以 vivrecard 人物属性常识图谱为例,首先咱们将之前取得的数据,转换为 Jena 反对解析的 N-Triple
三元组格局,命名空间前缀为 <http://kg.course/talkop-vivre-card/>
cd talkop
python avpair2ntriples_talkop_vivre_card.py
导出的 N-Triple
格局的数据保留在 talkop/data/processed_manual_talkop_vivre_card/ntriples_talkop_vivre_card.nt
,一共有14055 个,其中非空 triples 有 12863 个
NOTE:
-
在我的项目构建过程中,咱们也将从 CN-DBpedia 获取的常识转换为
N-Triple
格局,命名空间前缀为<http://kg.course/onepiece/>
python cndbpedia/avpair2ntriples_onepiece_cndbpedia.py
后果保留在
cndbpedia/data/ntriples_cndbpedia_onepiece.nt
,一共有4691 个 triple
启动 Fuseki
依照陈华均老师提供文件:https://github.com/zjunlp/kg-course/blob/master/tutorials/Tutorial-Jena.pdf
进一步配置 fuseki,上传数据集就能够查问了
3.1.2 SPARQL 查问示例
SPARQL10 是 W3C 制订的 RDF 常识图谱规范查询语言.SPARQL 从语法上借鉴了 SQL.SPARQL 查问的 根本单元是三元组模式 (triple pattern), 多个三元组模式可形成根本图模式(basic graph pattern).SPARQL 反对多 种运算符, 将根本图模式扩大为简单图模式(complex graph pattern).SPARQL 1.1 版本引入了属性门路(property path) 机制以反对 RDF 图上的导航式查问. 上面应用图 2 所示的电影常识图谱 RDF 图, 通过示例介绍 SPARQL 语言的基本功能. 11
上面给出了应用 SPARQL 在咱们构建的数据库上进行查问的示例
-
查问前五个角色的身高
PREFIX : <http://kg.course/talkop-vivre-card/> select ?s ?name ?zhname ?height ?o where { ?s ?height ?o . FILTER(?height in (: 身高, : 身长)) . OPTIONAL {?s : 名称 ?name. ?s : 外文名 ?zhname.} } limit 5
后果
"s" , "name" , "zhname" , "height" , "o" , ":0001" , "【蒙其·D·路飞 /Monkey D Luffy】" , "Monkey D Luffy" , ": 身高" , "174cm" , ":0004" , "【乌索普 /Usopp】" , "Usopp" , ": 身高" , "174cm" , ":0511" , "【乔艾莉·波妮 /Jewelry Bonney】" , "Jewelry Bonney" , ": 身高" , "174cm" , ":0002" , "【罗罗诺亚·索隆 /Roronoa Zoro】" , "Roronoa Zoro" , ": 身高" , "181cm" , ":0224" , "【缇娜 /Hina】" , "Hina" , ": 身高" , "181cm" ,
-
筛选生日范畴
PREFIX : <http://kg.course/talkop-vivre-card/> select ?s ?name ?o where { ?s : 生日 ?o . ?s : 名称 ?name . filter(?o > '4 月 1 日' && ?o < '5 月 1 日') } limit 5
后果
"s" , "name" , "o" , ":0009" , "【布鲁克 /Brook】" , "4 月 3 日" , ":0660" , "【伯尔杰米 /Porchemy】" , "4 月 3 日" , ":0010" , "【甚平 /Jinbe】" , "4 月 2 日" , ":0076" , "【哲夫 /Zeff】" , "4 月 2 日" , ":0028" , "【克比 /Koby】" , "5 月 13 日" ,
3.2. 基于原生图数据库:Neo4j
3.2.1. Neo4j 简介 &Cypher 查问示例
Neo4j12是由 Neo 技术公司开发的图数据库. 能够说,Neo4j 是目前风行水平最高的图数据库产品.Neo4j 基 于属性图模型, 其存储管理层为属性图的节点、节点属性、边、边属性等元素设计了专门的存储计划. 这使得 Neo4j 在存储层对于图数据的存取效率优于关系数据库.
4.2.2. 我的项目实际
relation to triple
以实体关系常识图谱为例,首先咱们将之前取得的各个实体之间关系的数据,转换为 Jena 反对解析的 N-Triple
三元组格局,命名空间前缀为 <http://kg.course/talkop-vivre-card/deepke/>
cd deepke-master
python utils/convert_vivrecard2deepke.py
导出的 N-Triple
格局的数据保留在 deepke-master/data/vivrecard/summary/vivrecard_ntriples.nt
,一共有1848 个
启用 Neo4j
Neo4j 的下载安装能够参考:https://neo4j.com/download-thanks-desktop/?edition=desktop&fl…
cd D:\neo4j\bin
neo4j.bat console
之后拜访: http://localhost:7474/
就能够了
默认的用户名和明码都是 neo4j
Cypher 最后是图数据库 Neo4j 中实现的属性图数据查询语言,是一种申明式的语言,用户只须要申明查什么,而不须要关系怎么查。
上面给出了应用 Cypher 在咱们构建的数据库上进行查问的示例
-
导入
CREATE INDEX ON :Resource(uri) CALL semantics.importRDF("file:///${PROJECT_PATH}/deepke-master/data/vivrecard/summary/vivrecard_ntriples.nt","N-Triples")
-
查看 schema
call db.schema()
把 resource 屏蔽掉,就能分明的看到 schema 了
-
查问前 100 集体
MATCH (n:ns0__人) RETURN n LIMIT 100
-
查问属于人的结点中,URI 外面蕴含
薇薇
的结点MATCH (n:ns0__人) WHERE n.uri CONTAINS '薇薇' RETURN n.uri
n.uri “http://kg.course/talkop-vivre-card/deepke/ 人 / 寇布拉•薇薇 ” “http://kg.course/talkop-vivre-card/deepke/ 人 / 奈菲鲁塔丽•薇薇 ” “http://kg.course/talkop-vivre-card/deepke/ 人 / 薇薇 ” -
依据 uri 筛选名字间最短门路
MATCH p=shortestPath((n1)-[*]-(n2) ) WHERE n1.uri CONTAINS '斯摩格' and n2.uri CONTAINS '罗宾' RETURN p
-
依据名字筛选德雷斯罗萨到司法岛外面 四跳的门路
# 五跳内能到的所有门路 # 9312 多萝菲(Miss. 圣诞快乐)# 9306 本·贝克曼 MATCH p = ((n1)-[*4]-(n2)) WHERE n1.uri CONTAINS '司法岛' and n2.uri CONTAINS '德雷斯罗萨' RETURN p
能够发现这外面存在一些环路的状况,即同一个结点在门路中呈现两次
4. 常识抽取
DeepKE13基于 Pytorch 的深度学习中文关系抽取解决套件。在这部分中咱们利用之前构建的关系抽取数据集和 deepke,进行中文关系抽取实际
4.1. 数据转换 & 标注统计
在这部分,咱们须要实现以下三局部内容:
- 将咱们的标注后果转换为 deepke 所接管的格局
- 为了保障关系散布平均,将数据随机打乱
- 实现训练集、测试集、验证集的划分,目前按 7:2:1 进行划分
应用 deepke-master/utils/convert_vivrecard2deepke.py
实现数据格式转换
cd deepke-master
python utils/convert_vivrecard2deepke.py
输入
一共有 616 个训练正样本,其中 train、test、valid 别离有:431/123/62 个
输入的文件保留在 deepke-master/data/vivrecard/
中的 origin
和 summary
文件夹中
├── annot
│ └── outputs
│ └── formatted_fuseki_vivrecard_sentence_item.json # 对 json 文件进行缩进等格式化
├── origin # 输入转换失去 deepke 训练数据到该文件夹
│ ├── relation.csv
│ ├── test.csv
│ ├── train.csv
│ └── valid.csv
└── summary
├── all_sent.txt # 所有的句子
├── annot_entity_sent.txt # 被标记上实体的句子
├── annot_relation_sent.txt # 被标记上关系的句子
├── entities_type_name_dict.json # 标注数据中所有的实体类型,以及属于该类型的所有实体名字
├── relation.csv # 标注数据中的存在的所有数据
├── unannot_entity_sent.txt # [未被]标记上实体的句子
└── unannot_relation_sent.txt # [未被]标记上关系的句子
4.2. 训练
在训练过程中咱们尝试应用了 deepke 所提供的 PCNN, rnn, gcn, capsule, transformer, bert 这些模型,epoch 设置为 50,num_relations
依据咱们数据集的理论状况批改为 19,须要留神的是基于 BERT 的语言模型进行训练时,须要先在相干网页 14 下载好预训练模型
新的数据集有 22 种 关系(包含 None),须要通过 num_relations
来更改
cd deepke-master
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=cnn
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=rnn
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=gcn
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=capsule
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=transformer
# lm bert layer=1
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=lm lm_file=~/ZJU_study/Knowledge_Graph/deepke/pretrained/ num_hidden_layers=1
# lm bert layer=2
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=lm lm_file=~/ZJU_study/Knowledge_Graph/deepke/pretrained/ gpu_id=0 num_hidden_layers=2
# lm bert layer=3
python main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=lm lm_file=/home/zenghao/ZJU_study/Knowledge_Graph/deepke/pretrained/ gpu_id=1 num_hidden_layers=3
4.3. 训练后果
PCNN | RNN | GCN | CAPSULE | TRANSFORMER | LM(BERT) LAYER=1 | LM(BERT) LAYER=2 | LM(BERT) LAYER=3 | |
---|---|---|---|---|---|---|---|---|
VALID | 80.11 | 83.87 | 55.91 | 75.27 | 82.26 | 89.79 | 90.86 | 89.78 |
TEST | 86.18 | 85.64 | 63.15 | 82.66 | 86.18 | 91.87 | 91.33 | 92.14 |
能够到基于 bert 的语言模型成果最好,显著因为其余模型。GCN 的成果最差。这也阐明在小规模数据上利用预训练的语言模型还是可能抽取到比拟好的特色的。
然而在咱们前面对于理论数据的预测后果发现,语言模型的泛化成果仿佛不如 PCNN 模型的好
咱们猜想是因为咱们的数据存在长尾散布问题,模型可能趋向于预测某些特定关系来舞弊,已达到准确率进步的成果
5. 常识计算
5.1. 图计算
常识图谱的一个很重要的特色就是其的图构造,不同实体之间的构造自身就内含着许多的隐式的信息,能够被进一步的开掘利用。
在这部分中,咱们参考别人在相似畛域的实际1516,利用 Neo4j 提供的图算法,对咱们构建的实体关系常识图谱,用图算法进行肯定的计算剖析,包含计算最短门路、要害结点、结点核心度、社区发现等。
5.1.1. 人物网络分析
人物数量
万事以简略开始。先看看上图上由有多少人物:
MATCH (c:`ns0__人 `) RETURN count(c)
count(c) |
---|
134 |
概要统计
统计每个角色接触的其它角色的数目:
MATCH (c:`ns0__人 `)-[]->(:`ns0__人 `)
WITH c, count(*) AS num
RETURN min(num) AS min, max(num) AS max, avg(num) AS avg_characters, stdev(num) AS stdev
min | max | avg_characters | stdev |
---|---|---|---|
1 | 6 | 1.8374999999999997 | 1.1522542572790615 |
图(网络)的直径
网络的直径或者测底线或者最长最短门路:
// Find maximum diameter of network
// maximum shortest path between two nodes
MATCH (a:`ns0__人 `), (b:`ns0__人 `) WHERE id(a) > id(b)
MATCH p=shortestPath((a)-[*]-(b))
RETURN length(p) AS len, extract(x IN nodes(p) | split(x.uri, 'http://kg.course/talkop-vivre-card/deepke')[-1]) AS path
ORDER BY len DESC LIMIT 4
len | path |
---|---|
10 | [“/ 人 / 克拉巴特尔 ”, “/ 职务 / 管家 ”, “/ 人 / 克洛 ”, “/ 职务 / 船长 ”, “/ 人 / 甚平 ”, “/ 事件 / 顶上和平 ”, “/ 人 / 缇娜 ”, “/ 事件 / 世界会议 ”, “/ 人 /Dr. 古蕾娃 ”, “/ 人 / 乔巴 ”, “/ 人 /Dr. 西尔尔克 ”] |
9 | [“/ 人 /Dr. 西尔尔克 ”, “/ 人 / 乔巴 ”, “/ 人 /Dr. 古蕾娃 ”, “/ 事件 / 世界会议 ”, “/ 人 / 伊卡莱姆 ”, “/ 组织 / 草帽一伙 ”, “/ 人 / 库洛卡斯 ”, “/ 地点 / 平凡航路 ”, “/ 人 / 哥尔·D·罗杰 ”, “/ 人 / 西奇 ”] |
9 | [“/ 人 /Dr. 西尔尔克 ”, “/ 人 / 乔巴 ”, “/ 人 /Dr. 古蕾娃 ”, “/ 事件 / 世界会议 ”, “/ 人 / 缇娜 ”, “/ 组织 / 草帽一伙 ”, “/ 人 / 娜美 ”, “/ 组织 / 恶龙一伙 ”, “/ 人 / 哞哞 ”, “/ 人 / 卡里布 ”] |
9 | [“/ 人 / 克拉巴特尔 ”, “/ 职务 / 管家 ”, “/ 人 / 克洛 ”, “/ 职务 / 船长 ”, “/ 人 / 东利 ”, “/ 人 / 路飞 ”, “/ 人 / 克利克 ”, “/ 地点 / 平凡航路 ”, “/ 人 / 哥尔·D·罗杰 ”, “/ 人 / 西奇 ”] |
咱们能看到网络中有许多长度为 9 的门路。
最短门路
应用 Cypher 的 shortestPath 函数找到图中任意两个角色之间的最短门路。让咱们找出 克洛克达尔 和加尔帝诺(Mr.3)之间的最短门路:
MATCH p=shortestPath((n1)-[*]-(n2)
)
WHERE n1.uri CONTAINS '克洛克达尔' and n2.uri CONTAINS '加尔帝诺'
RETURN p
还能够对门路中的结点进行一些限度,例如门路中 不能蕴含某种类型的结点
MATCH p=shortestPath((n1)-[*]-(n2))
WHERE n1.uri CONTAINS '克洛克达尔' and n2.uri CONTAINS '加尔帝诺' and id(n2) > id(n1) and NONE(n IN nodes(p) WHERE n:`ns0__组织 `)
RETURN p
门路中 只能蕴含某种类型的结点
例子:所有从索隆到强尼的 1 到 3 跳的门路中,只通过人物结点的门路
MATCH p=(n1)-[*1..3]-(n2)
WHERE n1.uri CONTAINS '索隆' and n2.uri CONTAINS '强尼' and all(x in nodes(p) where 'ns0__人' IN LABELS(x))
RETURN p
所有最短门路
联结 斯摩格 和一本松 之间的最短门路可能还有其它门路,咱们能够应用 Cypher 的 allShortestPaths 函数来查找:
MATCH (n1:`ns0__人 `), (n2:`ns0__人 `) WHERE n1.uri CONTAINS '克洛克达尔' and n2.uri CONTAINS '加尔帝诺' and id(n2) > id(n1)
MATCH p=allShortestPaths((n1)-[*]-(n2))
RETURN p
5.1.2. 要害节点
在网络中,如果一个节点位于其它两个节点所有的最短门路上,即称为要害节点。上面咱们找出网络中所有的要害节点:
// Find all pivotal nodes in network
MATCH (a:`ns0__人 `), (b:`ns0__人 `) WHERE id(a) > id(b)
MATCH p=allShortestPaths((a)-[*]-(b)) WITH collect(p) AS paths, a, b
MATCH (c:`ns0__人 `) WHERE all(x IN paths WHERE c IN nodes(x)) AND NOT c IN [a,b]
RETURN a.uri, b.uri, c.uri AS PivotalNode SKIP 490 LIMIT 10
a.uri | b.uri | PivotalNode |
---|---|---|
“http://kg.course/talkop-vivre-card/deepke/ 人 / 萨奇斯 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 妮可·罗宾 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 路飞 ” |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 萨奇斯 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 瓦波尔 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 路飞 ” |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 萨奇斯 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 诺琪高 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 路飞 ” |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 萨奇斯 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 诺琪高 ” | “http://kg.course/talkop-vivre-card/deepke/ 人 / 娜美 ” |
从后果表格中咱们能够看出乏味的后果:娜美和路飞是萨奇斯和诺琪高的要害节点。这意味着,所有联结萨奇斯和诺琪高的最短门路都要通过娜美和路飞。咱们能够通过可视化萨奇斯和诺琪高之间的所有最短门路来验证:
MATCH (n1:`ns0__人 `), (n2:`ns0__人 `) WHERE n1.uri CONTAINS '萨奇斯' and n2.uri CONTAINS '诺琪高' and id(n1) <> id(n2)
MATCH p=shortestPath((n1)-[*]-(n2))
RETURN p
5.1.3. 节点核心度
节点核心度给出网络中节点的重要性的绝对度量。有许多不同的形式来度量核心度,每种形式都代表不同类型的“重要性”。
度核心性(Degree Centrality)
度核心性是最简略度量,即为某个节点在网络中的联结数。在《海贼王》的图中,某个角色的度核心性是指该角色接触的其余角色数。作者应用 Cypher 计算度核心性:
MATCH (c:`ns0__人 `)-[]-()
RETURN split(c.uri, 'http://kg.course/talkop-vivre-card/deepke')[-1] AS character, count(*) AS degree ORDER BY degree DESC
character | degree |
---|---|
“/ 人 / 路飞 ” | 33 |
“/ 人 / 缇娜 ” | 20 |
“/ 人 / 娜美 ” | 19 |
“/ 人 / 山治 ” | 15 |
从下面能够发现,在《海贼王》网络中路飞和最多的角色有接触。鉴于他是漫画的配角,咱们感觉这是有情理的。
介数核心性(Betweenness Centrality)
介数核心性:在网络中,一个节点的介数核心性是指其它两个节点的所有最短门路都通过这个节点,则这些所有最短门路数即为此节点的介数核心性。介数核心性是一种重要的度量,因为它能够甄别出网络中的“信息中间人”或者网络聚类后的联结点。
图中红色节点是具备高的介数核心性,网络聚类的联结点。
为了计算介数核心性,须要装置 algo
库
CALL algo.betweenness.stream('ns0__人', 'ns1__遇见',{direction:'both'})
YIELD nodeId, centrality
MATCH (user:`ns0__人 `) WHERE id(user) = nodeId
RETURN user.uri AS user,centrality
ORDER BY centrality DESC;
或者
CALL algo.betweenness.stream('ns0__人', null,{direction:'both'})
YIELD nodeId, centrality
MATCH (user:`ns0__人 `) WHERE id(user) = nodeId
RETURN user.uri AS user,centrality
ORDER BY centrality DESC;
user | centrality |
---|---|
“http://kg.course/talkop-vivre-card/deepke/ 人 / 路飞 ” | 759.0 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 缇娜 ” | 335.0 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 加尔帝诺(Mr.3)” | 330.0 |
NOTE:下面的是不思考方向的,所以设置为 {direction:'both'}
。如果思考方向,能够
- loading incoming relationships: ‘INCOMING’,’IN’,’I’ or ‘<‘
- loading outgoing relationships: ‘OUTGOING’,’OUT’,’O’ or ‘>’
紧度核心性(Closeness centrality)
紧度核心性是指到网络中所有其余角色的均匀间隔的倒数。在图中,具备高紧度核心性的节点在聚类社区之间被高度联结,但在社区之外不肯定是高度联结的。
网络中具备高紧度核心性的节点被其它节点高度联结
MATCH (c:`ns0__人 `)
WITH collect(c) AS characters
CALL algo.closeness.stream('ns0__人', null)
YIELD nodeId, centrality
RETURN algo.asNode(nodeId).uri AS node, centrality
ORDER BY centrality DESC
LIMIT 20;
node | centrality |
---|---|
“http://kg.course/talkop-vivre-card/deepke/ 人 /Miss 黄金周 ” | 1.0 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 范德·戴肯 ” | 1.0 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 杰斯 ” | 1.0 |
5.1.4. 社区发现
CALL algo.beta.louvain.stream(null, null, {
graph: 'huge',
direction: 'BOTH'
}) YIELD nodeId, community, communities
RETURN algo.asNode(nodeId).uri as name, community, communities
ORDER BY community ASC
name | community | communities |
---|---|---|
“http://kg.course/talkop-vivre-card/deepke/ 人 / 瓦波尔 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 组织 / 黑胡子海贼团 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 地点 / 磁鼓岛 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 克罗马利蒙 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 组织 / 磁鼓王国 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 组织 / 医生 20” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 杰斯 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 组织 / 邪恶暗黑磁鼓王国 ” | 151 | null |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 宇宙小姐 ” | 151 | null |
能够看到,根本把瓦波尔那一系列的 community 给检测进去了,包含在磁鼓岛和光明磁鼓王国
5.1.5. PageRank
CALL algo.pageRank.stream('ns0__人', null, {iterations:20, dampingFactor:0.85})
YIELD nodeId, score
RETURN algo.asNode(nodeId).uri AS page,score
ORDER BY score DESC
page | score |
---|---|
“http://kg.course/talkop-vivre-card/deepke/ 人 / 路飞 ” | 2.9112886658942436 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 山治 ” | 1.4952359730610623 |
“http://kg.course/talkop-vivre-card/deepke/ 人 / 拉布 ” | 1.1878799288533628 |
5.2. 常识推理
TODO
6. 常识利用
6.1. 智能问答
在这部分中咱们参考前人的工作 1718,基于 REfO19 实现了一个 KBQA 零碎,次要流程为:解析输出的自然语言问句生成 SPARQL 查问,进一步申请后盾基于 TDB 知识库的 Apache Jena Fuseki 服务, 失去后果。代码和数据寄存在 vivirecard-KB_query
目录下
6.1.1. 反对的问题类型
- 对于生日 / 英文名 / 血型 / 星座 / 霸气 / 身高的查问
- 谁出世在哪里 / 出世在某个中央的有谁
6.1.2. 查问示例
运行 python query_main.py
就能够开始进行 QA 过程
cd vivirecard-KB_query
python query_main.py
间接输出问题,按回车后就会返回答案;当零碎中没有对应常识时,会返回 I don't know. :(
;当零碎无奈了解问题时会返回 I can't understand. :(
-
雷利的身高是多少?
188cm
-
罗杰的血型是啥
S 型
-
谁出世在风车村?
蒙其·D·路飞、玛琪诺、乔路叔 & 鸡婶、乌普·斯拉普
-
出世在可可亚西村的有谁?
娜美、诺琪高、阿健、贝尔梅尔、Dr. 纳克、萨姆
-
我想晓得斯摩格的生日
3 月 14 日
-
特朗普的生日是多少
I don’t know. :(
-
sasdasdasd
I can’t understand. :(
6.2. 常识图谱可视化
在这部分中,咱们参考他人的工作 20,利用 D321 对之前构建的实体关系常识图谱提供可视化交互性能,包含结点连贯关系可视化、查问相干结点信息。同时在这部分也整合了之间构建的人物属性常识图谱,提供了信息框的展现过程,相干的数据和代码寄存在 visualization
目录下。整个可视化页面的交互过程如上面的[gif 图]
可视化网页寄存于 visualization/html/index.html
,能够通过 Microsoft Edge 浏览器间接关上
如果须要在其余浏览器中关上,可能会加载不进去可视化后果。这是因为跨域申请在大多数浏览器中是禁止的,申请不到 json 数据。因而须要用 WAMP/LAMP/MAMP 配置一个 Web 网络环境。
关上后可视化界面如下所示,不同的色彩代表不同类型的实体,具备关系的实体会用红色的细线连贯,能够显著的看到有些实体与其余实体存在大量的连贯
点击左上角的模式切换按钮,咱们能够把结点展现从圆圈模式变换为文本模式,可能进行更加粗疏的察看
选中某个结点后,将只会显示该节点以及与其间接相连接的结点。特地的,如果该节点类型是人物,还会在页面右侧显示该人物的信息框
此外左侧还提供了搜寻框的性能,能够不便咱们查找结点信息
码源下载见文末跳转
码源下载见文末跳转
更多优质内容请关注公号 & 知乎:汀丶人工智能;会提供一些相干的资源和优质文章,收费获取浏览。
本文参加了 SegmentFault 思否写作挑战「摸索编码世界之旅 – 记我的第一份编程工作」,欢送正在浏览的你也退出。
- 1 ↩
- 2 ↩
- 3 ↩
- 4 ↩
- 6 ↩
- 5 ↩
- 7 ↩
- 8 ↩
- 9 ↩
- 11 ↩
- 10 ↩
- 12 ↩
- 13 ↩
- 14 ↩
- 15 ↩
- 16 ↩
- 17 ↩
- 18 ↩
- 19 ↩
- 20 ↩
- 21 ↩