作者寄语:
刚开始接触知识图谱不久,看过一些知识图谱视频及论文后,想自己亲手做实验来验证下所学的知识。于是开始在网上查看各种实验,找到了一个比较全面的实验,能更让人理解这里面的层层关系:如何构建本体,如何获取数据,如何将数据表转成三元组关系,如何使用三元组关系进行查询,如何最终与python相连接等等。这是一个以电影及人物为知识库的知识问答系统。
使用到的工具及版本:
网上虽然做这个实验的不少,但是本人查看了很多,几乎每个人用的版本不同出现的问题也不同,出现问题时有以下几个解决方案:1.去官网查看配置文件是否需要更改,有时是因为版本太新导致实验中的配置文件不能使用。2.下载之前的版本。3.查看别人的解决方案。
我使用到的工具:
mysql8.0(建议下载5.0+版本,否则之后使用d2rq会出现问题,因为d2rq源码支持5.1版本)
navicat for mysql
protege5.5.0
JAVA JDK 1.8
d2qr
Apache-jena及Apache-jena-fuseki3.7.0
python
pycharm编辑器
第三方库SPARQLWrapper
工具的下载这里就不多说了,网上很多详细教程,大家自行查看。
步骤一:数据的导入及构建本体
数据的导入:
运行sql文件导入数据表。数据表一共有5个:演员表、电影信息表、电影-演员表、电影类型表、电影-类型表。
或者根据自己的需要军进行自定义数据表。
导入后结果如下:
构建本体:
使用protege构建本体,最终结果是生成一个ontology.owl的文件。
构建过程如下:
1.点击“Entities”tab标签,选择“Classes”标签。在"owl:thing"下,我们创建三个类:movie、person、genre。右下方还可以设置描述该类的特性。
2.然后切换到"Object Properties"页面,我们在此界面创建类之间的关系,即,对象属性。这里我们创建了三个对象属性:"hasActedIn""hasActor""hasGenre"。"domain"表示该属性是属于哪个类的,"range"表示该属性的范围定义。Inverse Of表示该属性与"hasActor"互为相反属性。"SubProperty Of"指子属性关系。"Equivalent To"指相等属性关系。这里根据自己需求进行定义。
3.添加数据属性,"range"可以限制数据属性的类型,"domains"定义该属性属于的类别,还有定义子属性等。
4.使用OntoGraf进行展示,点击"Window"选项,在"Tabs"中选择"OntoGraf"。如果没有完全显示,点击图中的"+"即可生成。如果不小心把该页面关闭,可以在"Window"-->Views-->class views标签里选择OntoGraf即可显示。最终如下图:
最后将文件保存为“ontology.owl”。
步骤二:使用d2qr将数据表转成三元组关系
1.下载D2RQ,进入其目录,运行下面的命令生成默认的mapping文件:
generate-mapping -u root -p **密码** -o kg_demo_movie_mapping.ttl jdbc:mysql:///kg_demo_movie
-u 用户名 -p数据库密码 -o指定输出文件路径及名称,jdbc:mysql:///kg_demo_movie 指定我们要映射的数据库,根据我们的mysql数据库生成的默认mapping文件。
2.修改mapping文件
根据我们定义的本体修改的mapping文件。为了表达简洁,我们给本体的IRI设置一个前缀。
@prefix : <http://www.kgdemo.com>
这样,<http://www.kgdemo.com#person>就可以表示为:person 方便查询及使用。
3.使用下面的命令将我们的数据转为RDF:
.\dump-rdf.bat -o kg_demo_movie.nt .\kg_demo_movie_mapping.ttl
转换后结果片段如下图:
d2rq也可支持sparql查询,但是不支持复杂推理,因此我们需要用到Apache-jena。(本文没有涉及推理,日后会更新)
步骤三:Fuseki及SPARQL查询
1.下载Apache-jena及Apache-jena-fuseki3.7.0:
解压Apache-jena和Apache-jena-fuseki-3.7.0.zip文件。
右击“我的电脑”-->“属性”-->“高级系统设置”-->“环境变量”配置环境变量。
新建两个变量:“JENA_HOME”,值为apche-jena-3.7.0对应的路径"D:\apache-jena\apache-jena-3.7.0";"FUSEKI_HOME",值为
apche-jena-fuseki-3.7.0对应的路径。在PATH中添加“%JENA_HOME%\bin;”和“%FUSEKI_HOME%\bin;”。
2.创建一个目录命名为“tdb”,用于存放tdb数据。进入“apache-jena-3.7.0”文件夹的bat目录,可以看到很多批处理文件,使用“tdbloader.bat”将之前我们的RDF数据以TDB的方式存储。
.\tdbloader.bat --loc="D:\apache-jena\tdb" "D:\d2rq\kg_demo_movie.nt"
3.进入入“apache-jena-fuseki-3.7.0”文件夹,运行“fuseki-server.bat”,然后退出。程序会为我们在当前目录自动创建“run”文件夹。将本体文件“ontology.owl”移动到“run”文件夹下的“databases”文件夹中,并将“owl”后缀名改为“ttl”。在“run”文件夹下的“configuration”中,我们创建名为“fuseki_conf.ttl”的配置文件,加入如下内容:
@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
@prefix fuseki: <http://jena.apache.org/fuseki#> .
<#service1> rdf:type fuseki:Service ;
fuseki:name "kg_demo_movie" ;
fuseki:serviceQuery "sparql", "query" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#dataset> ;
.
<#dataset> rdf:type ja:RDFDataset ;
ja:defaultGraph <#modelInf> ;
.
<#modelInf> rdf:type ja:InfModel ;
ja:baseModel <#g> ;
.
<#g> rdf:type tdb:GraphTDB ;
tdb:location "D:/apache-jena/tdb" ;
tdb:unionDefaultGraph true ;
.
再次运行“fuseki-server.bat”,成功启动服务后,出现如下界面:
Fuseki默认的端口是3030,浏览器访问“http://localhost:3030/”:
点击query,可以进行SPARQL查询:
PREFIX : <http://www.kgdemo.com#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT * WHERE {
?x :personName ?n.
}
查询结果:
4.错误及解决方案:下载Apache-jena及Apache-jena-fuseki3.7.0版本,之前下载过3.12.0版本,但是报很多错误(最终也可以执行,不过配置文件应该也需要更改,最开始使用的配置文件在这里:fuseki-conf.ttl,后来更改了配置文件就是文中的。在这里只列出之前我遇到的错误):
Error1:
Server ERROR Exception in initialization: Failed reading assembler description: java.nio.charset.MalformedInputException: Input length = 1
解决方案:把配置文件中的#中文 删掉就可以了
Error2:
WebAppContext WARN Failed startup of context o.e.j.w.WebAppContext@2adddc06{/,file:///home/xxx/kg/apache-jena-fuseki-3.12.0/webapp/,UNAVAILABLE}
org.apache.jena.assembler.exceptions.TransactionAbortedException: the loading of content into file:///home/xxx/kg/apache-jena-fuseki-3.12.0/run/configuration/fuseki_conf.ttl#model_inf was aborted because of Read-only object file
解决方案:把conf文件里的ja:baseModel <#tdbGraph> ;改为 ja:MemoryModel <#tdbGraph>
Error3:
ERROR [line: 1, col: 7 ] Bad character in IRI (space): <?xml[space]...>
Server ERROR Exception in initialization: caught: [line: 1, col: 7 ] Bad character in IRI (space): <?xml[space]...>
解决方案:构建的本体模型默认是rdf/xml Syntax格式,这里需要更改为tyrtle syntax
步骤四:使用python进行查询
那么怎样将python与SPARQL结合起来查询呢?首先我们需要下载Python第三方库:SPARQLWrapper,执行命令下载:
pip install sparqlwrapper
下面是通过SPARQLWrapper,向apache-jena endpoint发送查询“章子怡参演的评分大于6的电影有哪些”,得到结果的代码。
from SPARQLWrapper import SPARQLWrapper, JSON
sparql = SPARQLWrapper("http://localhost:3030/kg_demo_movie/sparql")
sparql.setQuery("""
PREFIX : <http://www.kgdemo.com#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?n WHERE {
?s rdf:type :Person.
?s :personName '章子怡'.
?s :hasActedIn ?o.
?o :movieTitle ?n.
?o :movieRating ?r.
FILTER (?r >= 6)
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query().convert()
for result in results["results"]["bindings"]:
print('%s' % ( result["n"]["value"]))
查询结果:
参考链接:
https://blog.csdn.net/qingdujun/article/details/82501166
https://zhuanlan.zhihu.com/knowledgegraph
转载或引用请注明作者链接。