IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML  >

Thinking XML: 使用 XML WordNet 服务器系统增强搜索引擎

包括使用 XSLT 建立 WordNet 数据的 RDF/XML 表示

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论


级别: 中级

Uche Ogbuji (uche.ogbuji@fourthought.com), 首席顾问, Fourthought Inc.

2005 年 12 月 27 日

本专栏的上一期中,Uche Ogbuji 介绍了 WordNet 自然语言数据库,并说明如何用 XML 表示数据库节点和通过 Web 提供该 XML 文档。本文介绍如何将 XML 转换成 RDF 表示,以及如何使用 WordNet XML 服务器改进搜索引擎技术。

上两期文章,“查询 XML 格式的 WordNet” 和 “Thinking XML: 以 XML 形式提供 WordNet ” 中,我给出了对 WordNet 项目进行基于 XML 的处理的代码。WordNet 代表了和本专栏中心主题平行的一个重要研究方向:Thinking XML 讨论 XML 的语义,WordNet 则提供了自然语言本身语义的粗略模型。这里说粗略 并非轻视,因为数千年来的语言哲学表明要建立自然语言真正严格意义上的模型是很难的(甚至是不可能的)。目前对基于 Web 的系统(包括 XML)建模的最广泛的系统是 RDF。因此本文将提出到目前为止一直讨论的 XML WordNet 系统的 RDF 表示作为结束。我还将说明如何使用 WordNet XML 表示和服务器来改进搜索引擎。

源自 XML 的 RDF

要创建 RDF/XML 格式,您可以在本系列的 第一期文章 关于 XML 表示的讨论中找到 WordNet 需要的所有信息内容。首先看 清单 1,它给出了单词 “selection” 的同义词集(synset)的例子。


清单 1. 关于单词 “selection” 的第一个序列化的同义词集
<?xml version="1.0" encoding="UTF-8"?>
<noun xml:id="152253">
  <gloss>the act of choosing or selecting; "your choice of colors was 
  unfortunate"; "you can take your pick"</gloss>
  <word-form>choice</word-form>
  <word-form>selection</word-form>
  <word-form>option</word-form>
  <word-form>pick</word-form>
  <hypernym part-of-speech="noun" target="32816"/>
  <frames part-of-speech="verb" target="653781"/>
  <frames part-of-speech="verb" target="656613"/>
  <frames part-of-speech="verb" target="652154"/>
  <hyponym part-of-speech="noun" target="152613"/>
  <hyponym part-of-speech="noun" target="152749"/>
  <hyponym part-of-speech="noun" target="152898"/>
  <hyponym part-of-speech="noun" target="153642"/>
  <hyponym part-of-speech="noun" target="154057"/>
  <hyponym part-of-speech="noun" target="170871"/>
  <hyponym part-of-speech="noun" target="173378"/>
</noun>
  

现在遇到了最困难的部分:决定采用何种 RDF 模式。围绕着 WordNet 的 RDF 表示有大量的活动。最近的官方研究是 W3C 在 2004 年中期发表的 “Wordnet in RDFS and OWL” 初步草案。但是这项工作还远远没有完成,其他一些人和组织,包括 Chilean 的研究员 Alvaro Graves,已经在着手改进它。(关于这些研究的更多信息请参阅 参考资料。)我决定建立一种轻型的 RDF/XML 表示,与 W3C 的研究兼容,但是没有使用其中那些含混的内容。如果用这种格式表示,清单 1 的等价形式如 清单 2 所示。


清单 2. 清单 1 的 RDF/XML 表示

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:wn="http://uche.ogbuji.net/tech/rdf/wordnet/"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <wn:SynSet rdf:about="noun/152253">
  <wn:glossaryEntry>
    the act of choosing or selecting; "your choice of colors was unfortunate";
    "you can take your pick"
  </wn:glossaryEntry>
  <wn:wordForm>choice</wn:wordForm>
  <wn:wordForm>selection</wn:wordForm>
  <wn:wordForm>option</wn:wordForm>
  <wn:wordForm>pick</wn:wordForm>
  <wn:hypernym rdf:resource="noun/32816"/>
  <wn:frames rdf:resource="verb/653781"/>
  <wn:frames rdf:resource="verb/656613"/>
  <wn:frames rdf:resource="verb/652154"/>
  <wn:hyponym rdf:resource="noun/152613"/>
  <wn:hyponym rdf:resource="noun/152749"/>
  <wn:hyponym rdf:resource="noun/152898"/>
  <wn:hyponym rdf:resource="noun/153642"/>
  <wn:hyponym rdf:resource="noun/154057"/>
  <wn:hyponym rdf:resource="noun/170871"/>
  <wn:hyponym rdf:resource="noun/173378"/>
  </wn:SynSet>
