常识图谱之《海贼王-ONEPICE》畛域图谱我的项目实战(含码源):数据采集、常识存储、常识抽取、常识计算、常识利用、图谱可视化、问答零碎(KBQA)等

实体关系可视化页面可视化页面尝鲜

1. 我的项目背景& 我的项目内容

《海贼王》(英文名ONE PIECE) 是由日本漫画家尾田荣一郎创作的热血少年漫画,因为其巨大的世界观、丰盛的人物设定、精彩的故事情节、草蛇灰线的伏笔,受到世界各地的读者欢送,截止2019年11月7日,寰球销量冲破4亿6000万本1,并被吉尼斯世界纪录官网认证为“世界上发行量最高的繁多作者创作的系列漫画”2

《海贼王》从1997年开始连载至今,以及将近22年,在900多话的漫画中大量性情显明的角色相继退场,故事产生的地点也在一直变动,这既给咱们带来浏览的乐趣,同时也为咱们梳理故事脉络带来了挑战。

本次工作试图为《海贼王》中呈现的各个实体,包含人物、地点、组织等,构建一个常识图谱,帮忙咱们更好的了解这部作品。

本我的项目内容包含数据采集、常识存储、常识抽取、常识计算、常识利用五大部分

  1. 数据采集

    本次我的项目次要采集构建了两个常识图谱和一个关系抽取数据集

    • 人物常识图谱:次要蕴含各个人物的信息
    • 关系抽取数据集:标注出自然语言中存在的实体以及他们之间的关系
    • 实体关系常识图谱:构建《海贼王》中各个实体之间关系的常识图谱
  2. 常识存储

    尝试应用了三元组数据库Apace Jena和原生图数据库Neo4j,并别离应用RDF结构化查询语言SPARQL和属性图查询语言Cypher,在常识图谱上进行查问。

  3. 常识抽取

    基于之间构建的关系抽取数据集,利用deepke中提供的工具进行关系抽取实际,测试了包含PCNN、GCN、BERT等模型在咱们构建数据集上的成果

  4. 常识计算

    • 图计算:在Neo4j上对实体关系常识图谱进行了图开掘,包含最短门路查问、权威结点发现、社区发现等
    • 常识推理:在Apache Jena上对关系常识图谱进行了常识推理,补全了一部分的数据
  5. 常识利用

    • 智能问答:基于REfO实现一个对于《海贼王》中人物的知识库问答零碎(KBQA)。
    • 可视化图片:通过D3对实体关系图片进行可视化,并整合了人物常识图谱中的信息,进行展现。

码源下载见文末跳转

码源下载见文末跳转

2.数据采集

  • 数据起源

本次我的项目中所应用的数据次要起源为两个:一个是从别的常识图谱中获取曾经存在的常识信息,另一个是从相干网页中爬取解析半结构化的自然语言文本信息

2.1 人物常识图谱构建

2.1.1 抽取通用常识图谱中已有的指标域常识

常识图谱技术近些年来疾速倒退,一些公司机构曾经构建了许多通用常识图谱,咱们能够从中抽取出咱们指标畛域内相干的实体常识信息,作为咱们常识图谱的冷启动数据。

CN-DBpedia3是由复旦大学常识工场4实验室研发并保护的大规模通用畛域结构化百科,咱们抉择其作为通用常识图谱起源。

整个解决流程如下:

  1. 构建《海贼王》实体词汇库
  2. 获取实体列表
  3. 筛选实体列表
  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论坛中相干网页中存在的半结构化信息,构建对应人物的常识图谱。

抽取流程

