`
infinite
  • 浏览: 41735 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

阅读更多

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

 

全文检索几乎是所有内容管理系统软件(CMS)必备的功能,在对公司的CMS产品的开发维护过程中,全文检索始终是客户重点关注的模块,为满足客户各式各样越来越高的要求,对全文检索曾做过一段时间相对深入的研究,尤其是对分词机制,趁如今换工作比较空闲之际做个简单总结。

 

1、 什么是中文分词

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

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

 

2、 中文分词的实现

Lucene自带了几个分词器WhitespaceAnalyzerSimpleAnalyzerStopAnalyzerStandardAnalyzerChineseAnalyzerCJKAnalyzer等。前面三个只适用于英文分词,StandardAnalyzer对可最简单地实现中文分词,即二分法,每个字都作为一个词,这样分出来虽然全面,但有很多缺点,比如,索引文件过大,检索时速度慢等。ChineseAnalyzer是按字分的,StandardAnalyzer对中文的分词没有大的区别。 CJKAnalyzer是按两字切分的, 比较武断,并且会产生垃圾Token,影响索引大小。以上分词器过于简单,无法满足现实的需求,所以我们需要实现自己的分词算法。

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

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

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

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

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

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

 

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

2、常用的数量和人名的匹配

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

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

5、词典的动态扩展

6、分词效率: 第一次分词需要12秒(读取词典),之后速度基本与Lucene自带分词器持平。内存消耗: 30M+

 

MMAnalyzer的分词算法如下:

 

1、读取一个字,然后联想,直到联想到不能为止。如果当前可以构成词,便返回一个Token

2、如果当前不能构成词语,便回溯到最近的可以构成词语的节点,返回。

3、最差的情况就是返回第一个单字。

4、然后从返回结果的下一个字重新开始联想。

 

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 == null) break;

            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、  中文分词一些常见问题及解决办法

3.1 分词的缺失

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

 

3.2 优先级

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

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

结果: 清晰 被拆开了。

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

 

3.3 最大匹配的问题

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

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

 

34 新词识别

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

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

 

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

11
8
分享到:
评论
1 楼 judasn 2012-07-20  
前辈,可以跟你请教一个lucene的问题吗?你这篇文章整理的还不错!(jn3.141592654@163.com)

相关推荐

    中文分词及其在基于Lucene的全文检索中的应用

    本文构造出一种适应中英文信息处理的Lucene语言分析器,该分析器的核心模块——分词器所使用的分词算法是一种基于词典的中文分词算法,该算法具体实现上采用了基于词前缀哈希技术来进行逐字匹配,采用基于规则统计...

    全文检索服务中文分词技术

    IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。 庖丁中文分词库是一个使用Java开发的,可结合到Lucene 应用中的,为互联网、企业内部网使用的中文搜索引擎分词组件。

    Lucene的中文分词方法设计与实现

    处理方法,提高全文检索系统的中文处理能力.整个模块基于当前最流行的搜索引擎架构 Lucene,实现了带有歧义消除功能的正向最大匹配算法.在系统评测方面,比较了该方法与现 有方法的区别,对于如何构建一个高效的...

    lucene.net+盘古分词多条件全文检索并匹配度排序

    使用visual studio 开发的lucene.net和盘古分词实现全文检索。并按照lucene的得分算法进行多条件检索并按照得分算法计算匹配度排序。 可以输入一句话进行检索。 lucene.net的版本为2.9.2 盘古分词的版本为2.3.1 并...

    基于Lucene和IK Analyzer的全文检索框架搭建

    介绍了全文检索的基本概念,详细说明了全文检索框架Lucene的用法,并提供了样例代码。

    全文检索 lucene.net+盘古分词 的演示程序

    这是一个全文检索的演示程序 lucene.net加盘古分词,仅供参考,希望能给需要的人提供一些帮助 这是一个全文检索的演示程序 lucene.net加盘古分词,仅供参考,希望能给需要的人提供一些帮助

    lucene 中文分词 庖丁解牛

    庖丁解牛(很好的分词效率) 在做站内全文检索时创建索引时比较快,而且感觉效果比JE要好一些。。

    lucene 中文分词

    lucene 中文分词小案例,实现中文检索,最近看到lucene顺便自己动手做了一下感觉挺实用的,案例很简单,很容易看懂

    Apache Lucene全文检索和IKAnalyzer分词工具类

    * Apache Lucene全文检索和IKAnalyzer分词工具类 * <p>Company: 91注册码 * time:2014-04-22 * @author www.91zcm.com * @date * @version 1.1 */ public class LuceneUtil { /**索引创建的路径**/ ...

    Lucene介绍,全文检索

    Lucene是一个基于Java的全文索引工具包。 基于Java的全文索引引擎Lucene...另外,如果是在选择全文引擎,现在也许是试试Sphinx的时候了:相比Lucene速度更快,有中文分词的支持,而且内置了对简单的分布式检索的支持

    Lucene.Net+盘古分词器详细介绍

    Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。开发人员可以基于Lucene.net实现全文检索的...

    Lucene.Net+盘古分词C# Demo

    Lucene.Net+盘古分词是一个常见的中文信息检索组合。但是随着盘古分词停止更新,与Lucene.Net3.0无法兼容。为了使得大家少走弯路,本人利用Lucene.Net2.9+盘古分词2.3搭建了一个Demo,里面包含了两个模块的源码,方便...

    全文检索技术学习(三)——Lucene支持中文分词 - 李阿昀的博客 - CSDN博客1

    全文检索技术学习(三)——Lucene支持中文分词 - 李阿昀的博客 - CSDN博客首页博客学院下载图文课论坛问答商城活动招聘搜博主文章写博客小程序全文检索技

    Lucene中文分词组件 JE-Analysis 1.4.0

    分词效率: 第一次分词需要1-2秒(读取词典),之后速度基本与Lucene自带分词持平 运行环境: Lucene 1.9+ 内存消耗: 30M+ 1.4.0 —— 2006-08-21 增加词典的动态扩展能力 1.3.3 —— 2006-07...

    lucene.net +盘古分词器 实例

    Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎 它提供了类似SQLServer数据库正式版中的全文检索功能的... 但是Lucene.Net内置分词算法对中文支持不是很好,以下会使用国内较为流行的分词算法 -- 盘古分词

    lucene全文检索的功能,很强,比如baidu搜索功能,超级完美的例子,包括中文分词绝对有价值

    lucene全文检索的功能,很强,比如baidu搜索功能,超级完美的例子,包括中文分词绝对有价值

    基于Lucene的中文分词方法设计与实现

    处理方法,提高全文检索系统的中文处理能力. 整个模块基于当前最流行的搜索引擎架构 Lucene ,实现了带有歧义消除功能的正向最大匹配算法. 在系统评测方面,比较了该方法与现 有方法的区别,对于如何构建一个高效的中文...

    针对中文检索的Lucene改进策略

    为了提高基于Lucene中文检索系统的检索精度和效率,通过分析Lucene的结构,在系统中加入了中文分词模块和索引 文档预处理模块。给出了具体的实验方法和实验过程,对改进原理和实验数据进行了分析,表明了加入中文...

    全文检索MVC+Lucene+PanGu源码(含数据库)

    全文检索MVC+Lucene+PanGu分词源码(含数据库)

    lucene实现全文搜索

    全文检索介绍 索引 分词 Lucene介绍 Lucene应用详解 索引器 检索器 条件查询 实用工具及高亮器 Lucene综合应用——仿搜索引擎

Global site tag (gtag.js) - Google Analytics