在 IBM Bluemix 云平台上开发并部署您的下一个应用。 内容分类 是任何一种这样的进程,即增强数据,以便采用让数据更容易搜索、归档、管理和集成到其他进程中的方式组织数据。产生这样的元数据,让您可以从现有内容获得更大的价值。 常用缩写词
分类的重要问题之一是,人们根据自己的逻辑进行分类,会出现错误以及造成不同的分类。您定义分类系统时,考虑所有涉众的观点,试图找到一致的方法来组织数据,但是困难重重。例如,一个部门的人可能不明白什么样的元数据对另一个部门的人很重要。此外,培训人们去理解和一致地应用一种分类是很费时的。 随着海量数据(有些人称之为数字垃圾)的不断产生,手工对数据进行分类几乎已经是不可能的事了。您必须求助于分析各种格式和输入的自动化方法。 自动分类有很多优势:
安装和运行代码示例本文中我编写的代码示例目的是跟 eXist XML Database 或 Zorba XQuery 处理器一起使用。要将它与 eXist XML Database 一起使用,您需要安装了该数据库;否则,使用 Zorba XQuery 处理器(可以通过在线沙箱得到)。 安装 eXist XML Database要安装 eXist XML Database,可执行以下步骤:
使用 Zorba XQuery 处理器另外,通过执行以下步骤,您也可以使用 Zorba XQuery 处理器的在线版本来运行代码示例:
注意,eXist 和 Zorba 示例之间的差别很小。但是,眼尖的读者会注意到,它们使用 EXPath HTTP Client 库上有一点不同:Zorba 默认内置这个库,eXist 数据库则不这么做,因此,我提供一个单独的 注意:要明白,在使用这些服务之前,您可能需要同意接收一个 API 键。 利用 XQuery 进行简单分类本文的第一部分展示如何使用纯 XQuery 对内容进行分类。 文本分析:在非结构化上下文中定义单词频率术语 文本分析(text analytics)(或 文本挖掘(text mining))定义一组机器学习和语言技术,以从文本源抽取和建模信息元数据。文本分析在文本内容上应用自然语言处理(natural language processing,NLP)和分析方法,并抽取有用的元数据,比如:
文本挖掘的一个这样的例子是确定一个文档中包含的单词的频率,假设一个单词使用得越频繁,它就越与整个文档相关。 最常见的单词将被构造为文档关键词,但是要知道术语 关键词 通常应用于更复杂算法的输出,这些算法可比确定单词频率复杂多了。例如,关键词分析通常将常见单词与同义词查找表进行对照,也可以分析单词之间的距离,以帮助确定单词在整个文档上下文中的重要性。 任何文本分析中,第一步都是从文本内容生成一个语料库(corpus),后续的分析将应用于此语料库。生成语料库的原因之一是规范化文本并删除任何不相关的内容。 清单 1 展示了一个 XQuery 程序,它消费一个 HTML 页面(通过使用 EXPath HTTP Client 库)并从该 web 页面抽取出所有段落元素。由于不关心单词的大小写,所以您从内容创建的语料库全是小写的。 清单 1. 生成单词频率列表的 XQuery 程序xquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $content-url := 'http://en./wiki/Asteroid_impact_avoidance' let $content-request := <http:request href="{$content-url}" method="get" follow-redirect="true"/> let $content := fn:string-join(http:send-request($content-request)[2],' ') return let $corpus := for $w in tokenize($content, '\W+') return lower-case($w) let $wordList := distinct-values($corpus) return <words> { for $w in $wordList let $freq := count($corpus[. eq $w]) order by $freq descending return <word word="{$w}" frequency="{$freq}"/> }</words> 下一步是从语料库中派生出所有惟一的单词,为此您使用一个 FLWOR 来处理每个单词,生成单词计数(通过向后引用语料库,其中包含所有的单词),然后输出一个 注意:对于本文中的所有例子,我使用了相同的 web URL( 运行 清单 1 中程序的结果是一个 XML 文档,它具有一个 清单 2. 单词频率列表<words> <word word="the" frequency="377"/> <word word="of" frequency="236"/> <word word="a" frequency="193"/> <word word="to" frequency="167"/> <word word="and" frequency="141"/> <word word="in" frequency="124"/> <word word="earth" frequency="121"/> <word word="a" frequency="109"/> <word word="asteroid" frequency="102"/> .... </words> 如您所见,分析返回了很多单词,根据在英语中的常见用途,很多使用频率高的单词是不相关的。可以通过定义一些简单的规则来解决这个问题,这些规则用于降低干扰,比如说去除所有三个字母以内的单词以及去除频率在 3 以内的单词。 清单 3 展示了相同的代码,但是添加了测试单词字符串长度和频率的逻辑。 清单 3. 修改过的生成单词频率列表的 XQuery 程序xquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $content-url := 'http://en./wiki/Asteroid_impact_avoidance' let $content-request := <http:request href="{$content-url}" method="get" follow-redirect="true"/> let $response := http:send-request($content-request)[2] let $content := fn:string-join($response,' ') return let $corpus := for $w in tokenize($content, '\W+') return lower-case($w) let $wordList := distinct-values($corpus) return <words> { for $w in $wordList let $freq := count($corpus[. eq $w]) order by $freq descending return if(string-length($w) gt 3 and $freq gt 3) then <word word="{$w}" frequency="{$freq}"/> else () }</words> 对于不同的数据集,您可能必须调整或增强这些设置,以便排除更大长度或更高频率的单词,但是如 清单 4 所示,最小设置忽略了很多干扰,得到一个更为相关的术语集合。 清单 4. 修订后的单词频率列表<words> <word word="earth" frequency="121"/> <word word="asteroid" frequency="102"/> <word word="impact" frequency="58"/> <word word="near" frequency="56"/> <word word="with" frequency="55"/> <word word="that" frequency="53"/> <word word="space" frequency="49"/> <word word="nasa" frequency="43"/> <word word="object" frequency="36"/> <word word="from" frequency="34"/> <word word="this" frequency="32"/> ... </words> 无疑,这种方法有其局限性。但是它是一个良好的开始,并且向您展示了,用不多的 XQuery 代码,就可以得到一组基本的描述文档文本内容特征的关键词。 向单词频率添加结构元数据决策生成元数据时通常需要作出的首要决策之一是,将元数据保存在内容 XML 中,还是存储在单独的元数据文档中。在确定了您想要将元数据存储到哪里之后,还需要决定以何种格式编码元数据。存在很多标记元数据的方式 — 例如:
鼓励采用现有的特定标记语言,而不提倡设计自己的标记语言。但是要确保选择的格式既简单,又给元数据尽可能的灵活性。 如果完全忽略结构的话,应用于诸如 HTML 或 XML 之类半结构化文档的文本分析提供的见解很有限。但是如果您通过将内容与元素结构挂钩,给文本分析的重要性指定权值,从而得出更深层的推论,那又怎么样呢? 用 HTML 的术语来讲,如果您可以在某种程度上基于单词出现在嵌套结构中的何处而给单词打分,是不是很好?例如:
要得到这种结构,向每个单词添加一个 清单 5. 向生成单词频率列表的 XQuery 程序添加 fitnessxquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $content-url := 'http://en./wiki/Asteroid_impact_avoidance' let $content-request := <http:request href="{$content-url}" method="get" follow-redirect="true"/> let $response := http:send-request($content-request)[2] let $content := fn:string-join($response,' ') let $corpus := for $w in tokenize($content, '\W+') return lower-case($w) let $wordList := distinct-values($corpus) return <words> { for $w in $wordList let $fitness := if ( $response//*:title[contains(lower-case(.),$w)]) then 5 else if ($response//*:h1[contains(lower-case(.),$w)]) then 4 else if ($response//*:h2[contains(lower-case(.),$w)]) then 3 else if ($response//*:h3[contains(lower-case(.),$w)]) then 2 else if ($response//*:noscript[contains(lower-case(.),$w)]) then -2 else if ($response//*:script[contains(lower-case(.),$w)]) then -1 else 1 let $freq := count($corpus[. eq $w]) order by $freq descending return if ($freq gt 4 and string-length($w) gt 3) then <word word="{$w}" frequency="{$freq}" fitness="{$fitness}"/> else () }</words> 现在,您有了第二个度量,可以用来收集关于单词重要性的更多信息:
这一 fitness 度量过于简单,因为可能出现这样的情况,即重要单词不知为何也出现在 使用 web 服务进行文本分析有很多商业和开源工具可用于执行自然语言处理 (NLP)。下面是一些最流行的开源软件包:
此外,有几个 web 服务提供有用的文本分析。本文的后半部分关注如何在 XQuery 文件中使用这些服务。您使用 EXPath HTTP Client 库来访问它们。 使用 YQL 进行关键词抽取YQL 是一个类似于 SQL 的语言,使用它可以跨各种 Yahoo! web 服务查询数据。Yahoo! 用于使用一组 web 服务暴露大量数据和服务;现在,它使用不同的端点和方法通过单个接口 YQL 访问这些服务。 有了 YQL,您现在可以通过一种简单的语言跨 Internet 访问数据了,不再需要学习如何调用不同的 API。 http://developer.yahoo.com/yql/console/ ?q=select%20*%20from%20search.termextract%20where%20 context%3D%22Italian%20sculptors%20and%20painters%20of %20the%20renaissance%20favored%20the%20Virgin%20Mary%20for%20inspiration%22 操作性 YQL 语句声明,从一个名叫 select * from search.termextract where context= 单击 Test 生成包含一个 清单 6. YQL 结果<query xmlns:yahoo="http://www./v1/base.rng" yahoo:count="5" yahoo:created="2010-12-05T14:36:25Z" yahoo:lang="en-US"> <diagnostics> <publiclyCallable>true</publiclyCallable> <user-time>14</user-time> <service-time>11</service-time> <build-version>9962</build-version> </diagnostics> <results> <Result xmlns="urn:yahoo:cate">italian sculptors</Result> <Result xmlns="urn:yahoo:cate">virgin mary</Result> <Result xmlns="urn:yahoo:cate">painters</Result> <Result xmlns="urn:yahoo:cate">renaissance</Result> <Result xmlns="urn:yahoo:cate">inspiration</Result> </results> </query> 由于从 XQuery 中使用 EXPath HTTP Client 库很容易,下面就在您自己的内容分类进程中使用它来访问 YQL web 服务。清单 7 展示了如何从 XQuery 中调用这个 web 服务。 清单 7. 从 XQuery 访问 YQL web 服务xquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $content-url := 'http://en./wiki/Asteroid_impact_avoidance' let $content-request := <http:request href="{$content-url}" method="get" follow-redirect="true"/> let $response := http:send-request($content-request)[2] let $content := fn:string-join(subsequence(($response//*:title,$response//*:p),1,10),' ') let $query := fn:concat("select * from search.termextract where context=",$content," ") let $query := fn:encode-for-uri( fn:concat("select * from search.termextract where context='",$content,"'") ) let $yahoo-url :='http://query./v1/public/yql?diagnostics=true&q=' let $term-extraction-url := fn:concat($yahoo-url,$query) let $term-extraction-request := <http:request href="{$term-extraction-url}" method="get"/> return http:send-request($term-extraction-request)[2] 上面的 XQuery 代码使用 YQL 分析生成一个更高质量的术语集合,如 清单 8 所示。 清单 8. YQL 术语结果<query xmlns:yahoo="http://www./v1/base.rng" yahoo:count="20" yahoo:created="2010-12-05T20:14:37Z" yahoo:lang="en-US"> <diagnostics> <publiclyCallable>true</publiclyCallable> <url execution-time="433" >http://search./ContentAnalysisService/V1/termExtraction </url> <javascript execution-time="436" instructions-used="0" table-name="search.termextract"/> <user-time>437</user-time> <service-time>433</service-time> <build-version>9962</build-version> </diagnostics> <results> <Result xmlns="urn:yahoo:cate">tertiary extinction event</Result> <Result xmlns="urn:yahoo:cate">shoemaker levy 9</Result> <Result xmlns="urn:yahoo:cate">spaceguard survey</Result> <Result xmlns="urn:yahoo:cate">near earth objects</Result> <Result xmlns="urn:yahoo:cate">period comet</Result> <Result xmlns="urn:yahoo:cate">nasa report</Result> <Result xmlns="urn:yahoo:cate">extinction level event</Result> <Result xmlns="urn:yahoo:cate">deep impact probe</Result> <Result xmlns="urn:yahoo:cate">inner solar system</Result> <Result xmlns="urn:yahoo:cate">mitigation strategies</Result> <Result xmlns="urn:yahoo:cate">65 million years</Result> <Result xmlns="urn:yahoo:cate">material composition</Result> <Result xmlns="urn:yahoo:cate">impact winter</Result> <Result xmlns="urn:yahoo:cate">chicxulub crater</Result> <Result xmlns="urn:yahoo:cate">impact speed</Result> <Result xmlns="urn:yahoo:cate">catastrophic impact</Result> <Result xmlns="urn:yahoo:cate">catastrophic damage</Result> <Result xmlns="urn:yahoo:cate">planetary defense</Result> <Result xmlns="urn:yahoo:cate">impact events</Result> <Result xmlns="urn:yahoo:cate">astronomical events</Result> </results> </query> YQL 也有局限性。例如,您必须确保传递给 YQL 的内容不超出请求限制。由于这些请求被作为 HTTP 利用 AlchemyAPI 进行文本分析AlchemyAPI 是一家公司,提供一组有趣的内容分析工具(参见 参考资料)。该公司的所有工具都作为一套 web 服务可用。在本文中,您使用他们的术语和指定实体抽取服务来执行文本分析。 利用 Alchemy 进行关键词抽取AlchemyAPI 提供一个 web 服务,用于从任何可公共访问的 web 页面抽取主题关键词。使用一个直观的 HTTP 清单 9. 用于访问 AlchemyAPI 主题抽取 web 服务的 URLhttp://access./calls/url/URLGetRankedKeywords? apikey=PLACE_YOUR_APIKEY_HERE& url=http://en./wiki/Asteroid_impact_avoidance AlchemyAPI 需要两个 URL 参数:
您可以通过一个注册表单从 AlchemyAPI 站点获得 AlchemyAPI apikey。 由于 AlchemyAPI 为您获得 URL,所以从 XQuery 调用 web 服务比以前调用 YQL 的例子要稍微简单一些。清单 10 展示了代码。 清单 10. 使用 AlchemyAPI 生成关键词的 XQuery 代码xquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $url := 'http://en./wiki/Asteroid_impact_avoidance' let $apikey := 'PLACE_YOUR_APIKEY_HERE' let $alchemey_uri := 'http://access./calls/url/URLGetRankedKeywords?' let $href := fn:concat($alchemey_uri,'&apikey=',$apikey,'&url=',$url) let $content-request := <http:request href="{$href}" method="get" follow-redirect="true"/> return http:send-request($content-request)[2] 清单 11 展示了结果,其中包含所测试 web 页面的关键词。 清单 11. 主题抽取 web 服务的结果<results> <status>OK</status> <usage>By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www./company/terms.html</usage> <url>http://en./wiki/Asteroid_impact_avoidance</url> <language>english</language> <keywords> <keyword> <text>asteroid</text> <relevance>0.983321</relevance> </keyword> <keyword> <text>NASA</text> <relevance>0.376168</relevance> </keyword> <keyword> <text>comet</text> <relevance>0.370371</relevance> </keyword> <keyword> <text>near-earth object</text> <relevance>0.363529</relevance> </keyword> <keyword> <text>survey program</text> <relevance>0.3417</relevance> </keyword> .... more keywords .... </keywords> </results> 由于关键词带有相关性分数(还有很多更相关的结果),所以从质量上来讲,来自 AlchemyAPI web 服务的输出比 YQL 更好一些。 利用 AlchemyAPI 进行实体抽取通过使用 AlchemyAPI 指定实体抽取 web 服务,可以在复杂度上更进一步,AlchemyAPI 能够识别内容中的人、公司、组织、城市、地理特性和其他类型化实体。这里出现一些重型 NLP,以抽取有意义的实体。 跟主题关键词 web 服务一样,所有您必须做的事情就是提供一个 apikey 和 URL(包含您想要分析的内容),如 清单 12 所示。 清单 12. 用于访问 AlchemyAPI 指定实体抽取 web 服务的 URLhttp://access./calls/url/URLGetRankedNamedEntities? apikey=PLACE_YOUR_APIKEY_HERE& url=http://en./wiki/Asteroid_impact_avoidance 就从 XQuery 调用 web 服务来说,您做的完全是相同的事情,如 清单 13 所示。 清单 13. XQuery 使用 AlchemyAPI 生成实体xquery version "1.0"; import module namespace http = "http:///ns/http-client"; let $url := 'http://en./wiki/Asteroid_impact_avoidance' let $apikey := 'PLACE_YOUR_APIKEY_HERE' let $alchemey_uri := 'http://access./calls/url/URLGetRankedNamedEntities?' let $href := fn:concat($alchemey_uri,'&apikey=',$apikey,'&url=',$url) let $content-request := <http:request href="{$href}" method="get" follow-redirect="true"/> return http:send-request($content-request)[2] 文本分析的结果相当冗长,并且如 清单 14 所示,很清晰。 清单 14. 指定实体抽取 web 服务产生的结果<results> <status>OK</status> <usage>By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www./company/terms.html</usage> <url>http://en./wiki/Asteroid_impact_avoidance</url> <language>english</language> <entities> <entity> <type>GeographicFeature</type> <relevance>0.667231</relevance> <count>44</count> <text>Earth</text> </entity> <entity> <type>Organization</type> <relevance>0.472053</relevance> <count>25</count> <text>NASA</text> <disambiguated> <name>NASA</name> <subType>Company</subType> <subType>GovernmentAgency</subType> <subType>AirportOperator</subType> <subType>AwardPresentingOrganization</subType> <subType>SoftwareDeveloper</subType> <subType>SpaceAgency</subType> <subType>SpacecraftManufacturer</subType> <geo>38.88305555555556 -77.01638888888888</geo> <website>http://www./home/index.html</website> <dbpedia>http:///resource/NASA</dbpedia> <umbel>http:///umbel/ne/wikipedia/NASA</umbel> <yago>http:///yago/resource/NASA</yago> </disambiguated> </entity> .... entities .... </entities> </results> AlchemyAPI 指定实体抽取 web 服务识别了所有种类的实体。例如,它知道:
就这种意义上来说,文本挖掘从内容收集信息的能力几乎是不可思议的,但是最好关注一下相关性评分。没有哪个系统是百分之百准确的,您会发现某些内容对文本分析的响应要好于其他内容。 结束语为开始分类您自己的文档,本文介绍了很多技术。第一种尝试的焦点是,如何基于确定单词频率,建立您自己的 XQuery 文本挖掘技术。我然后展示了如何集成 Yahoo! 和 AlchemyAPI 提供的强大的外部 web 服务,用于文本分析。 无疑,web 服务提供的文本分析质量较高,但是即使对于基本的单词频率 XQuery 例子,也可以使用纯 XQuery 从您的数据得到有用的推论。 给出的所有方法都有一些局限性。例如,只分析一个文档。跨一组相关文档执行文本分析可以导致更高质量的分类,因为您可以交叉引用更大的语料库,并分析出文档之间更深层的关系。总之,我希望本文向您展示了 XQuery 对于自动化内容分类有多么强大,并且愿意听到关于您自己尝试以相同方式应用 XQuery 的反馈。 下载
|
|