全文检索lucene中文分词的一些总结

全文检索几乎是全部内容管理系统软件(CMS)必备的功能,在对公司的CMS产品的开发维护过程当中,全文检索始终是客户重点关注的模块,为知足客户各式各样愈来愈高的要求,对全文检索曾作过一段时间相对深刻的研究,尤为是对分词机制. 算法

 

1 什么是中文分词 缓存

学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开。而中文则以字为单位,字又组成词,字和词再组成句子。因此对于英文,咱们能够简单以空格判断某个字符串是否为一个单词,好比I love China,love 和 China很容易被程序区分开来;但中文“我爱中国”就不 同样了,电脑不知道“中国”是一个词语仍是“爱中”是一个词语。把中文的句子切分红有意义的词,就是中文分词,也称切词。我爱中国,分词的结果是:我 爱 中国。 数据结构

目前中文分词仍是一个难题———对于须要上下文区别的词以及新词(人名、地名等)很难完美的区分。国际上将一样存在分词问题的韩国、日本和中国并称为CJK(Chinese Japanese Korean),对于CJK这个代称可能包含其余问题,分词只是其中之一。 函数

 

2 中文分词的实现 测试

Lucene自带了几个分词器WhitespaceAnalyzer, SimpleAnalyzer, StopAnalyzer, StandardAnalyzer, ChineseAnalyzer, CJKAnalyzer等。前面三个只适用于英文分词,StandardAnalyzer对可最简单地实现中文分词,即二分法,每一个字都做为一个词,这样分出来虽然全面,但有不少缺点,好比,索引文件过大,检索时速度慢等。ChineseAnalyzer是按字分的,与StandardAnalyzer对中文的分词没有大的区别。 CJKAnalyzer是按两字切分的, 比较武断,而且会产生垃圾Token,影响索引大小。以上分词器过于简单,没法知足现实的需求,因此咱们须要实现本身的分词算法。 搜索引擎

现有的中文分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词方法和基于统计的分词方法。后面二者只是据说过,没深刻接触过,这里着重讲下基于字符串匹配的分词方法。 spa

基于字符串匹配的分词方法又叫作机械分词方法,它是按照必定的策略将待分析的汉字串与一个“充分大的”机 器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不一样,串匹配分词方法能够分为正向匹配和逆向匹配;按照不 同长度优先匹配的状况,能够分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又能够分为单纯分词方法和分词与标注相结合的一体化 方法。经常使用的几种机械分词方法以下: 设计

    1)正向最大匹配法(由左到右的方向); 继承

    2)逆向最大匹配法(由右到左的方向); 索引

    3)最少切分(使每一句中切出的词数最小)。

这种分词方法,首先要有一个词库。一个好的分词器须要一个庞大优良的词库以及设计优秀的数据结构来缓存该词库。下面使用一个名为MMAnalyzer的开源分词器作简单的分词演示,而后大体讲下怎么样基于lucene实现本身的分词器。MMAnalyzer 简介:

 

一、支持英文、数字、中文(简体)混合分词

二、经常使用的数量和人名的匹配

三、超过22万词的词库整理

四、实现正向最大匹配算法

五、词典的动态扩展

六、分词效率: 第一次分词须要1-2秒(读取词典),以后速度基本与Lucene自带分词器持平。内存消耗: 30M+

 

MMAnalyzer的分词算法以下:

 

一、读取一个字,而后联想,直到联想到不能为止。若是当前能够构成词,便返回一个Token。

二、若是当前不能构成词语,便回溯到最近的能够构成词语的节点,返回。

三、最差的状况就是返回第一个单字。

四、而后从返回结果的下一个字从新开始联想。

 

