打造自己的中文分词器之中文分词理论讲解(二)

取自 自然语言处理百科

跳转到: 导航, 搜索

上篇说到分词的时候以分蛋糕为例子来说明,从汉语语法上来说是为动宾短语,而实际上分词也是一个名词,表示的就是一个字或词,而此时“分”是个形容词,之所以叫分词就是表示这个词是经过划分出来的,此所谓分词也。

在lucene中与分词这一名词对应的单词就是token.

在讲token之前,我有几个问题想在这里提一下,比如有甲乙丙丁戊己庚辛这8个人,依序排成一行,我的问题如下:

1、丙的位置在哪里?你会如何回答呢?哦,你可能会有很多种回答,但其中一种回答会是:丙在左数第3个位置。

2、如果丁戊是一对夫妻,我想你告诉我这8个人中是一对夫妻的人的位置,你可能会回答:丁戊分别在左数第4和第5的位置,或者你还有种可能的回答是:丁在左数第4,而戊在从丁往右数1的位置上。这两种的结果其实是一样的,不是吗?

3、你能告诉我丙和戊的位置或者丙和己庚的位置吗?你的回答相比以前的回答必定要多一句:第一句是丙在左数第3位置,第二句则是已庚分别在左数第6第7的位置

到这里,要恭喜你了:你的大脑是个超级智能,超级强大的中文分词器!

恩,什么?这就是分词器?分词器就是这样简单?没错!分词器的原理就是这样的,但当然不是如此的简单,上面这3个问题只是涵盖了分词器最一般的工作,那就是单字切分与按字典切分,当然目前我也只是讲述这方面的,至于按词义分或者更复杂的智能搜索现在还没有做,所以就不会打算在这里讲了。

好了,现在我们来看下org.apache.lucene.analysis.Token里一段主要的代码(如果未加另外说明,lucene的版本均为2.2.0),如下所示:

  • String termText; //term中的值,也就是要被分的词
  • int startOffset; //termText在要被分词的文本中的起始位置
  • int endOffset; //termText在要被分词的文本中的结束位置
  • String type = "word"; //分词类型默认为word表示字典类型

不过对endOffset注意的是:由于对分词的初始位置是从0开始算起的--其实这也很好理解,在java中数组,列表等等都是从0开始算起的,所以这里的结束位置并不是当前被分的词在文本中的位置,举个例子:我爱戴运动型帽子,分词结果为,我的endOffset是1,而1对应的应该是“爱”,同样戴的endOffset是3,而3对应的是“运”,这个测试是用ShuzhenAnalyzer来进行测试的;下面再用Lucene自带的 StandardAnalyzer来进行测试:找到org.apache.lucene.index.DocumentWriter,找到224行,输入如下四行:

  • System.out.println("t.termText()>>>>>"+t.termText());
  • System.out.println(">>position>>"+position);
  • System.out.println("t.startOffset()>>>"+t.startOffset());
  • System.out.println("t.endOffset()>>>"+t.endOffset());

打印出(只举一个例子):

t.termText()>>>>>运

>>position>>3 //在 我爱戴运动型帽子 中的位置

t.startOffset()>>>3 //在 我爱戴运动型帽子 中的起始位置

t.endOffset()>>>4 //在 我爱戴运动型帽子 中的结束位置,如果从0开始的算的话,对应的是“动”,但仅仅看位置,则的确为4

所以就像我之前所提的3个问题那样,如果让你告诉我“运”这个字在“我爱戴运动型帽子”中的位置,哦,一看很显然,它就在左数第3个位置(起始为0),这个与之前的甲乙丙丁戊己庚辛排成一行又有何区别呢?

我所希望的当然就是你看完以上的东西后,能够明白:哦,原来这都是一样的。

好了,今天就先写到这里吧,写这点东西花了我2个多小时的时间,上一篇花的时间少,而这一篇花的时间长的原因,是因为我没想到上一篇会有那么多朋友关注,这让我感到了比较大的压力!所以这让我尽可能地去写得让人能明白我说的是什么。我的初衷是希望那些从来没有接触过中文分词的朋友也能看明白分词是个什么样的东东,所以我考虑从最基础的东西讲起。当然对于搜索引擎方面的高手而言,我可能有些是班门弄斧,呵呵,如果真是这样,随时愿受指点。


转自:http://www.blogjava.net/bbmonkey62/archive/2008/06/29/211477.html 作者为:bbmonkey62

个人工具
工具箱