基于规则的自动分词算法

所谓中文分词,就是将中文语句中的词汇切分出来。中文文本自动分词算法从20世纪80年代以来就一直是研究热点。分词技术作为自然语言处理的基础环节,同时也是关键环节之一,它的质量好坏直接影响到后续处理步骤的效果。

本文将讨论三种基于规则的中文分词算法,分别是正向最大匹配法、逆向最大匹配法、双向匹配法,介绍其要点及优缺点,并代码实现。

 

 (一)基于规则的自动分词算法

(1)简介:事先人工建立好分词词典和分词规则库,基于字符串匹配进行分词,要求有足够大的词表为依据。

(2)优缺点:当分词词典所收容的词较少时,覆盖率有限导致分词的正确率低。

(3)算法:正向最大匹配法、逆向最大匹配法、双向匹配法。

 

(二)正向最大匹配算法(Maximum Matching Method, MM)

 一、 主要原理

切分出单字串,然后和词库进行比对,如果是一个词就记录下来, 否则通过增加或者减少一个单字,继续比较,一直还剩下一个单字则终止。

二、算法描述

设MaxLen表示最大词长,D为分词词典。

①从待切分语料中按正向取长度为MaxLen的字串str,令Len=MaxLen;

②把str与D中的词相匹配;

③若匹配成功,则认为该字串为词,指向待切分语料的指针向前移Len个汉字(字节),返回到①;

④若不成功:如果Len>1,则将Len减2个字节,从待切分语料中取长度为Len的字串str,返回到②。否则,得到长度为2的单字词,指向待切分语料的指针向前移1个汉字,返回①。

三、优点分析

① 扫描方向从左到右,从长到短的顺序匹配;

② 原理简单,程序容易实现,复杂度低。

四、举例演示

待分词文本: content[]= 
{“中”,”华”,”民”,”族”,”从”,”此”,”站”,”起”,”来”,”了”,”。”} 
词表: dict[]={“中华”, “中华民族” , “从此”,”站起来”}

(1) 从content[1]开始,当扫描到content[2]的时候,发现”中华”已经在词表dict[]中了。但还不能切分出来,因为我们不知道后面的词语能不能组成更长的词(最大匹配)。

(2) 继续扫描content[3],发现”中华民”并不是dict[]中的词。但是我们还不能确定是否前面找到的”中华”已经是最大的词了。因为”中华民”是dict[2]的前缀。

(3) 扫描content[4],发现”中华民族”是dict[]中的词。继续扫描下去:

(4) 当扫描content[5]的时候,发现”中华民族从”并不是词表中的词,也不是词的前缀。因此可以切分出前面最大的词——”中华民族”。

五、算法实现(java)

  public static List forwardSeg(String text){  
        List result=new ArrayList();  
        while(text.length()>0){  
            int len=MAX_LENGTH;       
            if(text.length()<MAX_LENGTH){  
                len=text.length();  
            }  
            String tryWord=text.substring(0, len);                     
            while(!DIC.contains(tryWord)){ 
                if(tryWord.length()==1)
                    break;  
                tryWord=tryWord.substring(0, tryWord.length()-1);                             
            }         
            result.add(tryWord+"/");  
            text=text.substring(tryWord.length());  
        }  
        return result;  
    }  

六、缺点分析

(1)忽视“词中有词”的现象,导致切分错误;

(2)最大词长难以确定:

  ①太长:匹配所花时间多,算法时间复杂度高;

  ②太短:不能切分长度超过它的词,导致切分正确率降低。

七、改良方向

正向最大匹配分词FMM(Forward Maximum Matching)算法存在设定的最大词长初始值固定不变的问题,带来长词丢失或匹配次数较多的弊端。针对此问题提出了根据中文分词词典中的词条长度动态确定截取待处理文本长度的思想,改进了FMM算法。与此相配合,设计了一种词典结构,使之能够有效地支持改进的算法。改进的算法与一般正向最大匹配算法相比大大减少了匹配次数,分析表明中文分词的速度和效率有了很大提高【参考文献

 

(三)逆向最大匹配算法(Reverse Maximum Matching Method, RMM)

 一、 主要原理

切分出单字串,然后和词库进行比对,如果是一个词就记录下来, 否则通过增加或者减少一个单字,继续比较,一直还剩下一个单字则终止。

二、算法描述

设MaxLen表示最大词长,D为分词词典。

(1)将文章分成句子(通过标点符号来实现);

(2)循环的读入每一个句子S,设句子中的字数为n;

(3)设置一个最大词长度,就是我们要截取的词的最大长度max;

(4)从句子中取n-max到n的字符串subword,去字典中查找是否有这个词。如果有就走(5),没有就走(6);

(5)记住subword,从n-max付值给n,继续执行(4),直到n=0。

(6)将max-1,再执行(4)。

三、举例演示

例子:“我一个人吃饭”。 
反向最大匹配方式,最大长度为5。

一个人吃饭 
个人吃饭 
人吃饭 
吃饭 ====>得到一个词: 吃饭

我一个人 
一个人 
个人 ====>得到一个词: 个人

我一 
一 ====>得到一个词: 一

我 ====>得到一个词: 我

最后反向最大匹配的结果是: 
/我/一/个人/吃饭/

四、算法实现(java)

 1 public static List reverseSeg(String text){  
 2         Stack<String> result=new Stack();  
 3         while(text.length()>0){  
 4             int len=MAX_LENGTH;       
 5             if(text.length()<MAX_LENGTH){  
 6                 len=text.length();  
 7             }  
 8             String tryWord=text.substring(text.length()-len);  
 9             while(!DIC.contains(tryWord)){ 
10                 if(tryWord.length()==1){  
11                     break;  
12                 }  
13                 tryWord=tryWord.substring(1);                             
14             }  
15             result.add(tryWord+"/");  
16             text=text.substring(0,text.length()-tryWord.length());        
17         }  
18         int size=result.size();  
19         List list =new ArrayList(size);  
20         for(int i=0;i<size;i++){  
21             list.add(result.pop());  
22         }  
23         return list;  
24     }

 

(四)双向最大匹配算法

 一、 主要原理

切分出单字串,然后和词库进行比对,如果是一个词就记录下来, 否则通过增加或者减少一个单字,继续比较,一直还剩下一个单字则终止。

二、算法描述

对同一个字符串分别采用MM和RMM两种方法进行切分处理,如果能够得到相同的切分结果,则认为切分成功,否则认为有疑点。针对疑点,应采用上下文信息,根据歧义规则库进行排歧;或者进行人工干预,选取一种正确的切分。

三、优点分析

克服了MM方法里忽视“词中有词”的现象。

四、缺点分析

① 算法复杂度提高。

② 为了支持正反向匹配算法,词典设置要更复杂。

③ 对某些句子仍然无法发现歧义。

 

 

posted on 2016-12-01 22:52  Denise_hzf  阅读(2838)  评论(0编辑  收藏  举报

导航