lucene 分词原理

来源:互联网 发布:轻薄本推荐 知乎 编辑:程序博客网 时间:2024/05/21 18:33


(一)
Lucene是一个高性能的 java 全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:

0)设有两篇文章 1 和 2  
文章1 的内容为: Tom lives in Guangzhou,I live in Guangzhou too.  
文章2 的内容为: He once lived in Shanghai.  

1)由于 lucene 是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施  
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。  
b.文章中的 ” in ” ,  “ once ” “ too ” 等词没有什么实际意义,中文中的 “ 的 ”“ 是 ” 等字通常也无具体含义,这些不代表概念的词可以过滤掉  
c.用户通常希望查 “ He ” 时能把含 “ he ” , “ HE ” 的文章也找出来,所以所有单词需要统一大小写。  
d.用户通常希望查 “ live ” 时能把含 “ lives ” , “ lived ” 的文章也找出来,所以需要把 “ lives ” , “ lived ” 还原成 “ live ”  
e.文章中的标点符号通常不表示某种概念,也可以过滤掉  
在lucene 中以上措施由 Analyzer 类完成  

经过上面处理后  
文章1 的所有关键词为: [tom] [live] [guangzhou] [i] [live] [guangzhou]  
文章2 的所有关键词为: [he] [live] [shanghai]  

2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是: “ 文章号 ” 对 “ 文章中所有关键词 ” 。倒排索引把这个关系倒过来,变成: “ 关键词 ” 对 “ 拥有该关键词的所有文章号 ” 。文章 1 , 2 经过倒排后变成  
关键词 文章号  
guangzhou 1  
he 2  
i 1  
live 1,2  
shanghai 2  
tom 1  

通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:
a) 字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);
b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组( phase )查询快), lucene 中记录的就是这种位置。  

加上“ 出现频率 ” 和 “ 出现位置 ” 信息后,我们的索引结构变为:  
关键词 文章号[ 出现频率 ]  出现位置  
guangzhou 1[2] 3, 6  
he 2[1] 1  
i 1[1] 4  
live 1[2],2[1] 2, 5 , 2  
shanghai 2[1] 3  
tom 1[1] 1  

以live  这行为例我们说明一下该结构: live 在文章 1 中出现了 2 次,文章 2 中出现了一次,它的出现位置为 “ 2,5,2 ” 这表示什么呢?我们需要结合文章号和出现频率来分析,文章 1 中出现了 2 次,那么 “ 2,5 ” 就表示 live 在文章 1 中出现的两个位置,文章 2 中出现了一次,剩下的 “ 2 ” 就表示 live 是文章 2 中第  2 个关键字。  

以上就是lucene 索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的( lucene 没有使用 B 树结构),因此 lucene 可以用二元搜索算法快速定位关键词。  

实现时 lucene 将上面三列分别作为词典文件( Term Dictionary )、频率文件 (frequencies) 、位置文件  (positions) 保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。  

Lucene中使用了 field 的概念,用于表达信息所在位置(如标题中,文章中, url 中),在建索引中,该 field 信息也记录在词典文件中,每个关键词都有一个 field 信息 ( 因为每个关键字一定属于一个或多个 field) 。  

为了减小索引文件的大小,Lucene 对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为 < 前缀长度,后缀 > ,例如:当前词为 “ 阿拉伯语 ” ,上一个词为 “ 阿拉伯 ” ,那么 “ 阿拉伯语 ” 压缩为 <3 ,语 > 。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是 16389 (不压缩要用 3 个字节保存),上一文章号是 16382 ,压缩后保存 7 (只用一个字节)。  

下面我们可以通过对该索引的查询来解释一下为什么要建立索引。  
假设要查询单词 “ live ” , lucene 先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。  
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。



(二)