因为格局较为固定,因而采纳模板匹配的形式来抽取常识,整个流程如下:

  1. 从网页中获取原始文本信息
  2. 人工删除不相干的文本
  3. 利用代码以模板匹配的形式,主动抽取人物属性信息

    cd talkoppython parse_processed_manual_talkop_vivre_card.py

    输入的文件保留在 talkop/data/processed_manual_talkop_vivre_card 文件夹中,每个网页对应着三个输入文件

    • xxx-predicate_key_list.txt:所有解析失去的predicate
    • xxx-entities_id_name_list.txt:所有解析失去的id和实体名
    • xxx-entities_avpair.json:抽取到所有实体的属性常识,以json的格局保留
  4. 人工校验:例如:查看是否抽取到了所有的实体、通过查看抽取的predicate后果来调整模板。整个过程中是代码主动抽取和人工校验形成闭环的过程,在闭环过程中一直补充模板信息,改善抽取后果

在整个过程中,2、3、4是一直周而复始的过程,直至抽取的常识满足咱们的须要。

汇总后果

在下面局部中,咱们别离抽取了各个网页中人物实体的属性信息,当初将这些信息进行进一步的汇总

cd talkoppython 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格局,其具体模式如下所示,其中 TE 别离示意标注出的实体信息和关系信息

    {    "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_typetail_typerelationindexfreq
    NoneNoneNone00
    事件参加136
    同盟21
    夫妻33
    战斗438
    母亲53
    父亲64
    老师76
    遇见8100
    地点出生地93
    地点到过10145
    恶魔果实领有果实1110
    组织创立1223
    组织退出1366
    组织属于1438
    组织战斗1520
    组织来到1618
    组织遇见1714
    组织领导1815
    职务负责1970
    船只建造202
    组织组织战斗211

    这些关系的频数柱状图如下图所示,能够看到这些关系展现出显著的长尾散布

  • 训练正样本个数:616个

2.4 实体关系常识图谱构建

在进行关系抽取数据集的标注过程中,咱们将标注的实体和关系独自导出,构建《海贼王》实体关系数据集

在上述过程中,一共标注了307个不同的实体,569个不同结点间的关系

cd deepke-masterpython 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 talkoppython avpair2ntriples_talkop_vivre_card.py

导出的 N-Triple 格局的数据保留在 talkop/data/processed_manual_talkop_vivre_card/ntriples_talkop_vivre_card.nt,一共有14055个,其中非空triples有12863个

NOTE:

  1. 在我的项目构建过程中,咱们也将从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在咱们构建的数据库上进行查问的示例

  1. 查问前五个角色的身高

    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" ,
  2. 筛选生日范畴

    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-masterpython 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\binneo4j.bat console

之后拜访: http://localhost:7474/ 就能够了

默认的用户名和明码都是 neo4j

Cypher 最后是图数据库 Neo4j 中实现的属性图数据查询语言,是一种申明式的语言,用户只须要申明查什么,而不须要关系怎么查。

上面给出了应用Cypher在咱们构建的数据库上进行查问的示例

  1. 导入

    CREATE INDEX ON :Resource(uri)                          CALL semantics.importRDF("file:///${PROJECT_PATH}/deepke-master/data/vivrecard/summary/vivrecard_ntriples.nt","N-Triples")
  2. 查看schema

    call db.schema()

    把resource屏蔽掉,就能分明的看到schema了

  1. 查问前100集体

    MATCH (n:ns0__人) RETURN n LIMIT 100

  1. 查问属于人的结点中,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/人/薇薇"
  2. 依据uri筛选名字间最短门路

    MATCH p=shortestPath((n1)-[*]-(n2))WHERE n1.uri CONTAINS '斯摩格' and n2.uri CONTAINS '罗宾'RETURN p

  1. 依据名字筛选德雷斯罗萨到司法岛外面四跳的门路

    # 五跳内能到的所有门路# 9312 多萝菲(Miss.圣诞快乐)# 9306 本·贝克曼MATCH p = ((n1)-[*4]-(n2))WHERE n1.uri CONTAINS '司法岛' and n2.uri CONTAINS '德雷斯罗萨'RETURN p

    能够发现这外面存在一些环路的状况,即同一个结点在门路中呈现两次

4. 常识抽取

DeepKE13基于 Pytorch 的深度学习中文关系抽取解决套件。在这部分中咱们利用之前构建的关系抽取数据集和deepke,进行中文关系抽取实际

4.1. 数据转换&标注统计

在这部分,咱们须要实现以下三局部内容:

  1. 将咱们的标注后果转换为deepke所接管的格局
  2. 为了保障关系散布平均,将数据随机打乱
  3. 实现训练集、测试集、验证集的划分,目前按 7:2:1进行划分

应用 deepke-master/utils/convert_vivrecard2deepke.py 实现数据格式转换

cd deepke-masterpython utils/convert_vivrecard2deepke.py

输入

一共有616个训练正样本,其中train、test、valid别离有:431/123/62个

输入的文件保留在 deepke-master/data/vivrecard/ 中的 originsummary 文件夹中

├── 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-masterpython main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=cnnpython 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=gcnpython main.py show_plot=False data_path=data/vivrecard/origin out_path=data/vivrecard/out num_relations=22 epoch=50 model=capsulepython 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=1python 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=2python 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=3python 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. 训练后果

PCNNRNNGCNCAPSULETRANSFORMERLM(BERT) LAYER=1LM(BERT) LAYER=2LM(BERT) LAYER=3
VALID80.1183.8755.9175.2782.2689.7990.8689.78
TEST86.1885.6463.1582.6686.1891.8791.3392.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 numRETURN min(num) AS min, max(num) AS max, avg(num) AS avg_characters, stdev(num) AS stdev
minmaxavg_charactersstdev
161.83749999999999971.1522542572790615

图(网络)的直径

网络的直径或者测底线或者最长最短门路:

// Find maximum diameter of network// maximum shortest path between two nodesMATCH (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 pathORDER BY len DESC LIMIT 4
lenpath
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 networkMATCH (a:`ns0__人`), (b:`ns0__人`) WHERE id(a) > id(b)MATCH p=allShortestPaths((a)-[*]-(b)) WITH collect(p) AS paths, a, bMATCH (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.urib.uriPivotalNode
"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
characterdegree
"/人/路飞"33
"/人/缇娜"20
"/人/娜美"19
"/人/山治"15

从下面能够发现,在《海贼王》网络中路飞和最多的角色有接触。鉴于他是漫画的配角,咱们感觉这是有情理的。

介数核心性(Betweenness Centrality)

介数核心性:在网络中,一个节点的介数核心性是指其它两个节点的所有最短门路都通过这个节点,则这些所有最短门路数即为此节点的介数核心性。介数核心性是一种重要的度量,因为它能够甄别出网络中的“信息中间人”或者网络聚类后的联结点。

图中红色节点是具备高的介数核心性,网络聚类的联结点。

为了计算介数核心性,须要装置 algo

CALL algo.betweenness.stream('ns0__人', 'ns1__遇见',{direction:'both'})YIELD nodeId, centralityMATCH (user:`ns0__人`) WHERE id(user) = nodeIdRETURN user.uri AS user,centralityORDER BY centrality DESC;       或者       CALL algo.betweenness.stream('ns0__人', null,{direction:'both'})YIELD nodeId, centralityMATCH (user:`ns0__人`) WHERE id(user) = nodeIdRETURN user.uri AS user,centralityORDER BY centrality DESC;
usercentrality
"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 charactersCALL algo.closeness.stream('ns0__人', null)YIELD nodeId, centralityRETURN algo.asNode(nodeId).uri AS node, centralityORDER BY centrality DESCLIMIT 20;
nodecentrality
"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, communitiesRETURN algo.asNode(nodeId).uri as name, community, communitiesORDER BY community ASC
namecommunitycommunities
"http://kg.course/talkop-vivre-card/deepke/人/瓦波尔"151null
"http://kg.course/talkop-vivre-card/deepke/组织/黑胡子海贼团"151null
"http://kg.course/talkop-vivre-card/deepke/地点/磁鼓岛"151null
"http://kg.course/talkop-vivre-card/deepke/人/克罗马利蒙"151null
"http://kg.course/talkop-vivre-card/deepke/组织/磁鼓王国"151null
"http://kg.course/talkop-vivre-card/deepke/组织/医生20"151null
"http://kg.course/talkop-vivre-card/deepke/人/杰斯"151null
"http://kg.course/talkop-vivre-card/deepke/组织/邪恶暗黑磁鼓王国"151null
"http://kg.course/talkop-vivre-card/deepke/人/宇宙小姐"151null

能够看到,根本把瓦波尔那一系列的community给检测进去了,包含在磁鼓岛和光明磁鼓王国

5.1.5. PageRank

CALL algo.pageRank.stream('ns0__人', null, {iterations:20, dampingFactor:0.85})YIELD nodeId, scoreRETURN algo.asNode(nodeId).uri AS page,scoreORDER BY score DESC
pagescore
"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. 反对的问题类型

  1. 对于生日/英文名/血型/星座/霸气/身高的查问
  2. 谁出世在哪里/出世在某个中央的有谁

6.1.2. 查问示例

运行 python query_main.py 就能够开始进行QA过程

cd vivirecard-KB_querypython query_main.py

间接输出问题,按回车后就会返回答案;当零碎中没有对应常识时,会返回 I don't know. :(;当零碎无奈了解问题时会返回 I can't understand. :(

  1. 雷利的身高是多少?

    188cm
  2. 罗杰的血型是啥

    S型
  3. 谁出世在风车村?

    蒙其·D·路飞、玛琪诺、乔路叔&鸡婶、乌普·斯拉普
  4. 出世在可可亚西村的有谁?

    娜美、诺琪高、阿健、贝尔梅尔、Dr.纳克、萨姆
  5. 我想晓得斯摩格的生日

    3月14日
  6. 特朗普的生日是多少

    I don't know. :(
  7. sasdasdasd

    I can't understand. :(

6.2. 常识图谱可视化

在这部分中,咱们参考他人的工作20,利用D321对之前构建的实体关系常识图谱提供可视化交互性能,包含结点连贯关系可视化、查问相干结点信息。同时在这部分也整合了之间构建的人物属性常识图谱,提供了信息框的展现过程,相干的数据和代码寄存在 visualization 目录下。整个可视化页面的交互过程如上面的[gif图]

可视化网页寄存于 visualization/html/index.html,能够通过 Microsoft Edge 浏览器间接关上

如果须要在其余浏览器中关上,可能会加载不进去可视化后果。这是因为跨域申请在大多数浏览器中是禁止的,申请不到json数据。因而须要用 WAMP/LAMP/MAMP 配置一个Web网络环境。

关上后可视化界面如下所示,不同的色彩代表不同类型的实体,具备关系的实体会用红色的细线连贯,能够显著的看到有些实体与其余实体存在大量的连贯

点击左上角的模式切换按钮,咱们能够把结点展现从圆圈模式变换为文本模式,可能进行更加粗疏的察看

选中某个结点后,将只会显示该节点以及与其间接相连接的结点。特地的,如果该节点类型是人物,还会在页面右侧显示该人物的信息框

此外左侧还提供了搜寻框的性能,能够不便咱们查找结点信息

码源下载见文末跳转

码源下载见文末跳转

更多优质内容请关注公号&知乎:汀丶人工智能;会提供一些相干的资源和优质文章,收费获取浏览。

本文参加了 SegmentFault 思否写作挑战「摸索编码世界之旅 - 记我的第一份编程工作」,欢送正在浏览的你也退出。


  1. 1 ↩
  2. 2 ↩
  3. 3 ↩
  4. 4 ↩
  5. 6 ↩
  6. 5 ↩
  7. 7 ↩
  8. 8 ↩
  9. 9 ↩
  10. 11 ↩
  11. 10 ↩
  12. 12 ↩
  13. 13 ↩
  14. 14 ↩
  15. 15 ↩
  16. 16 ↩
  17. 17 ↩
  18. 18 ↩
  19. 19 ↩
  20. 20 ↩
  21. 21 ↩