</rdf:RDF>

W3C 还没有为 RDF 格式的 WordNet 建立名称空间,我暂时选择了 http://uche.ogbuji.net/tech/rdf/wordnet/。我使用和 WordNet 指针同名的关系建立同义词集间的指针(hypernymframes 等)。W3C 工作组似乎倾向于专门的属性名(如 hypernymOf),我不认为这是一个好主意,因为每当 WordNet 建立新的基于指针的关系时都要重新修订模式。





回页首


进行转换

我一直感兴趣的是确定多大程度上 XML 本身可以作为 RDF 模型的源格式,而不需要各种繁琐的 RDF/XML 格式。上一期文章(请参阅 参考资料)已经介绍了这一点。我发现最可行的办法是使用 XSLT 将 XML 转化成 RDF/XML,然后再导入一个 RDF 模型。理想情况下可使用 4Suite 资料库(参见 参考资料)这样的工具,完全不需要考虑中间的 RDF/XML 格式。现在已经看到了 WordNet 将要使用的 RDF/XML 格式(清单 2),因此只需要一个从 XML 转化到 RDF/XML 格式的 XSLT。清单 3 就是这样的转换。


清单 3. 从 WordNet XML 转换到 RDF/XML 格式的 XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0"
  xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
  xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:wn = "http://uche.ogbuji.net/tech/rdf/wordnet/"
  xml:base = "http://uche.ogbuji.net/tech/rdf/wordnet/"
>
  <xsl:output indent="yes"/>
  <xsl:template match="/">
    <rdf:RDF>
      <xsl:apply-templates/>
    </rdf:RDF>
  </xsl:template>
  <xsl:template match="noun|verb|adjective|adverb">
    <wn:SynSet rdf:about="{name()}/{@xml:id}">
      <xsl:apply-templates/>
    </wn:SynSet>
  </xsl:template>
  <xsl:template match="gloss">
    <wn:glossaryEntry><xsl:copy-of select="node()"/></wn:glossaryEntry>
  </xsl:template>
  <xsl:template match="word-form">
    <wn:wordForm><xsl:value-of select="."/></wn:wordForm>
  </xsl:template>
  <xsl:template match="*">
    <xsl:element namespace="http://uche.ogbuji.net/tech/rdf/wordnet/"
		 name="wn:{name()}">
      <xsl:attribute namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
		     name="rdf:resource">
	<xsl:value-of select="concat(@part-of-speech, '/', @target)"/>
      </xsl:attribute>
    </xsl:element>
  </xsl:template>
</xsl:transform>





回页首


给搜索一击

很早以前的一篇文章 中,我介绍了如何使用基于 RDF 的 WordNet 数据库为应用程序专用的搜索引擎增加一些自然语言的能力。我用 WordNet 的所有同义词集组成了 清单 2 所示的 RDF 表示,然后对结果数据库进行类似的单一查询。但这一次我选择了另一种方法,从本系列 上一期 文章开发的 WordNet 服务器上递归查询 XML。

要解决的问题是,给定一个要搜索的词,我们希望能够将搜索扩展到某些关系密切的词。如果用户搜索单词 “selection”,代码应该返回包含 “vote”、“choice” 和 “ballot” 这类词的结果。这就需要从检索词开始查询 WordNet 服务器,然后沿着相关词汇的指针递规地进行查询。本文中将指针限制为下义词(hyponym),一般而言就是查找与检索词有关的表示更具体概念的其他词汇。

