全文检索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,影响索引大小。以上分词器过于简单,无法满足现实的需求,所以我们需要实现自己的分词算法。
现有的中文分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词方法和基于统计的分词方法。后面两者只是听说过,没深入接触过,这里着重讲下基于字符串匹配的分词方法。
基于字符串匹配的分词方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。常用的几种机械分词方法如下:
1)正向最大匹配法(由左到右的方向);
2)逆向最大匹配法(由右到左的方向);
3)最少切分(使每一句中切出的词数最小)。
这种分词方法,首先要有一个词库。一个好的分词器需要一个庞大优良的词库以及设计优秀的数据结构来缓存该词库。下面使用一个名为MMAnalyzer的开源分词器做简单的分词演示,然后大致讲下怎么样基于lucene实现自己的分词器。MMAnalyzer 简介:
1、支持英文、数字、中文(简体)混合分词
2、常用的数量和人名的匹配
3、超过22万词的词库整理
4、实现正向最大匹配算法
5、词典的动态扩展
6、分词效率: 第一次分词需要1-2秒(读取词典),之后速度基本与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 最大匹配的问题
比如搜索“三季度”这个词,词库里同时有 “三季度” 和 “季度”这两个词,分词时按最大正向匹配 则 “三季度” 被分成一个完整的词,按 “季度” 去检索反而搜不出来了。
解决办法:缩短分词粒度,当字数等于或超过该粒度参数,且能成词,该词就被切分出来。
3.4 新词识别
新词,也就是那些在字典中都没有收录过,但又确实能称为词的那些词。最典型的是人名,人可以很容易理解句子“王军虎去广州了”中,“王军虎”是个词,因为是一个人的名字,但要是让计算机去识别就困难了。如果把“王军虎”做为一个词收录到字典中去,全世界有那么多名字,而且每时每刻都有新增的人名,收录这些人名本身就是一项巨大的工程。即使这项工作可以完成,还是会存在问题,例如:在句子“王军虎头虎脑的”中,“王军虎”还能不能算词?
新词中除了人名以外,还有机构名、地名、产品名、商标名、简称、省略语等都是很难处理的问题,而且这些又正好是人们经常使用的词,因此对于搜索引擎来说,分词系统中的新词识别十分重要。目前新词识别准确率已经成为评价一个分词系统好坏的重要标志之一。
其他的还有如热度、高亮显示等问题。总言之,中文分词机制的好坏,直接影响到用户对搜索结果的满意度,所以如何分词是搜索引擎的重中之重。
分享到:
相关推荐
《中文分词及其在基于Lucene的全文检索中的应用》这篇论文主要探讨了中文分词在全文检索系统,特别是基于Lucene平台的应用。全文检索技术是现代信息检索领域的重要组成部分,而Lucene作为一款开源的全文检索引擎框架...
由于中文是以词为基本单位,不像英文那样有明显的空格分隔,因此在进行信息检索时,需要先对中文文本进行分词,将连续的汉字序列切分成具有独立含义的词语。这样才能有效地进行关键词匹配和索引。 在Lucene中,常见...
Lucene.NET 是一个高性能、全文检索库,它是Apache Lucene项目在.NET平台上的实现。作为一个开源的搜索引擎框架,Lucene.NET为开发者提供了强大的文本搜索功能。而在处理中文文档时,由于中文词汇间的无明显空格分隔...
Lucene是一个高性能、全文检索库,而“lucene中文分词工具包”则为Lucene提供了一个专门针对中文分词的解决方案。这个工具包的核心是IKAnalyzer,它是一个开源且基于Java语言开发的轻量级中文分词工具,旨在提升中文...
在中文信息检索领域,分词是至关重要的一环,它能够将连续的汉字序列切割成具有独立意义的词语,为后续的索引和查询提供基础。Lucene作为Java最著名的全文搜索引擎库,其本身并不包含专门针对中文的分词模块。然而,...
使用visual studio 开发的lucene.net和盘古分词实现全文检索。并按照lucene的得分算法进行多条件检索并按照得分算法计算匹配度排序。 可以输入一句话进行检索。 lucene.net的版本为2.9.2 盘古分词的版本为2.3.1 并...
**全文检索Lucene** Lucene是Apache软件基金会的开源项目,它是一个高性能、全文本搜索库,被广泛用于构建各种搜索引擎。Lucene提供了一个简单但功能强大的API,开发者可以使用这个API来添加全文检索功能到自己的...
**Lucene全文检索引擎** Lucene是Apache软件基金会的一个开源项目,...总结来说,Lucene是一个强大的全文检索引擎,通过理解和掌握其工作原理及API,开发者可以构建出高效、灵活的搜索功能,满足各种复杂的搜索需求。
【标题】:“HeyJava传智播客全文检索Lucene源码” 【描述】:这个资源主要聚焦于Lucene,一个广泛使用的全文检索库,由Apache软件基金会开发并维护。通过学习这部分内容,你可以深入理解Lucene如何实现高效的文本...
其中,Apache Lucene作为一个开源的全文检索库,被广泛应用于各种项目中,尤其对于处理中文文本,分词是其关键的一环。本文将深入探讨如何在Lucene中高效地进行中文分词,借助“庖丁解牛”的概念,以求在理解与应用...
Lucene,作为一个强大的全文搜索引擎库,对于处理中文文档,分词的准确性和效率直接影响到搜索效果。本文将围绕“lucene中文分词”这一主题,深入探讨Lucene如何处理中文文本,以及如何利用相关的分词工具进行有效的...
在Java开发中,Apache Lucene是一个强大的全文搜索引擎库,但默认并不支持中文,这就需要借助第三方分词工具。本文将深入探讨如何在Lucene中结合“庖丁解牛”这一中文分词工具,实现高效、准确的中文文本处理。 一...
在本案例中,我们将在 .Net MVC4 框架上使用 Lucene.Net 来构建一个全文检索系统。 首先,我们需要理解全文检索的基本概念。全文检索是指在文档集合中,根据用户输入的查询词,查找包含这些词的文档。与传统的...
Lucene作为一款强大的全文检索库,虽然内置了StandardAnalyzer,但其对中文分词的支持并不完全满足所有应用需求。因此,开发者们开发了一系列专门针对中文分词的Analyzer,以提升搜索效率和准确度。以下是对几种常见...
Lucene是一个强大的全文搜索引擎库,广泛应用于各种文本检索和分析系统中。这个名为"Lucene-Demo.rar"的压缩包提供了一个基于Lucene的分词演示项目,可以帮助开发者快速理解和应用Lucene的分词功能。在这个压缩包中...
总结起来,"庖丁解牛"中文分词器是Lucene 3全中文索引解决方案的重要组成部分,它的引入能显著提升中文文本处理的效率和精确性。对于从事信息检索和自然语言处理的开发者来说,掌握并合理运用庖丁解牛,无疑能为你的...
在信息检索领域,Lucene作为一款强大的全文搜索引擎库,被广泛应用。在处理中文文本时,分词是至关重要的一步,它决定了搜索的精度和效果。本文将详细讲解如何在Lucene 6.6版本中结合拼音分词和IK中文分词,以及如何...
【标题】"Lucene.net 盘古分词C#" 涉及到的是在.NET环境中使用Lucene库进行全文检索,并结合盘古分词工具进行中文分词处理。Lucene是一个开源的全文检索库,提供了高效的索引和搜索功能。在.NET平台上,Lucene.net是...