中文分词

本文介绍了中文分词的概念及其在自然语言处理中的重要性。探讨了分词的基本方法,包括基于字符串匹配、理解和统计的分词方法。并详细介绍了如何在Lucene中实现中文分词,包括自定义Analyzer、Tokenizer和TokenFilter等关键组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是分词?什么是中文分词?

分词,就是将一段文字,按照语义上的最小单位切割开来。对于中文来说,虽然,很多汉字本身就具有相对独立的意思,但是更多情况下,单个的汉字是与其他一个或多个汉字组合在一起形成一个含义的。举个例子,“我是一个学生”,分词的结果是:“我/是/一个/学生”,再比如,“我/打算/去/做/分词/的 /研究”。中文分词,就是将中文段落划分成词。

分词是理解语义的前提。人类依据自身的知识,在看到文字的时候,就自动完成了分词的过程。然而,计算机不具备人类的知识,更加不具备人类的智能,让机器实现自动切分文本,就成为了一个重要的研究课题,隶属于自然语言处理技术领域。在各种语言的分词中,最为困难的,可能就是中文分词了,因为中文语法复杂,规则少,特例多,歧义性强。中文领域文本处理技术,大大落后于西文,分词就是制约因素之一。

分词是搜索引擎建立索引的重要环节。我们固然可以对单个汉字建立索引,但是那样建立的索引,体积庞大,效率低下,检索缓慢,精确率低。分词完毕后,就能大大减少索引的体积,提高检索的效率。对于检索领域来说,分词可能仍非必要环节,但是对于自然语言处理领域来说(典型的如机器翻译),分词就必不可少。

 

分词的基本方法

分词一般有三种方法,基于字符串匹配的分词方法,将一段文本,与一个充分大辞典,逐条进行匹配,实现分词。按照长度优先级的不同,可以分为最大匹配、最小匹配;按照匹配方向的不同,可以分为正向匹配、逆向匹配。这些方法可以互相组合。

基于理解的分词方法,这种方法让计算机模拟人对句子的理解,对句子进行语法分析,语义分析,最后实现分词。该方法实现难度大,需要大量的语言知识和信息,目前还没有可生产的系统。

基于统计的分词方法,是通过对大量语料统计两个字相邻出现的频率,识别出词的方法。该方法虽然不需要辞典,而且能够实现对新词的识别。

三大类分词方法,各有利弊,参见文献【2】,现实中的分词系统,往往是综合系统,也即两种以上方法的综合,以此实现最优的分词效果。

 

Lucene中分词

Lucene中执行分词任务的是Analyzer对象,该对象中最关键的方法,是tokenStream方法,该方法可以返回一个包含着token的集合,也即 TokenStream对象。TokenStream本身,是一个有着类似迭代器接口的抽象类,其具体类有两种,一种是以Reader对象作为输入的 Tokenizer对象,另一种是以另一个TokenStream对象作为输入的TokenFilter。

到此,我们已经不难看出,实际执行切割任务的是Tokenizer,而TokenFilter则正如其名,对切割的结果进行过滤。要得到一个分词完毕的结果集合,必须要各类Tokenizer和TokenFilter的合作才可以完成,而Analyzer在这里,就扮演着一个组装器的角色。

从StandardAnalyzer中,我们不难发现Lucene的思路。首先创建一个StandardTokenizer实现第一次切割,然后是StandardTokenFilter,实现对token的归一化,如将复数词变成单数词,接着是一个ToLowerCaseFilter,将所有的token转换成小写字母,最后是StopFilter,将所有的stop words(无意义虚词)去掉。这样就完成了对一个英文文字段落的分词。

这样的设计,将复杂的分词实现全部对用户透明,用户具体使用的时候,就非常容易,只要创建一个Analyzer对象,然后传递给IndexWriter或者QueryParser(分解用户的查询,第一个步骤也是分词)即可。

 

Lucene中实现中文分词

有了上面的理解,我们就知道,要让Lucene能够实现中文分词,我们必须创建自己的Analyzer,以及与其相关的Tokenizer和TokenFilter,有了这几个类的配合,就可以实现中文分词。

