文章同步个人独立博客
1.本体的创建
本体的作用是描述概念与概念之间的关系。它给出了构成相关领域词汇的基本术语和关系,以及利用这些术语和关系构成的规定这些词汇外延的规则的定义。
利用本体,我们可以统一管理所有的数据,使得数据规范化、并能利用本体进行一定程度的推理,提高自动问答技术的性能。
为了对图书馆的文献资源进行语义化描述,需要构建本体。我们基于DC和DCTERMS元数据标准, 构建了一个元数据本体。
此外,文献资源的描述还涉及到其他信息, 譬如作者名、出版机构名、主题词,分类号等,因为上述资源目前已有成熟的本体用于描述,我们直接对其进行复用或者进行必要的扩展。 采用的本体: FOAF: 描述个人/作者机构;SKOS: 描述受控词表;GeoNames: 描述地名;Event: 描述会议事件。
下面给出自定义本体的结构图:
2.RDF数据的构建
本项目所涉及的数据主要包括图书馆的书目数据,受控词表数据,个人/组织机构数据和地名数据。 其中,图书的书目数据来自南京大学图书馆的MARC书目数据,期刊论文,会议论文和学位论文的书目数据来自CNKI网站,作者信息来自南京大学信息管理学院官方网站中教师的个人网页。
原始数据为HTML文档,基于构建的元数据本体及相关本体(FOAF本体,EVENT本体,SKOS模型),将上述数据转换为RDF/XML格式。
下面给出一个RDF数据的例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
图书元数据(Book.RDF) < dcterms:title xml:lang = "zh" >政务信息资源管理与政府决策</ dcterms:title > < metaonto:abstract xml:lang = "zh" >本书共八章,内容包括:政务信息资源概论、政务信息资源采集与政府决策、政务信息资源组织与政府决策、政务信息处理与政府决策等。 </ metaonto:abstract > < dcterms:format xml:lang = "zh" >242页</ dcterms:format > < metaonto:identifierISBN >9787030220073</ metaonto:identifierISBN > < dcterms:subject xml:lang = "zh" >电子政务</ dcterms:subject > < dcterms:subject xml:lang = "zh" >信息管理</ dcterms:subject > </ metaonto:Book > |
3.关联数据的发布与访问
3.1关联数据的定义
关联数据(即linked data),是一种使得数据之间可以相互链接并变得更加有用的发布结构化数据的方式。它建立在如HTTP、RDF、URIs等标准的WEB技术之上。但是它的目的并不是为人类阅读提供web网页,而是使计算机可以自动的读取它们进而达到信息的共享。使不同来源的数据可以相互链接并被查询。
之所以要进行关联数据的发布,是因为我们项目目标是开发一个针对关联的图书馆资源的自动问答系统,也就是说这些图书馆数据是相互关联的。关联数据就是利用web在数据和不同的数据源间建立特定的链接。要实现轻松共享结构化数据的目标,首要步骤就是将现有资源或新生资源发布为关联数据。
3.2关联数据的构建
图书馆的文献资源之间,文献资源与其他资源之间(譬如知识组织资源,人名,地名)存在着相互联系,我们采用RDF链接显示地表达它们之间存在的各种关联关系,形成图书馆的关联数据。
本系统中用到的数据,相互之间存在着许多联系。这些联系靠RDF:resource标签呈现,一个RDF数据实例里面包含另外一个RDF数据实例的URI。例如,下面三条语句在book和person、organization以及place之间建立了联系:
1
2
3
|
<dcterms:creator
RDF:resource="http://example/nju.edu.cn/person/Xuyan#i"/> <dcterms:publisher
RDF:resource="http://example/nju.edu.cn/organization/YuluPress#i"/> <metaonto:placePublished
RDF:resource="http://example/nju.edu.cn/place/Changsha#i"/> |
下面给出整个系统中所有数据之间的联系,其关联形式如下图所示:
3.3 关联数据的发布
JenaTDB + Fuseki + Pubby。
关联数据的发布主要用到的工具为Fuseki和Pubby。其中Fuseki集成了RDF数据的存储工具TDB和Sparql查询终端。
Pubby的主要作用是在Fuseki提供的Sparql终端上面加一个关联数据接口。使得所有存储在TDB中的RDF数据,可以以关联数据的形式在浏览器中访问。
下面是Fuseki的查询界面及查询结果。
Pubby的使用方法:首先下载最新版本的Pubby,然后安装tomcat或者jetty,这两者为Pubby提供了servlet容器,将Pubby下的webapp文件夹拷贝到tomcat或者Jetty的webapps文件夹下,然后更改/WEB-INF/下的配置文件config.ttl,使其适合自身系统。下面的是Pubby和Fuseki结合工作的结构图。
Pubby的配置文件分为三个部分:前缀声明、server配置、dataset配置。其中server只能有一个,而dataset可以有多个,配置文件的格式如下:
1
2
3
4
5
6
7
8
|
<>
a conf:Configuration; conf:option1
value1; conf:option2
value2; (...) conf:dataset
[ conf:option1
value1; conf:option2
value2; ];. |
配置文件当中提供了许多配置选项,配置选项有的是必须的,有的可以缺省。为了和Sparql终端相连接,需要将conf:SparqlEndpoint设置为如下形式:
conf:SparqlEndpoint ;
3.4 关联数据的访问
采用Sparql查询, Fuseki是一个Sparql查询终端。由于关联数据在发布的时候会对URI进行重写,因此用户在访问关联数据的时候,不能通过实际的URI进行,而必须将URI转换为与Pubby发布结果一致的URL。通过观察可以发现,Pubby在重写URI的时候存在一定的规律,因此我们可以通过这个规律来访问关联数据。
如果Pubby的config.n3配置文件中 conf:webBase的填写如下:
conf:webBase ;
而原始URI为http://example/nju.edu.cn/person/ChenYa#i”,那么发布出来的URI会变成:
http://127.0.0.1:8080/webapp/page/person/Suxinning%23i
我们注意到这个URL和原始的URI有两点区别:
a.example/nju.edu.cn/被替换为127.0.0.1:8080/webapp/page/。
b.“#”被换成了“%23”。
因此,我们可以利用PHP脚本对其进行修改
1
2
3
4
5
|
$rep_str1 = "127.0.0.1:8080/webapp/" ; $rep_str2 = "%23" ; $result = str_replace ( "example/nju.edu.cn/" , $rep_str1 , $var ); echo str_replace ( "#" , $rep_str2 , $result ); |
这样就实现的URI的替换.
4. 问句的预处理
(1)识别用户提问中的命名实体,如书名,人名,组织机构名, 目前采用一种简单而直接的方法,构建一个命名实体列表及其索引,直接在问句中进行字符串匹配查找,然后进行标注, 标注可以采用XML标签;
(2)中文分词软件对中文问句进行分词处理;
(3)采用解析器Standford Parser 对问句进行句法解析。
分词:利用ICTCLAS中文分词
1
2
3
4
5
6
7
8
9
|
package com.xjt.nlp.word; public class
ICTCLAStest { public static
void
main(String[] args) { ICTCLAS
instance=ICTCLAS.getInstance(); String
sentence= "信息检索这本书的作者是谁?" ; System.out.println(instance.paragraphProcess(sentence)); } } |
分词结果为:
1
|
信息/n
检索/v 这/r 本书/r 的/u 作者/n 是/v ?/w |
下面对一个示例问句进行分析:
1
|
e.g.
who wrote books about information retrieval ? |
Parse
1
2
3
4
5
6
7
8
9
|
(ROOT (SBARQ (WHNP
(WP who)) (SQ (VP
(VBD wrote) (NP
(NNS books)) (PP
(IN about) (NP
(NN information) (NN retrieval))))) //这里NP为名词短语,也就是说information retrieval应该可以被识别出来 (.
?))) |
Typed dependencies
1
2
3
4
5
6
|
nsubj(wrote-2,
who-1)// nsubj 代表nominal subject,可以提取出主语who,知道查询的结果应该为WHO,然后通过wrote得到who应该表示creator,于是得到select后面应该为 ?creator 于是得到三元组<?s :creator ?creator> root(ROOT-0,
wrote-2) dobj(wrote-2,
books-3)// dobj代表 direct object,可以提取出type为book ,<?s RDF:type metaonto:book> prep(wrote-2,
about-4) nn(retrieval-6,
information-5)//nn代表noun compound modifier,名词组合,可以得到通过information retrieval通过对词表的匹配得到其为subject,然后得到三元组<?s :subject “information retrieval”> pobj(about-4,
retrieval-6) |
下面得到Sparql查询语句
1
2
3
4
5
6
7
8
9
|
prefix
dcterms:< http: //purl.org/dc/terms/> prefix
metaonto:< http: //example/nju.edu.cn/Ontology/metaonto.owl#> prefix
RDF: < http: //www.w3.org/1999/02/22-RDF-syntax-ns#> select
?creator Where {
?s metaonto:type Book ?s
dcterms:creator ?creator. ?s
dcterms:subject “information retrieval”. } |
5. 问题模板的构建和DEMO系统的开发
目前采用手工的方法自行构建某种类型问题的SPARQL查询模板,将问句手工到映射到对应的模型,在模板的空槽中探入问句中抽取出的命名实体。
本DEMO系统支持自然语言(中文)的查询,用户在浏览器中输入查询问句,系统经过分词,从问句当中提取出用于构造Sparql查询的三元组,然后从系统RDF数据中查询。如果查询到结果,则在浏览器中将结果呈现给用户,否则告诉用户资源不存在。
在中文分词过程中使用了两个词典,一个系统词典和一个用户自定义词典,用户自定义词典主要用途为实例提取。本体的功能主要是为Sparql查询的构造提供查询谓语,如foaf:name。所有的RDF数据都存储在TDB当中。Pubby用于关联数据的发布,让用户可以用URI查询到相同资源的更多信息。
DEMO系统的结构如下:
下面对DEMO系统的实现做一个详细的介绍。
5.1 DEMO系统的分词
这里用到的分词软件为简易中文分词系统(Simple Chinese Word Segmentation,简称SCWS),这是一套基于词频词典的机械式中文分词引擎,它能将一整段的中文文本基本正确地切分成词。该系统的分词算法上并无太多创新成分,采用的是自己采集的词频词典,并辅以一定的专有名称,人名,地名, 数字年代等规则识别来达到基本分词,经小范围测试准确率在 90% ~ 95% 之间, 基本上能满足一些小型搜索引擎、关键字提取等场合运用。
该系统支持用户自定义词典,词典格式为”xxx.xdb”或者”xxx.txt”,两者可以相互转换,词典必须遵循一定的格式,系统提供的词典是通用的互联网信息词汇集,收录了大约 28 万个词。
5.2 DEMO系统的命名实体抽取
在构造Sparql查询时,非常关键的一点就是命名实体的抽取。例如用户查询问句:
1
|
Question:请告诉我数据仓库和数据挖掘这本书的作者和出版社? |
那么我们第一步则需要把“数据仓库和数据挖掘”这个命名实体抽取出来。提取命名实体的办法有很多种。例如,限定用户输入问句时,必须给命名实体一个特殊标识,然后在分词时利用这个标识把命名实体提取出来。但这样对用户而言并不友好,我们不能假定所有的用户都按照我们的要求来提问。为了使系统更加的友好,简单而实用的办法就是自定义一个用户词典,这个词典记录了系统所有RDF数据的命名实体名称。
如果我们不利用用户词典直接对问句进行分词,本例的分词结果为:
1
|
请/告诉/我/数据/仓库/和/数据/挖掘/这/本/书/的/作者/和/出版社/ |
可见系统将“数据仓库和数据挖掘”这个命名实体分割成了“数据/仓库/和/数据/挖掘”,这样在构造Sparql查询时,必定无法查出任何结果,因此这并不是我们所需要的分词结果。
由于scws分词时可以使用多个词典,且用户自定义词典优先级大于系统词典,因此分词过程中会先利用用户词典,然后再使用系统词典。
在小的测试系统当中,我们可以手工将这些词抽取出来,并构建用户词典,但当数据集到达一定数量时,我们可以利用Jena或者php脚本对RDF数据进行读取,抽取出命名实体,并利用程序构造词典。
下面是用户自定义词典的样例:
【注】自定义词典中的TF和IDF利用分词系统提供的一个“新词生词的TF/IDF计算器”获得,此计算器的依据是参照百度搜索结果数量加以计算,计算公式仅适用于 scws 分词,其它用途则只能用于参考。
利用该方法得到的分词结果为:
1
2
3
4
5
6
7
8
9
10
|
请/告诉/我/数据仓库和数据挖掘/这/本/书/的/作者/和/出版社/1 这样就成功的将命名实体提取出来了。 <h4>5.3
DEMO系统的谓语抽取 </h4> Sparql查询的构造需要首先构建主语-谓语-宾语三元组,前面我们已经将命名实体(即实例)提取出来了,实例既可以是主语也可以是宾语,但在该DEMO系统当中,我们假定所有的实例在三元组当中都是作为宾语存在的。 下面一步则需要将谓语从问句中提取出来。如果本体比较庞大,可以利用Jena来解析本体,谓语的提取可以使用Jena解析本体,利用本体当中的RDFs:label标签的描述和分词结果进行匹配,然后得到相对应的查询谓语: 1 dcterms:creator RDFs:label
“作者”@zh; dcterms:publisher RDFs:label
“出版社”@zh; |
对于分词结果当中的“作者”可以得到查询谓语”dcterms:creator”。而对于“出版社”则可以得到谓语”dcterms:publisher”。
另外一个替代方法则是使用数据库,构建一张表格,表格当中存放着Sparql查询所需要的谓语以及本体RDF:label所对于的描述,表格如下:
这样一来,同样可以得到相对应得谓语。而且不需要每次查询时都解析本体,只需要简单的SQL查询和匹配即可。
5.4 DEMO系统的查询构造
获取到宾语和谓语之后,就可以自动生成Sparql查询语句了,在构建查询语句时,可以将查询语句分为三个部分。
第一部分:前缀,即prefix。对于一个封闭的系统,这一部分是固定的,不需要动态生成,只需要在构建查询时填充到Sparql查询中即可。Sparql前缀标识的格式为:
1
|
prefix
dcterms:<http://purl.org/dc/terms/> |
第二部分:查询目标,查询目标可以根据查询谓语获得,如“作者”和“出版社”都是查询目标,因此在动态生成Sparql查询时只需要将这两者作为查询目标即可。
1
|
Select
?author ?publisher |
第三部分:查询主体,前面两个步骤的主要目标就是获得查询语句的主体部分,按照前面的方法我们已经可以获得查询的宾语和谓语,因此查询主体的构造如下:
1
2
3
4
5
|
Where
{ ?s
dcterms:title "数据仓库和数据挖掘"@zh. ?s
dcterms:creator ?author. ?s
dcterms:creator ?publisher } |
当三个部分都构造好之后就可以将他们合并起来,生成一个完整的Sparql查询语句。
1
2
3
4
5
6
7
|
prefix
dcterms:< http: //purl.org/dc/terms/> Select
?author ?publisher Where
{ ?s
dcterms:title "数据仓库和数据挖掘"@zh. ?s
dcterms:creator ?author. ?s
dcterms: publisher ?publisher } |
经过在Fuseki中的测试,查询出来的结果为:
1
2
|
author:<http://example/nju.edu.cn/person/Suxinning#i> |
这样的查询并只能够把查询出来的结果用URI的形式进行展示,为了使系统更加的人性化,可以在已有的Sparql查询语句增加下面两条语句,
1
2
|
?author
foaf:name ?authorname. ?publisher
foaf:name ?publishername. |
并将查询目标改为:?authorname ?publishername。这样就可以查询出作者的名字和出版社的名称。
1
2
|
authorname:"苏新宁"
@zh publishername:"清华大学出版社"
@zh |
6.中期研究成果
(1)实现关联数据的发布,本系统中涉及的所有的图书馆数据都能以关联数据的形式进行发布。
例如:
一本书的URI地址为http://example/nju.edu.cn/book/7302126488#i,Pubby会将该URI自动重写为http://127.0.0.1:8080/webapp/page/book/7302126488%23i。 这本书的出版社为“清华大学出版社”,在系统中所对应的URI地址为http://example/nju.edu.cn/organization/TsinghuaUniversityPress#i,系统同样会自动重写这个URI,使得前面的图书和这个组织机构相互关联。
下图为以关联数据形式发布的“数据仓库和数据挖掘”这本图书的书目元数据。
(2)开发出一个针对语义网数据的自动问答DEMO系统,系统提供自然语言和Sparql查询两种查询界面。SPARQL查询界面可供专业人员使用,直接输入SPARQL查询;自然语言查询界面可以面向普通用户,以自然语言问句的形式输入要查询的信息, 界面更加友好和易用。
所有查询出来的资源,都采用一个URI地址进行表示,这个URI地址时可访问的,能够点击进去显示更多相关信息。
下面给出系统查询演示效果。
自然语言查询演示
1
|
问题1:网络信息资源搜集与利用这本书的作者感兴趣的课题有哪些? |
1
|
问题2:欧石燕老师感兴趣的课题有哪些? |
SPARQL查询演示
下面给出一个Sparql查询,它查询出“苏新宁”老师所著书籍。
1
2
3
4
5
6
7
8
|
prefix
dcterms:< http: //purl.org/dc/terms/> prefix
foaf:< http: //xmlns.com/foaf/1.0/> Select
?title from
< http: //book/book> Where{
?author foaf:name "苏新宁"@zh. ?s
dcterms:creator ?author; dcterms:title
?title. } |
查询结果
(3)完成多篇与本项目相关的综述以及技术博文,详细内容参见附件。
7、研究心得
通过本次项目的经历,我们对语义网的概念有了进一步的了解和认识,接触到了许多语义网相关的前沿技术。例如:SPARQL查询、JENA、ARC2等。不仅如此,我们还学习了许多其他的实用技术,如为了发布关联数据,我们认真学习了PHP脚本语言。为了实现中英文的分词和句子解析树的生成,我们学习了stanford parser和lucene-core提供的中文分词方法。为了学习JENA,我们认真学习了JAVA相关的技术。此外,我们还阅读了许多英文文献,从中汲取了许多知识和思想。
在DEMO系统开发的过程当中,遇到了很多难题。首先,刚开始的着手开发系统时,并没有可以参考的原型,因此,很多实现细节都需要自己边动手写程序,边思考问题如何解决。虽然进入并不如人意。但是进过反复不断的实验和测试,系统最终实现了我们想要的基本功能。
在关联数据的发布中,曾经花了很多时间在测试Pubby上面,无数次的失败使得我们想放弃使用Pubby而使用其他的工具来代替它。但是最终我们还是坚持下来,测试成功,完成了关联数据的发布。
总而言之,本次创新项目,让我们学习到了许多的技术,也锻炼了我们做研究的思维。从中我们体会到了学术研究过程的艰辛与曲折,以及做出成果之后的兴奋感。
8. DEMO系统的小部分的代码
Sparql查询生成函数
1
2
3
4
5
6
7
8
9
10
11
12
|
function case1( $book_query_target , $book_query_pre , $book_arr , $len_book_arr , $main_predicate ){ $Function_Compose_Query =
new FunctionComposeQuery(); $query =" prefix
dcterms:<http: //purl.org/dc/terms/> prefix
metaonto:<http: //example/nju.edu.cn/Ontology/metaonto.owl#> prefix
foaf:<http: //xmlns.com/foaf/1.0/> Select ".$Function_Compose_Query->query_target($book_query_target,$len_book_arr)." from
<http: //book/book> Where { ".$Function_Compose_Query->book_query($book_arr,$book_query_pre,$book_query_target,$main_predicate)." }"; return $query ; } |
结果处理程序片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php function URIprocess( $urivar ){ $var = $urivar ; $rep_str1 = "127.0.0.1:8080/webapp/page/" ; $rep_str2 = "%23" ; $result = str_replace ( "example/nju.edu.cn/" , $rep_str1 , $var ); $res = str_replace ( "#" , $rep_str2 , $result ); echo "<td
style=\"word-break:break-all\" width=\"5%\"><a href=" . $res . "
target=\"_blank\">" ; echo $urivar ; echo "</a></td>" ; } else { echo "<td
style=\"word-break:break-all\" width=\"5%\">" ; //print_r($urivar); echo $urivar ; echo "<br/></td>" ; } } ?> |
ARC2配置片段
1
2
3
4
5
6
7
8
|
/*
configuration */ $config =
array ( /*
remote endpoint */ ); /*
instantiation */ $store =
ARC2::getRemoteStore( $config ); |
自然语言处理的程序片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?php function languageparser( $text ){ $sh =
scws_open(); scws_set_charset( $sh , 'utf8' ); //添加自己的词典,该词典用于书名、人名等的查询;这样就可以把书名和人名等完整的分类出来; scws_add_dict( $sh , 'D:/Program
Files/scws/etc/mydict.txt' ,SCWS_XDICT_TXT); //系统默认的词典 scws_add_dict( $sh , 'D:/Program
Files/scws/etc/dict.utf8.xdb' ); scws_set_rule( $sh , 'D:/Program
Files/scws/etc/rules_cht.utf8.ini' ); //送入函数进行句子处理 scws_send_text( $sh , $text ); //获取结果 $top =scws_get_result( $sh ); //返回结果 return $top ; } ?> |
参考网站:scws