当前位置:   article > 正文

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

中文分词技术python

中文分词技术(一)

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

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

规则分词

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

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

正向最大匹配法(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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

结果如下所示:


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


逆向最大匹配法(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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

结果如下所示:


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


双向最大匹配法
  • 基本思想
    双向最大匹配法将正向和逆向的结果进行比较,按照最大匹配原则,选择词数切分最少的作为结果
  • 双向最大匹配规则
    • 如果结果词数不同,返回分词数量较少的一个;
    • 如果结果词数相同
      • 分词结果相同,任意返回一个
      • 分词结果不同,返回单个字较少的一个
  • 代码示例
#定义双向最大匹配法的类
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

结果如下所示:


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


统计分词

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

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

  • 建立统计语言模型
  • 对句子进行单词划分,对划分结果进行概率计算(隐马尔可夫【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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/379627
推荐阅读
相关标签
  

闽ICP备14008679号