自然语言处理:分词方法

正向最大匹配分词

  • 最大正向匹配(FMM)的基本思想是:假设自动分词词典中的最长词条所含汉字个数为L,则从左往右取被处理材料S1的前L个字作为匹配字段,查找分词词典。若词典中有这样的一个长度为L的相同词,则匹配成功,匹配字段作为一个词被切分出来;否则,匹配失败,匹配字段去掉最后一个汉字,剩下的字符作为新的匹配字段,进行新的匹配,如此进行下去,直至切分成功或匹配字段为单字为止。
  • 举例说明:词典wordDict={u"计算语言学",u"课程",u"课时"},待处理材料S1=u"计算语言学课程有三个课时",词典中所含最大词条包含的汉字个数为5,那么正向最大匹配分词的过程如下:

(1)S2="",S1不为空,从S1左边取出候选子串W="计算语言学";

(2)查词表,“计算语言学”在词表中,将W加入到S2中,S2=“计算语言学/”,并将W从S1中去掉,此时 S1="课程有三个课时";

(3)S1不为空,于是从S1左边取出候选子串W="课程有三个";

(4)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程有三";

(5)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程有";

(6)查词表,W不在词表中,将W最右边一个字去掉,得到W="课程"

(7)查词表,W在词表中,将W加入到S2中,S2=“计算语言学/课程/”,并将W从S1中去掉,此时S1="有三个课时";

(8)S1不为空,于是从S1左边取出候选子串W="是三个课时";

(9)查词表,W不在词表中,将W最右边一个字去掉,得到W="有三个课";

(10)查词表,W不在词表中,将W最右边一个字去掉,得到W="有三个";

(11)查词表,W不在词表中,将W最右边一个字去掉,得到W="有三"

(12)查词表,W不在词表中,将W最右边一个字去掉,得到W=“有”,这时     W是单字,将W加入到S2中,S2=“计算语言学/课程/有/”,并将W从S1中去掉,此时S1="三个课时";

(13)S1不为空,从S1左边取出候选子串W="三个课时";

(14)查词表,W不在词表中,将W最右边一个字去掉,得到W="三个课";

(15)查词表,W不在词表中,将W最右边一个字去掉,得到W="三个";

(16)查词表,W不在词表中,将W最右边一个字去掉,得到W=“三”,这时     W是单字,将W加入到S2中,S2=“计算语言学/课程/有/三/”,并将W从S1中去掉,此时S1="个课时";

(17)S1不为空,从S1左边取出候选子串W="个课时";

(18)查词表,W不在词表中,将W最右边一个字去掉,得到W="个课";

(19)查词表,W不在词表中,将W最右边一个字去掉,得到W=“个”,这时W是单字,将W加入到S2中,S2=“计算语言学/课程/有/三/个/",并将W从S1中去掉,此时S1="课时";

(20)S1不为空,从S1左边取出候选子串W="课时";

(21)查词表,W在词表中,将W加入到S2中,S2=“计算语言学/课程/有/三/个/课时/",并将W从S1中去掉,此时S1=""。

(22)S1为空,输出S2作为分词结果,分词过程结束。

  • 算法流程图

  • 反向最大匹配分词

  • 与FMM方法相对应的方法是反向最大匹配分词方法,也称为RMM方法。它的分词过程与FMM方法相同,不过是从句子(或文章)末尾开始处理,每次匹配不成功时去掉的是前面的一个汉字。
  • python 代码示例
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
中文分词算法
"""

def FMM(wordDict, maxLen, match_string):
    """
    正向最大匹配算法
    :param wordDict: 词典
    :param maxLen: 匹配最大长度
    :param match_string: 待匹配字符串
    :return: 匹配结果
    """
    wordList = []
    segStrLen = len(match_string)
    while segStrLen > 0:
        if segStrLen > maxLen:
            wordLen = maxLen
        else:
            wordLen = segStrLen
        subStr = match_string[0:wordLen]
        while wordLen > 1:#词典中有匹配词/单字,退出
            if subStr in wordDict:
                break
            else:
                wordLen = wordLen - 1
                subStr = subStr[0:wordLen]
        wordList.append(subStr)
        match_string = match_string[wordLen:]
        segStrLen = segStrLen - wordLen

    return "/".join(wordList)

def RMM(wordDict, maxLen, match_string):
    """
    逆向最大匹配算法
    :param wordDict: 词典
    :param maxLen: 匹配最大长度
    :param match_string: 待匹配字符串
    :return: 匹配结果
    """
    wordList = []
    segStrLen = len(match_string)
    while segStrLen > 0:
        if segStrLen > maxLen:
            wordLen = maxLen
        else:
            wordLen = segStrLen
        subStr = match_string[-wordLen:]
        while wordLen > 1:#词典中有匹配词/单字,退出
            if subStr in wordDict:
                break
            else:
                wordLen = wordLen - 1
                subStr = subStr[-wordLen:]
        wordList.append(subStr)
        match_string = match_string[0:-wordLen]
        segStrLen = segStrLen - wordLen

    return "/".join(wordList)

def exper():
    wordDict = [u"计算语言学",u"课程",u"课时"]
    S1 = u"计算语言学课程有三个课时"
    maxLen = 5
    print FMM(wordDict,maxLen,S1)
    print RMM(wordDict, maxLen, S1)

if __name__ == '__main__':
    exper()

  • 基于统计的词网格分词

  • 与基于词网格分词的第一步是候选词网格构造:利用词典匹配,列举输入句子所有可能的切分词语,并以词网格形式保存。实际上,词网格是一个有向无环图,它蕴含了输入句子所有可能的切分,其中的每一条路径代表一种切分。如下图“中国人民生活“的切分词网:
  • 词网分词的第二步是计算词网格中的每一条路径的权值,权值通过计算图中每一个节点(每一个词)的一元统计概率和节点之间的二元统计概率的相关信息。然后根据图搜索算法在图中找到一条权值最小的路径,对应的路径即为最后的分词结果。

  • 双向最大匹配分词

  • 比较FMM法与RMM法的切分结果,从而决定正确的切分(比较规则可以自定义),可以识别出分词中的交叉歧义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值