public static void main(String[] args) throws IOException {

String text = "2008年前三季度,美国次贷危机升级,全球金融持续动荡,世界经济增加全面放缓,全球经济增加动力减弱,世界主要经济体与新兴市场正面临巨大的外部冲击。";

Analyzer analyzer = new MMAnalyzer();

TokenStream stream = analyzer.tokenStream("xxx", new StringReader(text));

        while (true) {

            Token token = stream.next();

            if (token == nullbreak;

            System.out.print("[" + token.termText() + "] ");

        }

}

返回结果以下:

[2008] [年前] [三季度] [美国] [次] [贷] [危机] [升级] [全球] [金融] [持续] [动荡] [世界经济] [增加] [全面] [放] [缓] [全球] [经济] [增加] [动力] [减弱] [世界] [主要] [经济] [体] [新兴] [市场] [正] [面临] [巨大] [外部] [冲击]

 

MMAnalyzer分词器有两个构造函数MMAnalyzer()和MMAnalyzer(int n)。

MMAnalyzer():采用正向最大匹配的中文分词算法,至关于分词粒度等于0。

MMAnalyzer(int n):参数为分词粒度:当字数 >= n,且能成词,该词就被切分出来。

另外MMAnalyzer还有如下经常使用方法:

addDictionary(FileReader reader):增长一个新词典,采用每行一个词的读取方式。

addWord(String newWord):往词库里新增长一个新词。

 

其中addWord方法测试了好像只会把新词加入到缓存了的词库中,并不会并永久性写入词典文件中。若是须要写入词典文件,可再按如下方法处理。

 

URL dictionaryPath = URLUtil.getResourceFileUrl("resources/dictionary.txt");

if(dictionaryPath != null){

    // new FileWriter(String, boolean) 第二个参数true表示追加文件到尾部

    BufferedWriter bw = new BufferedWriter(new FileWriter(dictionaryPath.getPath(), true));  

    bw.write(searchStr);//追加文件内容  

    bw.newLine();

    bw.close();

}

 

       固然也可本身实现分词器,实现过程很简单,首先实现一个Tokenizer(须要继承lucene包里的Tokenizer抽象类),覆写里面的next()方法,这也是lucene分词器实现的最关键的地方。而后再实现一个Analyzer(须要继承lucene包里的Analyzer抽象类),将上面实现的Tokenizer指定给该Analyzer。

 

三、  中文分词一些常见问题及解决办法

3.1 分词的缺失

好比同义词。用户搜 "北京 饭店" 能不能把" 首都 饭店"也列出来呢? 这个分词器无能为力。因此这个问题,解决办法就只能是在分词以前,咱们再加一层:同义词返回模块。这个思路很不错,也比较简单,很容易实现。关键是词库的创建。

 

3.2 优先级

例如:我还清晰地记得咱们坐在江边聊天的情境。

分出来是: 我 还清 晰 地 记得 咱们 坐在 江边 聊天 的 情境。

结果: 清晰 被拆开了。

这个是基于词库的分词算法固有的问题。没有很好的解决方法。有统计结果代表,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。有一种解决方案是正向匹配结果后再逆向匹配一次,而后比较结果,消除歧义。最好加入词汇几率统计功能.有歧义的用几率决定。

 

3.3 最大匹配的问题

好比搜索“三季度”这个词,词库里同时有 “三季度” 和 “季度”这两个词,分词时按最大正向匹配 则 “三季度” 被分红一个完整的词,按“季度” 去检索反而搜不出来了。

解决办法:缩短分词粒度,当字数等于或超过该粒度参数,且能成词,该词就被切分出来。

 

3.4 新词识别

      新词,也就是那些在字典中都没有收录过,但又确实能称为词的那些词。最典型的是人名,人能够很容易理解句子“王军虎去广州了”中,“王军虎”是个词,由于是一我的的名字,但要是让计算机去识别就困难了。若是把“王军虎”作为一个词收录到字典中去,全世界有那么多名字,并且每时每刻都有新增的人名,收录这些人名自己就是一项巨大的工程。即便这项工做能够完成,仍是会存在问题,例如:在句子“王军虎头虎脑的”中,“王军虎”还能不能算词?

     新词中除了人名之外,还有机构名、地名、产品名、商标名、简称、省略语等都是很难处理的问题,并且这些又正好是人们常用的词,所以对于搜索引擎来讲,分词系统中的新词识别十分重要。目前新词识别准确率已经成为评价一个分词系统好坏的重要标志之一。

 

其余的还有如热度、高亮显示等问题。总言之,中文分词机制的好坏,直接影响到用户对搜索结果的满意度,因此如何分词是搜索引擎的重中之重。

相关文章
相关标签/搜索