`
Qieqie
  • 浏览: 342035 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Lucene中文分词“庖丁解牛”

阅读更多

 Lucene中文分词 “庖丁解牛”

 附件 为本人设计编写的组件,中文分词“庖丁解牛”,具有相当好的使用价值。。。

高效率:我的赛扬PC 1 秒解析 >>> 20000汉字的词语  (实际测试结果数据,可达1秒10万+汉字。)
高可维护性:使用“庖丁”隐喻,形象明晰
高灵活性,可扩展:OOD

对比:《终于突破中文分词的效率问题》http://www.lucene.org.cn/read.php?tid=54&fpage=2 他的效率为 6秒 解析2588汉字
 

2007-08-08:

由于庖丁解牛进行了一些调整和重构,这里的附件代码已经是"较旧"的,最新的下载地址:

http://code.google.com/p/paoding/downloads/list

SVN地址为:http://paoding.googlecode.com/svn/trunk/paoding-analysis/ 

同时也可以通过浏览器访问http://paoding.googlecode.com/svn/trunk/paoding-analysis/  直接浏览代码。

最新的在JavaEye的发布帖子是:

http://www.iteye.com/topic/110148   中文分词 庖丁解牛 2.0.0 发布

 

  • Paoding.rar (1.1 MB)
  • 描述: 中文分词“庖丁解牛”,面向对象,高效率,高扩展性
  • 下载次数: 6782
  • HashBinaryDictionary.java.rar (2.2 KB)
  • 描述: 原来的HashBinaryDictionary.java使用对第一个字符hash+二份查找。这个算法已经不错。 但下面的更新使用了更好的策略。可连续hash词语的字符。理论上这个词典算法应该到达极致了。 覆盖HashBinaryDictionary.java在com/sohospace/dictionary下
  • 下载次数: 2578
  • Main1.java.rar (6.1 KB)
  • 描述: 对一个长度2185856的字符串(4,347,520字节)的分词效率测试。 下载解压后添加到源文件中
  • 下载次数: 2402
分享到:
评论
32 楼 imjl 2007-01-26  
呵呵,,泼点冷水,,从应用角度来看

我觉得个人做lucene中文分词,没有什么商业价值.
因为中文分词牵涉的不单单是编程知识,还有自然语言等方面的知识.
YAHOO目前采用的中文分词还是购买的.
什么样的公司需要自己订做中文分词? 就lucene的两个analyzer足够用了。
有多少是做类似yahoo,baidu这样大的搜索引擎,,只有这样的公司需要中文分词,国内还有其他公司需要自己中文分词吗?我觉得都用不到。包括sina,163,sohu这样的门户。


从技术角度我支持你。

31 楼 lordhong 2007-01-26  
拜达人...
30 楼 Qieqie 2007-01-26  
考虑中,我的思考点是:

1、能够促进持续改进,相互提升
2、鼓励实践中做适应性的变更
3、保护开放源代码机制


有人专门研究各开源协议的不?
29 楼 netfishx 2007-01-26  
alin_ass 写道
Qieqie同志


能不能把你的代码挪到我的开源项目里?保留你的声明和作者名,包名和代码要修改


同问,作者能不能定下来用什么开源协议?否则我们不敢用啊。
28 楼 alin_ass 2007-01-26  
Qieqie同志


能不能把你的代码挪到我的开源项目里?保留你的声明和作者名,包名和代码要修改
27 楼 billgmh 2007-01-26  
Qieqie 写道
billgmh 写道
我也正在就中文分词方向进行研究,也是使用首字hash+折半查找的方法构造词典的,是我尝试过分词效率最高的一种词典实现方式,但是最近我收集到一份论文《基于双数组Trie树的词典查询算法》,发现效率可能比基于双数组Trie树的词典查询算法还要高(利用有穷自动机的原理与Trie树的易扩展性),不知楼主有没有尝试过这种方法呢?


加粗的句子看不明白是什么意思。

HashBinaryDictionary.java.rar中的java文件,他不是单纯的首字hash+折半查找。

只要参数设置的好,可以认为采用hash查找的时间复杂度是O(1),而折半不管怎么说也是log2n,而且每次折半比较都要对字符串和目标词语各个字符进行compare。所以,不能只满足对首字进行hash。

我的原始想法是: 每读入字符串一个新的字符,都要能够把字符串限制到最可能小的位置范围中,直至这个限制在很小很小的范围内(由下面的C来衡量),然后在最终的这个很小很小的范围内判断是否有该字符串,从而达到最快查找。[分词效率高不高,关键是词典查找算法构造得是否优化关系很大,跟分词采用策略关系较少]

我具体采用的是,尽量hash每个字符:

第一次 对第0个字进行hash,所有首字相同的词语是一个子集合。这个子集合相对整个词典称为子词典。
循环每个子词典
   
  • 如果这个子词典的词语数 < 某个常数C(我暂使用C=16) 那这个子词典使用二分查找(对应BinaryDictionary.java)。
  •     
  • 否则 继续对这个子词典做与第一次一样的hash(只是这一次hash的字符是上一次hash的字符的后一位,即上次是第0个字符,这一次就是第1个字符,以此类推),分解出再下一级的子词典。

极端情况下设置C=2,那就是逐字匹配算法,词语查找就和词典的词汇量没有关系了,O(1)。
[该算法已在HashBinaryDictionary.java.rar的java体现。需要下载该rar替代Paoding.rar中的HashBinaryDictionary.java]


多谢楼主的解释,受教了……我之前也尝试过双重Hash,但是效率没有首字hash+折半查找高,我第一层Hash是根据词汇的长度来计算的,第二层Hash是首字Hash,最后得到词汇子表进行折半查找,可是我发现效率反而比不上首字Hash+折半查找来得高。
PS:加粗部分写错了,《基于双数组Trie树的词典查询算法》文中介绍的词典实现宣称比现有的词典实现的效率都高,楼主有空可以上google搜索这篇论文来比对一下。
26 楼 Qieqie 2007-01-26  
对了,“庖丁”是支持自定义算法的。实现特制的Knife,然后注册到Paoding这个类便可。现在这个注册过程由XFactory.java负责,有兴趣时可以弄成Spring xml配置。
25 楼 Qieqie 2007-01-25  
我矛盾中....

“羽毛球拍卖了”如何解词? 最短路径的切分方法的切分结果会是什么?
24 楼 方世玉 2007-01-25  
Qieqie 写道
菲利浦思 写道
这种切分还是有很明显的缺点.例如下面一段文字:
"发展社区老年活动场所和服务设施"

如果我想搜索日本的和服相关资料,输入关键字"和服"的时候,上面的资料也会被搜索出来



搜索引擎是第一步搜索:
      在浩瀚的信息中,快速集结最后可能是所想要的结果,按照可能是最好的顺序展现出来。

人的眼睛是第二步搜索:
      找寻最符合要求的结果,同时将机器无法轻易识别的少数“无效”结果过滤

“和服”问题,涉及了汉语语义的问题,几乎不可完全解决(可作为“特例”解决,或通过排序方法,将他排到相对靠后等价解决)。




涉及语义的问题也可以通过数学的方法来解决。楼主可以参考一下google上的那个基于最短路径的切分方法。
象“结合成分子时”这样的句子用词库的最长匹配是解决不了。基于概率的最短路径就可以。
23 楼 Qieqie 2007-01-25  
billgmh 写道
我也正在就中文分词方向进行研究,也是使用首字hash+折半查找的方法构造词典的,是我尝试过分词效率最高的一种词典实现方式,但是最近我收集到一份论文《基于双数组Trie树的词典查询算法》,发现效率可能比基于双数组Trie树的词典查询算法还要高(利用有穷自动机的原理与Trie树的易扩展性),不知楼主有没有尝试过这种方法呢?


加粗的句子看不明白是什么意思。

HashBinaryDictionary.java.rar中的java文件,他不是单纯的首字hash+折半查找。

只要参数设置的好,可以认为采用hash查找的时间复杂度是O(1),而折半不管怎么说也是log2n,而且每次折半比较都要对字符串和目标词语各个字符进行compare。所以,不能只满足对首字进行hash。

我的原始想法是: 每读入字符串一个新的字符,都要能够把字符串限制到最可能小的位置范围中,直至这个限制在很小很小的范围内(由下面的C来衡量),然后在最终的这个很小很小的范围内判断是否有该字符串,从而达到最快查找。[分词效率高不高,关键是词典查找算法构造得是否优化关系很大,跟分词采用策略关系较少]

我具体采用的是,尽量hash每个字符:

第一次 对第0个字进行hash,所有首字相同的词语是一个子集合。这个子集合相对整个词典称为子词典。
循环每个子词典
   
  • 如果这个子词典的词语数 < 某个常数C(我暂使用C=16) 那这个子词典使用二分查找(对应BinaryDictionary.java)。
  •     
  • 否则 继续对这个子词典做与第一次一样的hash(只是这一次hash的字符是上一次hash的字符的后一位,即上次是第0个字符,这一次就是第1个字符,以此类推),分解出再下一级的子词典。

极端情况下设置C=2,那就是逐字匹配算法,词语查找就和词典的词汇量没有关系了,O(1)。
[该算法已在HashBinaryDictionary.java.rar的java体现。需要下载该rar替代Paoding.rar中的HashBinaryDictionary.java]
22 楼 alin_ass 2007-01-25  
Qieqie 写道

感觉在RedSage.com上申请个版本控制服务是个不错注意




code.google.com的svn最好用了啊,又不用申请
前阵子光纤断了我都照用,

sf目前的速度基本废了



你求职的事情,我发你站内短信了,请回复或加我msn
21 楼 alin_ass 2007-01-25  
为了在我的eclipse里看你的代码, 我中午牺牲休息时间写了一个小小的批量转码的软件,类似iconv
20 楼 Qieqie 2007-01-25  

感觉在RedSage.com上申请个版本控制服务是个不错注意
19 楼 dwangel 2007-01-25  
subversion不好吗?
18 楼 Qieqie 2007-01-25  
netfishx 写道
查了一下,楼主似乎没有处理噪声词啊


是啊,bug!

bugfix:

请在com.sohospace.paoding.cjk.FileWordsLoader.java的loadCJKVocabulary方法返回前加上如下以行代码:
Merger.remove(base, ejk.get("x干扰词"));


经过调试解决了该bug!


alin_ass 写道
lz,你的代码包是gbk的,我把源码部分转成utf8传上来,需要的来下附件


>>>>>感谢中,我已经把说明加到主贴上了。


不知哪里有较好的网上 版本控制器 推荐下? 这样该代码就好办了。
17 楼 netfishx 2007-01-25  
查了一下,楼主似乎没有处理噪声词啊
16 楼 alin_ass 2007-01-25  
lz,你的代码包是gbk的,我把源码部分转成utf8传上来,需要的来下附件
15 楼 Qieqie 2007-01-25  


Merger.merge()方法在com.sohospace.paoding.cjk.FileWordsLoader.java的loadCJKVocabulary()方法中使用。

目的是:将读到的多个词语清单(LinkedList的形式)合并到第一个LinkedList中,并且保持升序。从而支持多个词典文件组成一个大词典(Vocabulary)。

Merger.merge()采用的是归并算法。

14 楼 xingqing 2007-01-25  
/*
* 本代码所有权归作者所有 但在保持源代码不被破坏以及所有人署名的基础上 任何人可自由无限使用
*/
package com.sohospace.dictionary.support.merging;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.ListIterator;

/**
*
* @author zhiliang.wang@yahoo.com.cn
*
* @since 1.0
*
*/
public class Merger {

public static void merge(LinkedList<String> a, LinkedList<String> b) {
ListIterator<String> aIter = (ListIterator<String>) a.iterator();
ListIterator<String> bIter = (ListIterator<String>) b.iterator();
while (aIter.hasNext() && bIter.hasNext()) {     //判断有没有元素
String aWord = aIter.next();
System.out.println("aWord="+aWord);
boolean bGoOn = true;
while (bGoOn && bIter.hasNext()) {
String bWord = bIter.next();
System.out.println("bWord="+bWord);
int r = bWord.compareTo(aWord);
System.out.println("r="+r);
if (r == 0) {
continue;
}
if (r < 0) {
aIter.previous();
aIter.add(bWord);
aIter.next();
}
else {
bIter.previous();
bGoOn = false;
}
}
}
while (bIter.hasNext()) {
a.add(bIter.next());
}
}

public static void remove(LinkedList<String> a, LinkedList<String> b) {
ListIterator<String> aIter = (ListIterator<String>) a.iterator();
ListIterator<String> bIter = (ListIterator<String>) b.iterator();
while (aIter.hasNext() && bIter.hasNext()) {
String aWord = aIter.next();
boolean bGoOn = true;
while (bGoOn && bIter.hasNext()) {
String bWord = bIter.next();
int r = bWord.compareTo(aWord);
if (r == 0) {
aIter.remove();
if (aIter.hasNext()) {
aWord = aIter.next();
}
}
else if (r < 0){
continue;
}
else {
bIter.previous();
bGoOn = false;
}
}
}
}

public static void main(String[] args) {
LinkedList<String> a = new LinkedList<String>();
LinkedList<String> b = new LinkedList<String>();
a.add("1");
a.add("4");
a.add("a");
a.add("c");

b.add("2");
b.add("3");
b.add("b");
b.add("d");
b.add("太阳");

Merger.merge(a, b);
//Merger.remove(a, b);

System.out.println(Arrays.toString(a.toArray(new String[]{})));
   // System.out.println(Arrays.toString(b.toArray(new String[]{})));
}
}

运行后为aWord=1
bWord=2
r=1
aWord=4
bWord=2
r=-2
bWord=3
r=-1
bWord=b
r=46
aWord=a
bWord=b
r=1
aWord=c
bWord=b
r=-1
bWord=d
r=1
[1, 2, 3, 4, a, b, c, d, 太阳]
这个类在程序中起到什么作用?
13 楼 billgmh 2007-01-25  
<br/>
<strong>Qieqie 写道:</strong><br/>
<div class='quote_div'>
<p><font><strong>Lucene中文分词 “庖丁解牛” </strong></font></p>
<p><font>附件 为本人设计编写的组件,中文分词“庖丁解牛”,具有相当好的使用价值。。。 </font></p>
<p>高效率:我的赛扬PC <strong>1 秒</strong>解析 <strong>&gt;&gt;&gt; 20000</strong>汉字的词语  (实际测试结果数据,可达<strong>1秒10万</strong>汉字)<br/>
高可维护性:使用“庖丁”隐喻,形象明晰<br/>
高灵活性,可扩展:OOD</p>
<p><font>对比:《终于突破中文分词的效率问题》<a href='http://www.lucene.org.cn/read.php?tid=54&amp;amp;fpage=2 '>http://www.lucene.org.cn/read.php?tid=54&amp;fpage=2 </a>他的效率为 <strong>6秒</strong> 解析<strong>2588</strong>汉字<br/>
 <br/>
示例程序为<font>com.sohospace.lucene.analysis.xanalyzer.Main0</font></font></p>
<p><font/></p>
<p><font>附带广告&lt;偶<strong>寻觅工作中</strong>&gt;:</font> </p>
<p><font><strong>我是</strong>: <br/>
接近5年Java/J2EE开发经验。good at Java底层基础, 网站开发架构与技术, 设计模式, 面向对象。 <br/>
崇尚有效的工作和管理。 </font></p>
<p><font><strong>我要</strong>: <br/>
找一个Java/J2EE架构师、高级工程师职位(北京)。</font></p>
<p><font>我的联系方法: <br/>
email: leyan_cc.wang@yahoo.com.cn <br/>
skype:jimudugushi <br/>
tel: 133-xxxx-0083</font></p>
<p><font> </font></p>
<p> </p>
</div>
我也正在就中文分词方向进行研究,也是使用首字hash+折半查找的方法构造词典的,是我尝试过分词效率最高的一种词典实现方式,但是最近我收集到一份论文《<font>基于双数组Trie树的词典查询算法》,发现效率可能比<font>基于双数组Trie树的词典查询算法还要高(利用有穷自动机的原理与Trie树的易扩展性),不知楼主有没有尝试过这种方法呢?</font></font><br/>

相关推荐

    lucene 中文分词 庖丁解牛

    《Lucene中文分词:庖丁解牛》 在信息技术高速发展的今天,全文搜索引擎已经成为网站内容检索不可或缺的一部分。其中,Apache Lucene作为一个开源的全文检索库,被广泛应用于各种项目中,尤其对于处理中文文本,...

    lucene中文分词(庖丁解牛)庖丁分词

    《Lucene中文分词——庖丁解牛》 在自然语言处理领域,中文分词是基础且关键的一环。在Java开发中,Apache Lucene是一个强大的全文搜索引擎库,但默认并不支持中文,这就需要借助第三方分词工具。本文将深入探讨...

    lucene3庖丁解牛中文分词器

    《深入剖析:Lucene3与庖丁解牛中文分词器》 在信息技术飞速发展的今天,全文检索和搜索引擎已经成为日常开发中不可或缺的部分。Lucene作为一款强大的全文检索库,被广泛应用于各种信息检索系统中。然而,对于中文...

    lucene Analyzer 庖丁解牛 中文分词

    《Lucene Analyzer剖析:中文分词的奥秘》 在信息检索领域,Lucene作为一款强大的全文搜索引擎库,被广泛应用于各种系统中。其核心功能之一就是对输入文本进行高效精准的分词处理,以便进行后续的索引和查询操作。...

    Lucene 庖丁解牛分词法2.4版本jar包

    总的来说,"庖丁解牛分词法"为Lucene提供了一种高效的中文分词解决方案,显著提升了中文信息检索的准确性和用户体验。通过不断优化和更新,如"paoding-analysis-2.0.4-alpha2"这样的分词工具,使得开发者能够更好地...

    paoding analysis 3.0.1 jar (庖丁解牛分词器)

    由于庖丁官方目前提供可下载尚不支持Lucene 3.0以上版本。因此作者对paoding进行重新编译,使其与最新Lucene 3.0.1版本适用。 Latest paoding 3.0.1 for lucene 3.0.1 使用说明: 先下载2.0.4的版本(h t t p : / ...

    庖丁解牛,一种中文分词器

    总的来说,"庖丁解牛"分词器是中文信息处理领域的一个强大工具,它与Lucene的结合进一步增强了对中文文本的处理能力。对于需要处理大量中文文本的开发者来说,掌握这款分词器的使用和集成技巧是非常有价值的。通过...

    lucene中文分词器(paoding解牛)

    Paoding这个名字来源于中国古代的一种宰牛技术,寓意其对中文文本的“解构”能力,如同庖丁解牛般精细入微。 Paoding的核心特点包括: 1. **智能词典**:Paoding使用了一种动态加载的词典机制,能够根据上下文信息...

    庖丁解牛工具

    “Lucene分词器”是"庖丁解牛工具"的一个重要组成部分。Apache Lucene是一个高性能、全文本搜索库,它是Java开发者常用来构建搜索引擎的工具。而"庖丁解牛"则为Lucene提供了针对中文的分词支持,使得开发者可以更好...

    Lucene加庖丁解牛测试类

    本文将深入探讨“Lucene加庖丁解牛测试类”,旨在帮助读者理解Lucene的核心概念,并通过实际的测试类解析,提升对Lucene的运用能力。 首先,我们需要理解“庖丁解牛”的含义。这源自古代典故,意指做事技艺娴熟,能...

    适用于lucene..5的庖丁解牛分词器

    可以适用于lucene3.5的庖丁解牛分词器jar包

    Lucene3.0以上版本庖丁解牛分词法demo

    最新庖丁解牛分词法的使用demo,支持Lucene3.3、3.4等3.0以上版本,庖丁解牛的分词包为自己编译生成的,之前的2.0的版本不能支持Lucene3.0以上版本,所以需要从svn下载最新的庖丁解牛源码,生成jar文件(我同样已...

    庖丁解牛 源码 for Lucene 2.4

    《庖丁解牛 源码 for Lucene 2.4》是一份针对开源全文搜索引擎Lucene 2.4版本的深度解析资料。这个压缩包包含的文件名为"paoding-for-lucene-2.4",很可能是针对中文处理的Paoding Lucene库的源代码分析或扩展。...

    lucene3.0 分词器

    lucene3.0 中文分词器, 庖丁解牛

    sorlr + tomcat+ 庖丁解牛中文分词 配置文档

    标题 "sorlr + tomcat+ 庖丁解牛中文分词 配置文档" 提到的是一个关于在Apache Solr中集成Tomcat服务器,并利用庖丁解牛中文分词工具进行中文处理的配置教程。这个配置过程对于搭建支持中文搜索的Solr环境至关重要。...

    lucene最新版本加庖丁解牛实现搜索引擎

    《使用Lucene最新版与庖丁解牛方法构建搜索引擎》 在信息技术日新月异的今天,搜索引擎已经成为了我们获取信息的重要工具。Apache Lucene是一个高性能、全文本搜索库,被广泛应用于各种搜索引擎的开发中。本文将...

    支持Lucene3.3、3.4的庖丁解牛分词法的源码和jar包

    资源为庖丁解牛分词法的最新源码以及生成的jar包,支持最新的Lucene3.4以及Lucene3.0以上版本。Jar包为本地生成,大家也可以到SVN上检出自己生成,另外庖丁解牛分词法的使用Demo我会接下来上传一份,欢迎分享。

    lucene3.0庖丁+索引搜索程序

    《深入剖析Lucene3.0:庖丁解牛与索引搜索实践》 在IT行业中,搜索引擎技术扮演着至关重要的角色,而Lucene作为一个开源全文检索库,为开发者提供了强大的文本搜索功能。本文将深入探讨Lucene3.0版本,结合“庖丁解...

    庖丁解牛分词器jar包

    Paoding's Knives 中文分词具有极 高效率 和 高扩展性 。引入隐喻,采用完全的面向对象设计,构思先进。 高效率:在PIII 1G内存个人机器上,1秒 可准确分词 100万 汉字。 采用基于 不限制个数 的词典文件对文章...

    paoding(庖丁解牛)

    ### Paoding庖丁解牛:中文分词库与Nutch集成详解 #### 一、Paoding庖丁解牛概述 Paoding庖丁解牛是一款基于Java语言开发的中文分词库,它能够作为中文搜索引擎的一个关键组件进行部署,特别是在Lucene这样的搜索...

Global site tag (gtag.js) - Google Analytics