分词算法

本文深入探讨了基于规则的分词方法,包括正向最大匹配法、逆向最大匹配法和双向最大匹配法。详细解释了每种算法的工作原理,并提供了Python实现代码,帮助读者理解如何在实际应用中进行文本分词。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行逐一匹配,找到则切分,否则不予切分。按照匹配切分的方式,主要有正向最大匹配法、逆向最大匹配法以及双向最大匹配法三种方法。


正向最大匹配算法


先设定扫描的窗口大小maxLen(最好是字典最长的单词长度),从左向右取待切分汉语句的maxLen个字符作为匹配字段。查找词典并进行匹配。若匹配成功,则将这个匹配字段作为一个词切分出来,并将窗口向右移动这个单词的长度。若匹配不成功,则将这个匹配字段的最后一个字去掉,剩下的字符串作为新的匹配字段,进行再次匹配,重复以上过程,直到切分出所有词为止。

 

反向最大匹配算法


该算法是正向的逆向算法,区别是窗口是从后向左扫描,若匹配不成功,则去掉第一个字符,重复上述的匹配步骤。

双向最大匹配算法


双向最大匹配法是将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,从而决定正确的分词方法。定义的匹配规则如下:

  • 如果正反向匹配算法得到的结果相同,我们则认为分词正确,返回任意一个结果即可。
  • 如果正反向匹配算法得到的结果不同,则考虑单字词、非字典词、总词数数量的数量,三者的数量越少,认为分词的效果越好。我们设定一个惩罚分数(score_fmm / score_bmm = 0),例如:正向匹配中单字词数量多于反向匹配,则正向匹配的分值score_fmm += 1。其他两个条件相同。可以根据实际的分词效果调整惩罚分数的大小,但由于没有正确分词的数据,因此惩罚分数都设为1。最后比较惩罚分数,返回较小的匹配结果。
     

分词算法python 实现

word_dict = {'我', '要', '爱', '携程', '携程旅游网', '旅行网', '旅行'}


def fmm(text, word_dict):
    """
    正向最大匹配算法
    :param text: 输入待分词文本
    :param word_dict: 词典
    :return:分词结果
    """
    result = []
    len_text = len(text)
    window_size = max({len(word) for word in word_dict})
    start_index = 0
    while start_index < len_text:
        is_match = False
        for i in range(window_size, 0, -1):
            end_index = start_index + i
            sub_text = text[start_index: end_index]
            if sub_text in word_dict:
                result.append(sub_text)
                start_index = end_index
                is_match = True
                break
        if not is_match:
            result.append(text[start_index])
            start_index += 1
    return result


def bmm(text, word_dict):
    """
    反向最大匹配算法
    :param text:  输入的待分词文本
    :param word_dict: 词典
    :return: 分词结果
    """
    result = []
    len_text = len(text)
    window_size = max({len(word) for word in word_dict})
    end_index = len_text
    while end_index > 0:
        is_match = False
        for i in range(window_size, 0, -1):
            start_index = end_index - i
            sub_text = text[start_index: end_index]
            if sub_text in word_dict:
                result.append(sub_text)
                end_index = start_index
                is_match = True
                break
        if not is_match:
            result.append(text[end_index - 1])
            end_index -= 1
    result.reverse()
    return result


def bi_mm(text, word_dict):
    """
    双向最大匹配算法
    :param text: 待分词文本
    :param word_dict: 词典
    :return: 分词结果
    """
    forward = fmm(text, word_dict)
    backward = bmm(text, word_dict)
    if forward == backward:
        return forward
    else:
        score_fmm = 0
        score_bmm = 0

        # 总词数
        tot_fmm = len(forward)
        tot_bmm = len(backward)
        # 单字词个数
        single_word_fmm = len([word for word in forward if len(word) == 1])
        single_word_bmm = len([word for word in backward if len(word) == 1])
        # 不在词典的词个数
        oov_fmm = len([word for word in forward if word not in word_dict])
        oov_bmm = len([word for word in forward if word not in word_dict])

        if tot_bmm < tot_fmm:
            score_bmm += 1
        elif tot_fmm < tot_bmm:
            score_fmm += 1

        if single_word_bmm < single_word_fmm:
            score_bmm += 1
        elif single_word_fmm < single_word_bmm:
            score_fmm += 1

        if oov_bmm < oov_fmm:
            score_bmm += 1
        elif oov_fmm < oov_bmm:
            score_fmm += 1

        if score_bmm < score_fmm:
            return backward
        else:
            return forward


if __name__ == '__main__':
    print(fmm('我爱fdsf携程旅游网', word_dict))
    print(bmm('我爱速度携程旅游网', word_dict))
    print(bi_mm('我爱速度携程旅游网', word_dict))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值