建立索引和查询的过程中,都是以基本的语素项为单位的。基本的语素项就是通过分词得到。这个过程决定了索引单元金额最终的匹配过程。 
分词在文本索引的建立过程和用户提交检索过程中都存在。利用相同的分词器,把短语或者句子切分成相同的结果,才能保证检索过程顺利进行。 
1、 英文分词的原理 
基本的处理流程是:输入文本、词汇分割、词汇过滤(去除停留词)、词干提取(形态还原)、大写转为小写、结果输出。 
2、 中文分词原理 
中文分词比较复杂,并没有英文分词那么简单。这主要是因为中文的词与词之间并不像英文中那样用空格来隔开。 
主要的方法有三种:基于词典匹配的分词方法、基于语义理解的分词、基于词频统计的分词。 
①      基于词典匹配的分词方法 
基 于字典匹配的分词方法按照一定的匹配策略将输入的字符串与机器字典词条进行匹配。如果在词典中找到当前字符串,则匹配成功输出识别的词汇。按照匹配操作的 扫描方向不同,字典匹配分词方法可以分为正向匹配和逆向匹配,以及结合了两者的双向匹配算法;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最 小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与词性标注相结合的方法。几种常用的词典分词方法如下所示: 
● 正向最大匹配(由左到右的方向)。 
● 逆向最大匹配(由右到左的方向)。 
● 最少切分(是每一句中切除的词数最小)。 
实际应用中上述各种方法经常组合使用,达到最好的效果,从而衍生出了结合正向最大匹配方法和逆向最大匹配算法的双向匹配分词法。由于中分词最大的问题是歧义处理,结合中文语言自身的特点,经常采用逆向匹配的切分算法,处理的精度高于正向匹配,产生的切分歧义现象也较少。 
真正实用的分词系统,都是把词典分词作为基础手段,结合各种语言的其他特征信息来提高切分的效果和准确度。有的实用系统中将分词和词性标注结合起来,利用句法和词法分析对分词决策提高帮助,在词性标注过程中迭代处理,利用词性和语法信息对分词结果进行检验、调整。 
既然是基于分词词典的分词方法,当然还要考虑选择一个好的查找词典算法。一般有数字搜索树, Trie 算法等等。 
所 谓的数字搜索树( retrieve 树)就是要求树的一个节点保留一个字符。如果一个单词比一个字符长,则包含第一个字符串的节点有指向下一个字符的节 点,以此类推。这样组成一个层次结构的树,树的第一层包括所有单词的第一个字符,树的第二层包括所有单词的第二个字符,以此类推,数字搜索树的最大高度是 词典中最长单词的长度。但是这样的树,每一个节点都需要很多内存。假设每个词都是由一个小写英文字母组成的,这个节点中会有 26 个指针。所以不太可能 直接用这样的数字搜索树来存储中文这样的大字符集。 
Trie 树, 即三叉搜索树,每一个节点包括一个字符,但只有三个指针,一个指向左边的树,一个指向右边的树,还有一个向下,指向单词的下一个数据单元。三叉搜索树是二 叉搜索树和数字搜索树的混合体。它有和数字搜索树差不多的速度但是和二叉搜索树一样只需要相对较少的内存空间。单词的读入顺序对于创建平衡的三叉搜索树很 重要,但对于二叉搜索树就不是太重要了。由于限于篇幅,这里就不写上代码了。 
②      基于语义理解的分词 
基于语义理解的分词方法是模拟人脑对语言和句子的理解,达到识别词汇单元的效果。基本模式是把分词、句法、语义分析并行进行,利用句法和语义信息来处理分词的歧义。 
一般结构中通常包括分词子系统、句法语义子系统、调度系统。在调度系统的协调下,分词子系统可以获得有关词、句子等的句法和语义信息,模拟人脑对句子的理过程。基于语义理解的分词方法需要使用大量的语言知识和信息。 
目前国内外对汉语语言知识的理解和处理能力还没有达到语义层面,具体到语言信息很难组织成机器可直接读取、计算的形式,因此目前基于语义理解的分词系统还处在试验阶段。 
③      基于词频统计的分词 
这种做法基于人们对中文词语的直接感觉。通常词是稳定的词的组合,因此在中文文章的上下文中,相邻的字搭配出现的频率越多,就越有可能形成一个固定的词。根据 n 元语法知识可以知道,字与字相邻同时出现的频率或概率能够较好地反映成词的可信度。 
实 际的系统中,通过对精心准备的中文语料中相邻共现的各个字的组合的频度进行统计,计算不同字词的共现信息。根据两个字的统计信息,计算两个汉字的相邻共现 概率。统计处来的信息体现了中文环境下汉字之间结合紧密程度。当紧密程度高于某一个阈值时,便可认为此字组可能构成一个词。 
基 于词频统计的分词方法只需要对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计分词方法。这种方法经常抽出一些共现频度高、但并 不是词的常用字组,需要专门处理,提高精确度。实际应用的统计分词系统都使用一个基本的常用词词典,把字典分词和统计分词结合使用。基于统计的方法能很好 地解决词典未收录新词的处理问题,即将中文分词中的串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,有利用了无词典分词结合上下文识 别生词、自动消除歧义的优点。 
3、 Lucene 分词 
在 Lucene3.0 中, 对分词主要依靠 Analyzer 类解析实现。 Analyzer 内部主要通过 TokenStream 类实 现。 Tonkenizer 类, TokenFilter 类是 TokenStream 的两个子类。 Tokenizer 处理单个字符组成的字符 流,读取 Reader 对象中的数据,处理后转换成词汇单元。 TokneFilter 完成文本过滤器的功能,但在使用过程中必须注意不同的过滤器的使用的顺序。

0 0