中文分词技术(一):规则分词

基于规则的分词是一种机械分词方法,主要通过维护词典,在切分语句时,将语句的每个字符串与词典中的词进行逐一匹配,找到则切分,否则不切分。按照语句切分的方式,可分为:正向最大匹配法、逆向最大匹配法、双向最大匹配法。下面将详细介绍。

一、正向最大匹配法

正向最大匹配法(Maximun Match Method,简称MM)的基本思路是:假设分词词典中最长词的长度为i个字符,则用被处理语句的前i个字符作为匹配字段,来查找词典。如果匹配到这个字段,则这个字段作为一个词被切分出来。如果词典没有匹配到这个字段,就将匹配字段的最后一个字符去掉,再把剩下的匹配字段与词典匹配,直至匹配成功或者剩余字符串长度为0。这样就完成了一轮匹配,然后取下一个i个字符的字符串进行匹配处理。

大致步骤如下:

首先定义待切分字符串s1,分词后的输出为s2,词典最大词长为maxlen

例如:词典为  ['研究','生命','命','的','研究生','起源'],则语句“研究生命的起源”可以切分为:['研究生', '命', '的', '起源']。具体代码如下:

class MM(object):
    def __init__(self):
        self.window_size=3          #词典的最长词长度
    def cut(self,text):
        dic=['研究','生命','命','的','研究生','起源']
        result=[]
        index=0
        text_length=len(text)
        while text_length>index:
            for size in range(self.window_size+index,index,-1):      
            #一个for循环为一个长度为词典中最长词条的匹配字段,没有匹配到,去掉最后一个字,再来匹配
                words=text[index:size]
                if words in dic:
                    index=size-1           #调整下一个匹配字段的起始位置
                    break                  #匹配到字典,跳出本次循环
            index+=1                   
            #出现上一个字段匹配到不在词典中的单字符时,保证正确索引下一个匹配字段的起始位置
            result.append(words + '--')
        print(result)

if __name__ =='__main__':
    text='研究生命的起源'
    cut_mm=MM()
    cut_mm.cut(text)

二、逆向最大匹配法

逆向最大匹配法(Reverse Maximum Match Method,简称RMM)的基本思想与正向自带类似,不过是分词切分的方向与MM法相反。逆向最大匹配法从待处理文本的末端开始切分匹配,每次取最末端的i个字符(i为词典中最长词数)作为匹配字段,若匹配失败,去掉匹配字段最前面的一个字,继续匹配。

需要注意的是,逆向最大匹配法使用的词典是逆序词典,词条都按逆序方式存放。 

关于准确度,与正向最大匹配法相比,逆向最大匹配法的误差要小一点。

例如: 词典为  ['研究','生命','命','的','研究生','起源'],则语句“研究生命的起源”可以切分为:['研究', '生命', '的', '起源']。

代码如下:

# coding=utf-8
#逆向最大匹配法分词
class RMM(object):
    def __init__(self):
        self.window_size=3          #词典的最长词长度
    def cut(self,text):
        dic=['研究','生命','命','的','研究生','起源']
        result=[]
        index=len(text)
        while index>0:
            for size in range(index-self.window_size,index):      
                words=text[size:index]
                if words in dic:
                    index=size+1           #调整下一个匹配字段的起始位置
                    break                  #匹配到字典,跳出本次循环
            index-=1                   
            #出现上一个字段匹配到不在词典中的单字符时,保证正确索引下一个匹配字段的起始位置
            result.append(words + '--')
        result.reverse()
        print(result)

if __name__ =='__main__':
    text='研究生命的起源'
    cut_rmm=RMM()
    cut_rmm.cut(text)

 三、双向最大匹配法

双向最大匹配法(Bi-directction Match Method)的基本思想是将正向最大匹配法得到的分词结果和逆向最大匹配法得到的结果进行比较,根据双向最大匹配原则,选取分析结果。

双向最大匹配原则:

(1)如果正反向分词结果词数不同,则取分词数量较少的那个;

(2)如果正反向分词结果词数相同:

  • 分词结果相同,可返回任意一个;
  • 分词结果不同,返回其中单字较少的那个。

例如:

# coding=utf-8
#双向最大匹配法
class MM(object):
    def __init__(self):
        self.window_size=3          #词典的最长词长度
    def cut(self,text):
        dic=['研究','生命','命','的','研究生','起源']
        result1=[]
        index=0
        text_length=len(text)
        while text_length>index:
            for size in range(self.window_size+index,index,-1):      
                words=text[index:size]
                if words in dic:
                    index=size-1           #调整下一个匹配字段的起始位置
                    break                  #匹配到字典,跳出本次循环
            index+=1                  
            result1.append(words + '--')
        print("正向最大匹配:",result1)
        return result1
class RMM(object):
    def __init__(self):
        self.window_size=3          #词典的最长词长度
    def cut(self,text):
        dic=['研究','生命','命','的','研究生','起源']
        result2=[]
        index=len(text)
        while index>0:
            for size in range(index-self.window_size,index):     
                words=text[size:index]
                if words in dic:
                    index=size+1           #调整下一个匹配字段的起始位置
                    break                  #匹配到字典,跳出本次循环
            index-=1                   
            #出现上一个字段匹配到不在词典中的单字符时,保证正确索引下一个匹配字段的起始位置
            result2.append(words + '--')
        result2.reverse()
        print("逆向最大匹配:",result2)
        return result2

if __name__ =='__main__':
    text='研究生命的起源'
    result=[]
    one_length1=0
    one_length2 = 0
    cut_mm=MM()
    result1=cut_mm.cut(text)
    cut_rmm = RMM()
    result2=cut_rmm.cut(text)
    if len(result1)==len(result2):  #正反向分词结果数相同

        if result1 ==result2 :
            #正反向分词结果数相同,结果相同,返回任意一个
            result=result1
        else:
            #统计分析结果的单字数,#正反向分词结果数相同,结果不同,返回单字少的
            for word in result1:
                if len(word)==1:
                    one_length1 +=1
            for word in result2:
                if len(word)==1:
                    one_length2 +=1
            if one_length2>one_length1:
                result=result1
            else:
                result =result2
    else:
        #正反向分词结果数不同,选择分次数少的
        if len(result1 )>len(result2 ):
            result =result2
        else:
            result = result1
    print("双向最大匹配法:",result)

综上可知,基于规则的分词一般都较为简单高效,但是词典的维护是一个很庞大的工程,很难通过词典覆盖到所有词。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值