我在网上调研了数个中文分词系统,但是,里面实现了Lucene接口的并不多,好在我只是做一般性科研用途,对性能,效率不需考量,所以,我就直接选择了按照Lucene的接口设计的Paoding Analysis包。如果,我们期望能够得到更高的精确率和分词效率,我们还需要选用更加优秀的分词组件才行,那时候,就必须要自己手动来进行一次封装,以实现Lucene的接口,不过,这并不是一个复杂的事情。很多分词组件本身已经非常全面,例如ICTCLAS,已经实现了定制化分词,其给出的结果,就直接是最终结果了,所以,如果要包装ICTCLAS,我们要做的事情就很简单了,将ICTCLAS返回的结果,用TokenStream包装即可,可能单实现一个 Analyzer就足够了。即便考虑得全面一些,事情也不会太复杂。

 

总结

市面上的中文分词组件非常多,一般应用,我们完全可以采用现成的系统。没有必要重复发明轮子。但是这些系统大多数难以适用于要求更高的商业系统,那时候就不得不选购一些相关的解决方案,或者在某开源系统的基础上进行再开发。

我个人在实际项目中,选用了Paoding Analysis,主要考虑到该实现完全使用Java,具有优秀的跨平台特性,而且用起来也最为省心,分词效果也还不错。虽然效率可能存在一定的问题,但是由于系统本身内容较少,也就不是矛盾的主要方面了。日后可以考虑更换更为高效和更为准确的系统。当然,前提是你在构建系统的时候,不要将你使用的 Analyzer硬编码进系统,而是使用配置文件等方式来接入。

 

 

 

 

 

 

 


 Lucene应用越来越多,在对中文对索引过程中,中文分词问题也就越来越重要。
在已有的分词模式中,目前比较常用的也是比较通用的有一元分词、二元分词和基于词库的分词三种。
一元分词在Java版本上由yysun实现,并且已经收录到Apache。其实现方式比较简单,即将每一个汉字作为一个Token,例如:“这是中文字”,在经过一元分词模式分词后的结果为五个Token:这、是、中、文、字。而二元分词,则将两个相连的汉字作为一个Token划分,例如:“这是中文字”,运用二元分词模式分词后,得到的结果为:这是、是中、中文、文字。
一元分词和二元分词实现原理比较简单,基本支持所有东方语言。但二者的缺陷也比较明显。一元分词单纯的考虑了中文的文字而没有考虑到中文的词性,例如在上述的例子中,“中文”、“文字”这两个十分明显的中文词语就没有被识别出来。相反,二元分词则分出了太多的冗余的中文词,如上所述,“这是”、“是中”毫无意义的文字组合竟被划分为一个词语,而同样的缺陷,命中的词语也不十分准确,如上:在“这是中文字”中,“中文字”这个词语应该优先考虑的。而二元分词也未能实现。
基于词库的分词实现难度比较大,其模式也有多种,如微软在自己的软件中的汉语分词、海量的中文分词研究版,还有目前在.Net下实现的使用率较高的猎兔,和一些其他人自发实现的分词工具等等。其都有自己的分析体系,虽然分析精度高,但实现难度大,实现周期长,而且,对一般的中小型应用系统来讲,在精度的要求不是十分苛刻的环境下,这种模式对系统对消耗是一种奢侈行为。
在综合考虑一元分词、二元分词及基于词库的分词模式后,我大胆提出一种基于StopWord分割的分词模式。这种分词模式的设计思想是,针对要分割的段落,先由标点分割成标准的短句。然后根据设定的StopWord,将短句由StopWord最大化分割,分割为一个个词语。如:输入短句为“这是中文字”,设定的StopWord列表为:“这”、“是”,则最终的结果为:“中文字”。
这个例子相对比较简单,举个稍微长一点的例子:输入短句“中文软件需要具有对中文文本的输入、显示、编辑、输出等基本功能”,设定的StopWord列表为:“这”、“是”、“的”、“对”、“等”、“需要”、“具有”,则分割出对结果列表为:
====================
 中文软件
 中文文本
 输入
 显示
 编辑
 输出
 基本功能
====================
基本实现了想要的结果,但其中也不乏不足之处,如上述的结果中“中文软件”与“中文文本”应该分割为三个独立词“中文”、“软件”和“文本”,而不是上述的结果。
并且,对StopWord列表对设置,也是相对比较复杂的环节,没有一个确定的约束来设定StopWord。我的想法是,可以将一些无意义的主语,如“我”、“你”、“他”、“我们”、“他们”等,动词“是”、“对”、“有”等等其他各种词性诸如“的”、“啊”、“一”、“不”、“在”、“人”等等(System32目录下noise.chs文件里的内容可以作为参考)作为StopWord。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值