python构建知识图谱_NLP第20课:Neo4j从⼊门到构建⼀个简
单知识图谱
Neo4j 对于⼤多数⼈来说,可能是⽐较陌⽣的。其实,Neo4j 是⼀个图形数据库,就像传统的关系数据库中的 Oracel 和 MySQL⼀样,⽤来持久化数据。Neo4j 是最近⼏年发展起来的新技术,属于 NoSQL 数据库中的⼀种。
本⽂主要从 Neo4j 为什么被⽤来做知识图谱,Neo4j 的简单安装,在 Neo4j 浏览器中创建节点和关系,Neo4j 的 Python 接⼝操作以及⽤ Neo4j 构建⼀个简单的农业知识图谱五个⽅⾯来讲。
Neo4j 为什么被⽤来做知识图谱
从第19课《知识挖掘与知识图谱概述》中,我们已经明⽩,知识图谱是⼀种基于图的数据结构,由节点和边组成。其中节点即实体,由⼀个全局唯⼀的 ID 标⽰,关系(也称属性)⽤于连接两个节点。通俗地讲,知识图谱就是把所有不同种类的信息连接在⼀起⽽得到⼀个关系⽹络,提供了从“关系”的⾓度去分析问题的能⼒。
⽽ Neo4j 作为⼀种经过特别优化的图形数据库,有以下优势:
数据存储:不像传统数据库整条记录来存储数据,Neo4j 以图的结构存储,可以存储图的节点、属性和边。属性、节点都是分开存储的,属性与节点的关系构成边,这将⼤⼤有助于提⾼数据库的性能。
数据读写:在 Neo4j 中,存储节点时使⽤了 Index-free Adjacency 技术,即每个节点都有指向其邻居节点的指针,可以让我们在时间复杂度为 O(1) 的情况下到邻居节点。另外,按照官⽅的说法,在 Neo4j 中边是最重要的,是 First-class Entities,所以单独存储,更有利于在图遍历时提⾼速度,也可以很⽅便地以任何⽅向进⾏遍历。
资源丰富:Neo4j 作为较早的⼀批图形数据库之⼀,其⽂档和各种技术博客较多。
同类对⽐:Flockdb 安装过程中依赖太多,安装复杂;Orientdb,Arangodb 与 Neo4j 做对⽐,从易⽤性来说都差不多,但是从稳定性来说,neo4j 是最好的。
综合上述以及因素,我认为 Neo4j 是做知识图谱⽐较简单、灵活、易⽤的图形数据库。
Neo4j 的简单安装
Neo4j 是基于 Java 的图形数据库,运⾏ Neo4j 需要启动 JVM 进程,因此必须安装 Java SE 的 JDK。从 Oracle 官⽅⽹站下载 Java SE JDK,选择版本 JDK8 以上版本即可。
下⾯简单介绍下 Neo4j 在 Linux 和 Windows 的安装过程。⾸先去官⽹下载对应版本。解压之后,Neo4j 应⽤程序有如下主要的⽬录结构:
bin ⽬录:⽤于存储 Neo4j 的可执⾏程序;
conf ⽬录:⽤于控制 Neo4j 启动的配置⽂件;
data ⽬录:⽤于存储核⼼数据库⽂件;
plugins ⽬录:⽤于存储 Neo4j 的插件。
Linux 系统下的安装
通过 tar 解压命令解压到⼀个⽬录下:
tar -xzvf neo4j-community-3.3.
然后进⼊ Neo4j 解压⽬录:
cd /usr/local/neo4j/neo4j-community-3.1.0
通过启动命令,可以实现启动、控制台、停⽌服务:
bin/neo4j start/console/stop(启动/控制台/停⽌)
通过 cypher-shell 命令,可以进⼊命令⾏:
bin/cypher-shell
在 Neo4j 浏览器中创建节点和关系
下⾯,我们简单编写 Cypher 命令,Cypher 命令可以通过 Neo4j 教程学习,在浏览器中通过 Neo4j 创建两个节点和两个关系。
在 $ 命令⾏中,编写 Cypher 脚本代码,点击 Play 按钮完成创建,依次执⾏下⾯的语句:
CREATE (n:Person { name: 'Andres', title: 'Developer' }) return n;
作⽤是创建⼀个 Person,并包含属性名字和职称。
enter image description here
下⾯这条语句也创建了⼀个 Person 对象,属性中只是名字和职称不⼀样。
CREATE (n:Person { name: 'Vic', title: 'Developer' }) return n;
紧接着,通过下⾯两⾏命令进⾏两个 Person 的关系匹配:
match(n:Person{name:"Vic"}),(m:Person{name:"Andres"}) create (n)-[r:Friend]->(m) return r;
match(n:Person{name:"Vic"}),(m:Person{name:"Andres"}) create (n)
最后,在创建完两个节点和关系之后,查看数据库中的图形:
match(n) return n;
如下图,返回两个 Person 节点,以及其关系⽹,两个 Person 之间组成 Friend 关系:
enter image description here
Neo4j 的 Python 操作
既然 Neo4j 作为⼀个图库数据库,那我们在项⽬中使⽤的时候,必然不能通过上⾯那种⽅式完成任务,
推荐几部好看的小说⼀般都要通过代码来完成数据的持久化操作。其中,对于 Java 编程者来说,可通过 Spring Data Neo4j 达到这⼀⽬的。
⽽对于 Python 开发者来说,Py2neo 库也可以完成对 Neo4j 的操作,操作过程如下。
⾸先 安装 Py2neo。Py2neo 的安装过程⾮常简单,在命令⾏通过下⾯命令即可安装成功。
pip install py2neo
安装好之后,我们来看⼀下简单的图关系构建,看下⾯代码:
from py2neo.data import Node, Relationship
a = Node("Person", name="Alice")
b = Node("Person", name="Bob")
ab = Relationship(a, "KNOWS", b)
第⼀⾏代码,⾸先引⼊ Node 和 Relationship 对象,紧接着,创建 a 和 b 节点对象,最后⼀⾏匹配 a 和 b 之间的⼯作雇佣关系。接着来看看 ab 对象的内容是什么:
print(ab)
通过 print 打印出 ab 的内容:
(Alice)-[:KNOWS {}]->(Bob)
通过这样,就完成了 Alice 和 Bob 之间的⼯作关系,如果有多组关系将构建成 Person 之间的⼀个关系⽹。
了解更多 Py2neo 的使⽤⽅法,建议查看官⽅⽂档。
⽤ Neo4j 构建⼀个简单的农业知识图谱
我们来看⼀个基于开源语料的简单农业知识图谱,由于过程⽐较繁杂,数据和知识图谱数据预处理过程这⾥不再赘述,下⾯,我们重点看基于 Neo4j 来创建知识图谱的过程。
整个过程主要包含以下步骤:
环境准备
语料准备
语料加载
知识图谱查询展⽰阿娇不照雅照片全集
Neo4j 环境准备。
根据上⾯对 Neo4j 环境的介绍,这⾥默认你已经搭建好 Neo4j 的环境,并能正常访问,如果没有环境,请⾃⾏搭建好 Neo4j 的可⽤环境。
本次提供的语料是已经处理好的数据,包含6个 csv ⽂件,⽂件内容和描述如下。
attributes.csv:⽂件⼤⼩ 2M,内容是通过互动百科页⾯得到的部分实体的属性,包含字段:Entity、AttributeName、Attribute,分别表⽰实体、属性名称、属性值。⽂件前5⾏结构如下:
Entity,AttributeName,Attribute
密度板,别名,纤维板
葡萄蔓枯病,主要为害部位,枝蔓
坎德拉,性别,男
坎德拉,国籍,法国
坎德拉,场上位置,后卫
hudong_pedia.csv:⽂件⼤⼩ 94.6M,内容是已经爬好的农业实体的百科页⾯的结构化数据,包含字段:title、url、image、openTypeList、detail、baseInfoKeyList、baseInfoValueList,分别表⽰名称、百科 URL 地址、图⽚、分类类型、详情、关键字、依据来源。⽂件前2⾏结构如下:
"title","url","image","openTypeList","detail","baseInfoKeyList","baseInfoValueList"
"菊糖","www.baike/wiki/菊
糖","a0.att.hudong/72/85/20200000013920144736851207227_s.jpg","健康科学##分⼦⽣物学##化学品##有机物##科学##⾃然科学##药品##药学名词##药物中⽂名称列表","[药理作⽤] 诊断试剂 ⼈体内不含菊糖,静注后,不被机体分解、结合、利⽤和破坏,经肾⼩球滤过,通过测定⾎中和尿中的菊糖含量,可以准确计算肾⼩球的滤过率。菊糖⼴泛存在于植物组织中,约有3.6万种植物中含有菊糖,尤其是菊芋、菊苣块根中含有丰富的菊糖[6,8]。菊芋(Jerusalem artichoke)⼜名洋姜,多年⽣草本植物,在我国栽种⼴泛,其适应性⼴、耐贫瘠、产量⾼、易种植,⼀般亩产菊芋块茎为2 000~4 000 kg,菊芋块茎除⽔分外,还含有15%~20%的菊糖,是加⼯⽣产菊糖及其制品的良好原料。","中⽂名:","菊糖"
"密度板","www.baike/wiki/密度
板","a0.att.hudong/64/31/20200000013920144728317993941_s.jpg","居家##巧克⼒包装##应⽤科学##建筑材料##珠宝盒##礼品盒##科学##糖果盒##红酒盒##装修##装饰材料##隔断##⾸饰盒","密度板(英⽂:Medium Density Fiberboard (MDF))也称纤维板,是以⽊质纤维或其他植物纤维为原料,施加脲醛树脂或其他适⽤的胶粘剂制成的⼈造板材。按其密度的不同,分为⾼密度板、中密度板、低密度板。密度板由于质软耐冲击,也容易再加⼯,在国外是制作家私的⼀种良好材料,但由于国家关于⾼密度板的标准⽐国际标准低数倍,所以,密度板在中国的使⽤质量还有待提⾼。","中⽂名:##全称:##别名:##主要材料:##分类:##优点:","密度板##中密度板纤维板##纤维板##以⽊质纤维或其他植物纤维##⾼密度板、中密度板、低密度板##表⾯光滑平整、材质细密性能稳定"
hudong_pedia2.csv:⽂件⼤⼩ 41M,内容结构和 hudong_pedia.csv ⽂件保持⼀致,只是增加数据量,作为 hudong_pedia.csv 数据的补充。
new_node.csv:⽂件⼤⼩ 2.28M,内容是节点名称和标签,包含字段:title、lable,分别表⽰节点名称、标签,⽂件前5⾏结构如下:
title,lable
药物,newNode
艾伦是谁膳⾷纤维,newNode
Boven Merwede,newNode
亚美尼亚苏维埃百科全书,newNode
wikidata_relation.csv:⽂件⼤⼩ 1.83M,内容是实体和关系,包含字段 HudongItem1、relation、HudongItem2,分别表⽰实体1、
关系、实体2,⽂件前5⾏结构如下:
HudongItem1,relation,HudongItem2
菊糖,instance of,化合物
菊糖,instance of,多糖
⽡尔,instance of,河流
2020我想对你说菊糖,subclass of,⾷物
⽡尔,origin of the watercourse,莱茵河
wikidata_relation2.csv:⼤⼩ 7.18M,内容结构和 wikidata_relation.csv ⼀致,作为 wikidata_relation.csv 数据的补充。
语料加载。
语料加载,利⽤ Neo4j 的 LOAD CSV WITH 功能进⾏加载,具体操作过程如下。
⾸先,依次执⾏以下命令:
// 将hudong_pedia.csv 导⼊
LOAD CSV WITH HEADERS FROM "file:///hudong_pedia.csv" AS line
CREATE
(p:HudongItem{title:line.title,image:line.image,detail:line.detail,url:line.url,openTypeList:line.openTypeList,baseInfoKeyList:line.baseInfo
执⾏成功之后,控制台显⽰成功:
enter image description here
上⾯这张图,表⽰数据加载成功,并显⽰加载的数据条数和耗费的时间。
在挫折中成长作文// 新增了hudong_pedia2.csv
LOAD CSV WITH HEADERS FROM "file:///hudong_pedia2.csv" AS line
CREATE
(p:HudongItem{title:line.title,image:line.image,detail:line.detail,url:line.url,openTypeList:line.openTypeList,baseInfoKeyList:line.baseInfo
// 创建索引
CREATE CONSTRAINT ON (c:HudongItem)
ASSERT c.title IS UNIQUE
鱼香茄子的家常做法以上命令的意思是,将 hudong_pedia.csv 和 hudong_pedia2.csv 导⼊ Neo4j 作为结点,然后对 titile 属性添加 UNIQUE(唯⼀约束/索
引)。
注意: 如果导⼊的时候出现 Neo4j JVM 内存溢出错误,可以在导⼊前,先把 Neo4j 下的 f 中的
下⾯继续执⾏数据导⼊命令:
// 导⼊新的节点
LOAD CSV WITH HEADERS FROM "file:///new_node.csv" AS line
CREATE (:NewNode { title: line.title })
//添加索引
CREATE CONSTRAINT ON (c:NewNode)
ASSERT c.title IS UNIQUE
//导⼊hudongItem和新加⼊节点之间的关系
LOAD CSV WITH HEADERS FROM "file:///wikidata_relation2.csv" AS line
MATCH (entity1:HudongItem{title:line.HudongItem}) , (entity2:NewNode{title:line.NewNode})
CREATE (entity1)-[:RELATION { type: lation }]->(entity2)
LOAD CSV WITH HEADERS FROM "file:///wikidata_relation.csv" AS line
MATCH (entity1:HudongItem{title:line.HudongItem1}) , (entity2:HudongItem{title:line.HudongItem2})
CREATE (entity1)-[:RELATION { type: lation }]->(entity2)
执⾏完这些命令后,我们导⼊ new_node.csv 新节点,并对 titile 属性添加 UNIQUE(唯⼀约束/索引),导⼊ wikidata_relation.csv 和wikidata_relation2.csv,并给节点之间创建关系。
紧接着,继续导⼊实体属性,并创建实体之间的关系:
LOAD CSV WITH HEADERS FROM "file:///attributes.csv" AS line
MATCH (entity1:HudongItem{title:line.Entity}), (entity2:HudongItem{title:line.Attribute})
CREATE (entity1)-[:RELATION { type: line.AttributeName }]->(entity2);
LOAD CSV WITH HEADERS FROM "file:///attributes.csv" AS line
MATCH (entity1:HudongItem{title:line.Entity}), (entity2:NewNode{title:line.Attribute})
CREATE (entity1)-[:RELATION { type: line.AttributeName }]->(entity2);
LOAD CSV WITH HEADERS FROM "file:///attributes.csv" AS line
MATCH (entity1:NewNode{title:line.Entity}), (entity2:NewNode{title:line.Attribute})
CREATE (entity1)-[:RELATION { type: line.AttributeName }]->(entity2);
LOAD CSV WITH HEADERS FROM "file:///attributes.csv" AS line
MATCH (entity1:NewNode{title:line.Entity}), (entity2:HudongItem{title:line.Attribute})
CREATE (entity1)-[:RELATION { type: line.AttributeName }]->(entity2)
这⾥注意,建索引的时候带了 label,因此只有使⽤ label 时才会使⽤索引,这⾥我们的实体有两个 label,所以⼀共做 2*2=4 次。当然也可以建⽴全局索引,即对于不同的 label 使⽤同⼀个索引。
以上过程,我们就完成了语料加载,并创建了实体之间的关系和属性匹配,下⾯我们来看看 Neo4j 图谱关系展⽰。
知识图谱查询展⽰
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论