这个问题需要进一步细化 上一期文章 中给出的代码,具体来说就是需要 WordNet 服务器返回原始的 XML 表示的同义词集,而不仅仅返回完整的单词形式。清单 4 是上一期文章中 清单 1 所示的 CherryPy Web 服务器的特化。它允许从基于 WordNet 指针的 URL 返回原始同义词集 XML,比如 http://localhost:8080/raw/pointer/noun/5955443


清单 4. 上一期文章中给出的 CherryPy Web 服务器的特化
import cherrypy
from picket import Picket, PicketFilter
from wnxmllib import *
class root:
    _cpFilterList = [ PicketFilter(defaultStylesheet="viewword.xslt") ]
class wordform_handler:
    def __init__(self, applyxslt=False):
        self.applyxslt = applyxslt
        return
    @cherrypy.expose
    def default(self, word):
        synsets = serialized_synsets_for_word(word)
        result = ''.join(synsets) #Concatenate strings in result list
        #Wrap up the XML fragments into a full document
        wordxml = '<word-senses text="'+word+'">'+result+'</word-senses>'
        if self.applyxslt:
            picket = Picket()
            picket.document = wordxml
            return picket #apply the XSLT and return the result
        return wordxml
class pointer_handler:
    def __init__(self, applyxslt=False):
        self.applyxslt = applyxslt
        return
    @cherrypy.expose
    def default(self, pos, target):
        synset = getSynset(pos, int(target))
        synsetxml = serialize_synset(synset)
        if self.applyxslt:
            picket = Picket()
            picket.document = synsetxml
            return picket #apply the XSLT and return the result
        return synsetxml
cherrypy.root = root()
cherrypy.root.view = wordform_handler(applyxslt=True)
cherrypy.root.raw = wordform_handler()
cherrypy.root.pointer = pointer_handler(applyxslt=True)
cherrypy.root.raw.pointer = pointer_handler()
#Disable debugging messages in Web responses
cherrypy.config.update({'logDebugInfoFilter.on': False})
cherrypy.server.start()

清单 5 是接受一个单词然后用 Python 集合返回下义词链的客户机代码。它要求 WordNet XML 服务器运行 清单 4 中修改后的代码,后者需要 4Suite XML 1.0b3 版(请参阅 参考资料)。相应修改 import 语句和 API 后也可使用其他的 XML/XPath 处理库。


清单 5. 接受一个单词然后用 Python 集合返回下义词链的客户机代码
import sets
import urllib
from Ft.Xml import Parse
BASEURI = 'http://localhost:8080/'
def get_hyponym_chain(word):
    '''
    returns a list with all the hyponyms of a word, the hyponyms
    of those hyponyms, and so on, recursively
    '''
    accumulator = []  #Storage list for the hyponym chain
    def process(xml):
        '''
        extract the hyponym chain from a DOM node.  Common processing for
        word-form and synset XML
        '''
        hyponyms = xml.xpath(u'//hyponym')
        wforms = [e.xpath(u'string()')
                  for e in xml.xpath(u'//word-form')]
        accumulator.extend(wforms)
        for hyponym in hyponyms:
            pos = hyponym.xpath(u'string(@part-of-speech)')
            target = hyponym.xpath(u'string(@target)')
            expand_hyponyms(pos, target, accumulator)
        return
    def expand_hyponyms(pos, target, accumulator):
        '''
        follow a pointer and extract the hyponym chain from the resulting XML
        '''
        synsetxml = Parse(BASEURI + 'raw/pointer/' + pos + '/' + target)
        process(synsetxml)
        return
    #escape any spaces or other problem characters in the word
    word = urllib.quote(word)
    wordxml = Parse(BASEURI + 'raw/' + word)
    process(wordxml)
    return sets.Set(accumulator) #eliminate dupes
if __name__ == '__main__':
    #If invoked from the command line, get the hyponym chain from the
    #word given in the command-line parameters
    import sys, pprint
    print get_hyponym_chain(' '.join(sys.argv[1:]))

可能需要根据 WordNet XML 服务器的部署来编辑 BASEURI。如果在命令行中运行该程序并使用参数 “selection”,将得到下面的结果,即一组 Unicode 字符串(在格式上进行了编辑):

