Python与自然语言处理——中文分词(一)

本文介绍了中文分词技术,包括规则分词的正向最大匹配法、逆向最大匹配法和双向最大匹配法,以及统计分词的HMM模型,并提供了相关代码示例和数据集链接。
摘要由CSDN通过智能技术生成

中文分词技术(一)

中文分词问题主要来源于:在汉语中,句子是以字为单位的,但是语义理解仍然是需要以词为单位,所以也就存在了中文分词问题。

主要的技术可以分为:规则分词、统计分词以及混合分词(规则+统计)

规则分词

基于规则的分词是一种机械分词,主要依赖于维护词典,在切分时将与剧中的字符串与词典中的词进行匹配

主要的切分方法包括三种:正向最大匹配法、逆向最大匹配法以及双向最大匹配法。

正向最大匹配法(MM法)
  • 基本思想
    假设分词词典中最长词由 i i i个汉字组成,则用被处理文档当前前 i i i个字作为匹配字段,若字典中存在这样的词则匹配成功,否则去掉最后一个字再进行查找。
  • 代码示例
#定义正向最大匹配法类
class MM(object):
    def __init__(self):
        self.window_size=3    #词典中最长字符串包含的字数
    
    def cut(self,text):
        result=[]
        index=0
        text_length=len(text)
        dic=['研究','研究生','生命','命','的','起源']   #词典
        while text_length>index:     #只要还有字就进行匹配
            for size in range(self.window_size+index,index,-1):  #生成可能长度
                piece=text[index:size]
                if piece in dic:
                    index=size-1   #匹配成功将index设置为匹配成功的最后一个字的位置
                    break
            index=index+1   #开始下一个字符串的匹配
            result.append(piece+'----')
        print(result)

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

结果如下所示:


[‘研究生----’, ‘命----’, ‘的----’, ‘起源----’]


逆向最大匹配法(RMM法)
  • 基本思路
    基本思路与正向相同,只是切分方向正好与MM法相反。从文档末尾开始处理,每次去除第一个字进行匹配,维护的也是逆序词典,每个词都按逆序方式存放。
    RMM比MM的误差小。
  • 代码示例
#定义逆向最大匹配法类
class RMM(object):
    def __init__(self):
        self.window_size=3
    
    def cut(self,text):
        result=[]
        index=len(text)  #从文本末尾开始
        dic=['研究','研究生','生命','命','的','起源'] 
        while index>0:
            for size in range(index-self.window_size,index):
                piece=text[size:index]  #找到最后几个字组成的字符串
                if piece in dic:
                    index=size+1      #将位置更新为匹配到的最后一个字的位置
                    break
            index=index-1   #开始新的位置
            result.append(piece+'----')
        result.reverse()  #由于从最后进行匹配,所以顺序是反的,需要颠倒过来
        print(result)
        
if __name__=='__main__':
    text='研究生命的起源'
    tokenizer=RMM()
    tokenizer.cut(text)

结果如下所示:


[‘研究----’, ‘生命----’, ‘的----’, ‘起源----’]


双向最大匹配法
  • 基本思想
    双向最大匹配法将正向和逆向的结果进行比较,按照最大匹配原则,选择词数切分最少的作为结果
  • 双向最大匹配规则
    • 如果结果词数不同,返回分词数量较少的一个;
    • 如果结果词数相同
      • 分词结果相同,任意返回一个
      • 分词结果不同,返回单个字较少的一个
  • 代码示例
#定义双向最大匹配法的类
class BMM(object):
    def __init__(self):
        self.window_size=3
        self.result_MM=[]
        self.result_RMM=[]
        self.num_MM=0
        self.num_RMM=0
    
    #正向最大
    def MM(self,text):
        index=0
        text_length=len(text)
        dic=['研究','研究生','生命','命','的','起源']   #词典
        while text_length>index:     #只要还有字就进行匹配
            for size in range(self.window_size+index,index,-1):  #生成可能长度
                piece=text[index:size]
                if piece in dic:
                    index=size-1   #匹配成功将index设置为匹配成功的最后一个字的位置
                    break
            index=index+1   #开始下一个字符串的匹配
            self.result_MM.append(piece+'----')
            if len(piece)==1:
                self.num_MM+=1
    
    #逆向最大
    def RMM(self,text):
        index=len(text)  #从文本末尾开始
        dic=['研究','研究生','生命','命','的','起源'] 
        while index>0:
            for size in range(index-self.window_size,index):
                piece=text[size:index]  #找到最后几个字组成的字符串
                if piece in dic:
                    index=size+1      #将位置更新为匹配到的最后一个字的位置
                    break
            index=index-1   #开始新的位置
            self.result_RMM.append(piece+'----')
            if len(piece)==1:
                self.num_RMM+=1
        self.result_RMM.reverse()  #由于从最后进行匹配,所以顺序是反的,需要颠倒过来
    
    def cut(self,text):
        if len(self.result_MM)>len(self.result_RMM):
            result=self.result_RMM
        elif len(self.result_MM)<len(self.result_RMM):
            result=self.result_MM
        elif len(self.result_MM)==len(self.result_RMM):
            if self.result_MM==self.result_RMM:
                result=self.result_RMM
            else:
                if self.num_MM>self.num_RMM:
                    result=self.result_RMM
                else:
                    result=self.result_MM
        print(result)

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

结果如下所示:


[‘研究----’, ‘生命----’, ‘的----’, ‘起源----’]


统计分词

主要思想:将每个词视作由字组成,如果相连的字在不同文本中出现次数越多,就越可能是一个词

基于统计的分词一般有以下两步:

  • 建立统计语言模型
  • 对句子进行单词划分,对划分结果进行概率计算(隐马尔可夫【HMM】、条件随机场【CRF】等)
语言模型
  • 语言模型
    为长度为 m m m的字符串确定其概率分布 P ( x 1 , x 2 , ⋯ &ThinSpace; , x m ) P\left( { {x_1},{x_2}, \cdots ,{x_m}} \right) P(x1,x2,,xm),其中 x 1 , x 2 , ⋯ &ThinSpace; , x m { {x_1},{x_2}, \cdots ,{x_m}} x1,x2,,xm为文本中的各个词语,计算公式如下:
    P ( x 1 , x 2 , ⋯ &ThinSpace; , x m ) = P ( x 1 ) P ( x 2 ∣ x 1 ) P ( x 3 ∣ x 1 , x 2 ) ⋯ P ( x m ∣ x 1 , x 2 , ⋯ &ThinSpace; , x m − 1 ) P\left( { {x_1},{x_2}, \cdots ,{x_m}} \right) = P\left( { {x_1}} \right)P\left( { {x_2}\left| { {x_1}} \right.} \right)P\left( { {x_3}\left| { {x_1},{x_2}} \right.} \right) \cdots P\left( { {x_m}\left| { {x_1},{x_2}, \cdots ,{x_{m - 1}}} \right.} \right) P(x1,x2,,xm)=P(x1)P(x2x1)P(x3x1,x2)⋯</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值