Set([u'selection', u'move', u'co-option', u'cut', u'secret ballot',
u'manoeuvre', u'juke', u'casting', u'survival', u'Haftarah', u'choice',
u'cutting', u'safe harbor', u'suicide pill', u'shark repellent',
u'scorched-earth policy', u'designation', u'delegacy', u'casting vote',
u'press cutting', u'demarche', u'epigraph', u'security', u'balloting',
u'precaution', u'tactical maneuver', u'fast one', u'split ticket',
u'clipping', u'stratified sampling', u'artifice', u'excerpt', u'greenmail',
u'election', u'parking', u'naming', u'write-in', u'extract', u'recognition',
u'pocket veto', u'survival of the fittest', u'decision', u'track', u'quote',
u'Haphtarah', u'shtik', u'schtik', u'maneuver', u'analecta', u'veto',
u'citation', u'analects', u'step', u'representative sampling', u'favorite',
u'colouration', u'sortition', u'drawing lots', u'pick', u'schtick', u'gambit',
u'stratagem', u'misquotation', u'cumulative vote', u'sampling', u'guard',
u'laying on of hands', u'fake', u'vote', u'gimmick', u'countermine', u'ploy',
u'intention', u'willing', u'call', u'lucky dip', u'way', u'footwork',
u'option', u'Haphtorah', u'feint', u'determination', u'safeguard',
u'security measures', u'quotation', u'press clipping', u'ruse', u'trick',
u'Haftorah', u'porcupine provision', u'shtick', u'measure', u'straight ticket',
u'twist', u'mimesis', u'appointment', u'volition', u'random sampling',
u'ordinance', u'ballot', u'poison pill', u'pac-man strategy',
u'proportional sampling', u'conclusion', u'multiple voting',
u'golden parachute', u'favourite', u'assignment', u'block vote', u'device',
u'nomination', u'coloration', u'casting lots', u'newspaper clipping',
u'co-optation', u'ordination', u'natural selection', u'tactical manoeuvre',
u'pleasure', u'voting', u'resolution', u'countermeasure'])

有一点要注意,四年前我尝试用大型 RDF 数据库进行这种同义词驱动的搜索时遇到了很多性能问题。完成 “selection” 和下义词的搜索花费了两分多钟。用目前的计算机再次尝试时,这种方法用了大约一分钟。但是采用本文提出的新方法,使用 WordNet XML 服务器,在同一台计算机上用了不到一秒钟,尽管期间涉及到几次本地 HTTP 请求。这是因为 WordNet XML 服务器利用了 WordNet 数据库所用的专用散列和索引,而不是查询一般的 RDF 数据库。它采用分而治之的方法在较小的范围内处理 XML,而不是单一的查询。再强调一次,RDF 有时候是一种很好的处理模型,但对于通用 DBMS 并不是最可行的语法,也不是最佳存储形式。





回页首


结束语

我们用了三篇文章讨论如何在 XML 和 RDF 应用程序中使用 WordNet 自然语言语义数据库,这是最后一篇。希望为您构建这类应用程序提供了一些工具。Princeton 的 English 语言 WordNet 项目是一项庞大的公共服务,正在取得不断进步。遗憾的是对其他语言的类似研究出现得很慢。2001 年开始发起的 EuroWordNet(请参阅 参考资料)在对几种欧洲语言进行类似的研究,但是没有看到东亚或其他语言区开展类似的活动。如果您了解此类计划,或者对这个主题有其他想法,请在 Thinking XML 讨论论坛 上分享。



参考资料

学习

获得产品和技术

讨论


关于作者

Uche Ogbuji 的照片

Uche Ogbuji 是 Fourthought Inc. 的顾问兼创始人,该公司是一家专为企业知识管理提供 XML 解决方案的软件供应商和咨询公司。Fourthought 开发了 4Suite,这是一个用于 XML、RDF 和知识管理应用程序的开放源码平台。Mr. Ogbuji 还是 Versa RDF 查询语言的首席开发人员。 他是一位出生于尼日利亚的计算机工程师和作家,目前生活和工作在美国科罗拉多的博耳德。您可以通过他的 Weblog Copia 或者 uche.ogbuji@fourthought.com 与 Ogbuji 先生联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款