【NLP第二期中文分词技术:规则、统计与混合方法全解】

发布于:2025-07-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

🚀 作者 :“码上有前”
🚀 文章简介 :NLP
🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬
请添加图片描述

在这里插入图片描述

中文分词技术:规则、统计与混合方法全解

摘要:本文围绕中文分词技术展开深入剖析,详细讲解基于规则(正向/逆向/双向最大匹配法)、基于统计(n - gram模型、隐马尔可夫模型)以及混合分词(以jieba库为例)的三类方法。通过原理阐释、实例演示与代码实践,对比不同分词技术的优缺点与适用场景,帮助读者全面掌握中文分词核心技能,为自然语言处理后续任务筑牢基础。

一、引言

中文分词作为自然语言处理(NLP)基石,需将连续文本切分为词汇单元,为文本分析、信息检索等上层应用奠基。因中文无天然分词标记,需借助规则、统计及混合技术实现,以下逐层解析。

二、基于规则(词典)的分词方法

(一)核心逻辑

依赖预构建词典,按匹配规则从文本识别词汇,以“南京市长江大桥”演示三种方法。

(二)具体方法

1. 正向最大匹配法(MM)

步骤
① 设定最大词长(如5),从文本开头截取等长片段;
② 查词典,匹配则分割,失败则缩短片段长度(减1),重复匹配;
③ 遍历文本,直至全部分割。

Python示例代码

def forward_max_match(text, word_dict, max_len=5):
    result = []
    while text:
        start = 0
        end = min(max_len, len(text))
        while end > start:
            segment = text[start:end]
            if segment in word_dict:
                result.append(segment)
                text = text[end:]
                break
            end -= 1
        else:
            # 未匹配到,单字分割(可选策略)
            result.append(text[0])
            text = text[1:]
    return result

word_dict = {"南京市", "长江", "大桥"}
text = "南京市长江大桥"
print(forward_max_match(text, word_dict))  
# 输出: ['南京市', '长江', '大桥']

优缺点

  • 优点:逻辑直观,词典匹配成功时分词高效;
  • 缺点:依赖词典完备性,遇未登录词易出错;最大词长难适配所有文本,长文本易因片段截取策略产生歧义。
2. 逆向最大匹配法(RMM)

步骤
① 设定最大词长,从文本末尾截取等长片段;
② 查词典,匹配则分割,失败缩短片段长度(减1),重复匹配;
③ 遍历文本,完成分割。

Python示例代码

def reverse_max_match(text, word_dict, max_len=5):
    result = []
    while text:
        end = len(text)
        start = max(0, end - max_len)
        while start < end:
            segment = text[start:end]
            if segment in word_dict:
                result.insert(0, segment)
                text = text[:start]
                break
            start += 1
        else:
            result.insert(0, text[-1])
            text = text[:-1]
    return result

word_dict = {"南京市", "长江", "大桥"}
text = "南京市长江大桥"
print(reverse_max_match(text, word_dict))  
# 输出: ['南京市', '长江', '大桥']

优缺点

  • 优点:对部分歧义文本(如“研究生命起源”),逆向匹配结果更优;
  • 缺点:同样依赖词典,且分词效率随文本长度增加而降低,需频繁截取片段查词典。
3. 双向最大匹配法(BMM)

步骤
① 分别用正向、逆向最大匹配法分词,得到两组结果;
② 按规则选优:优先选分词数少的;若数量相同,选单字少的;若仍相同,选逆向结果(或自定义规则 )。

Python示例代码

def bidirectional_max_match(text, word_dict, max_len=5):
    forward_result = forward_max_match(text, word_dict, max_len)
    reverse_result = reverse_max_match(text, word_dict, max_len)
    # 选优规则:分词数少优先,再看单字数量
    def count_single_words(res):
        return sum(1 for w in res if len(w) == 1)
    if len(forward_result) != len(reverse_result):
        return forward_result if len(forward_result) < len(reverse_result) else reverse_result
    else:
        forward_single = count_single_words(forward_result)
        reverse_single = count_single_words(reverse_result)
        return forward_result if forward_single < reverse_single else reverse_result

word_dict = {"南京市", "长江", "大桥", "研究", "生命", "起源"}
text = "研究生命起源"
print(bidirectional_max_match(text, word_dict))  
# 正向可能 ['研究生', '命', '起源'],逆向 ['研究', '生命', '起源'],选逆向,输出: ['研究', '生命', '起源']

优缺点

  • 优点:通过双向匹配选优,降低歧义概率;
  • 缺点:需执行两次最大匹配,效率低于单一方向;规则选优可能无法覆盖所有复杂歧义场景。

三、基于统计的分词方法

(一)语言模型(n - gram模型)

基本思想:计算不同分词路径概率,选概率最大的结果,将分词转化为概率求解问题。

步骤
① 基于大规模语料,统计n - gram概率(如二元模型,统计相邻词共现概率 P ( w i ∣ w i − 1 ) P(w_i|w_{i - 1}) P(wiwi1) );
② 对文本生成所有可能分词路径,计算每条路径概率(路径概率为各词概率乘积 );
③ 选概率最大的路径作为分词结果。

Python示例(简化版,基于频次模拟概率)

from collections import defaultdict
import math

# 模拟语料统计n - gram频次
corpus = ["机器学习 是 热门 领域", "机器 学习 很 重要", "我爱 机器学习"]
word_freq = defaultdict(int)
bigram_freq = defaultdict(int)
for sentence in corpus:
    words = sentence.split()
    for word in words:
        word_freq[word] += 1
    for i in range(len(words) - 1):
        bigram_freq[(words[i], words[i + 1])] += 1

# 计算概率(简化为频次比)
def get_word_prob(word):
    return word_freq[word] / sum(word_freq.values()) if word_freq[word] else 0

def get_bigram_prob(prev, curr):
    return bigram_freq[(prev, curr)] / word_freq[prev] if word_freq[prev] and bigram_freq[(prev, curr)] else 0

# 分词路径概率计算(简化示例,仅演示逻辑)
def ngram_segment(text, possible_segments):
    best_path = None
    max_prob = -math.inf
    for seg in possible_segments:
        prob = 1
        for i in range(len(seg) - 1):
            prob *= get_bigram_prob(seg[i], seg[i + 1])
        if prob > max_prob:
            max_prob = prob
            best_path = seg
    return best_path

text = "机器学习"
possible_segments = [["机器", "学习"], ["机", "器", "学习"]]
print(ngram_segment(text, possible_segments))  
# 输出: ['机器', '学习'](假设“机器 学习”概率更高)

优缺点

  • 优点:无需依赖固定词典,能适应新词;通过概率模型挖掘语义关联;
  • 缺点:需大规模语料训练,计算成本高;分词路径爆炸(长文本可能路径极多 ),实际应用需剪枝优化。

(二)隐马尔可夫模型(HMM)

基本思想:将分词转化为字的序列标注任务,定义隐藏状态(B - 词首、M - 词中、E - 词尾、S - 单字成词 ),用维特比算法求解最优状态序列。

步骤
① 标注训练语料,统计状态转移概率(如B→M、M→E等概率 )、发射概率(字→状态的概率,如“学”作为B状态的概率 );
② 对新文本,用维特比算法计算每个位置的状态概率,找到最优状态序列;
③ 依据状态序列分割文本(B开头、E结尾为一词,S单独成词 )。

Python示例(简化版,基于简单标注训练)

import numpy as np
from collections import defaultdict

# 模拟训练语料标注(状态:B, M, E, S)
corpus = [
    ("我", "S"), ("爱", "S"), ("自", "B"), ("然", "E"), 
    ("语", "B"), ("言", "E"), ("处", "B"), ("理", "E")
]
state_trans = defaultdict(lambda: defaultdict(int))  # 状态转移计数
emission_prob = defaultdict(lambda: defaultdict(int))  # 发射概率计数
states = ["B", "M", "E", "S"]
prev_state = corpus[0][1]
for char, state in corpus[1:]:
    state_trans[prev_state][state] += 1
    emission_prob[state][char] += 1
    prev_state = state

# 转化为概率(简化为频次比)
for state in states:
    total_trans = sum(state_trans[state].values())
    for next_state in states:
        state_trans[state][next_state] /= total_trans if total_trans else 0
    total_emission = sum(emission_prob[state].values())
    for char in emission_prob[state]:
        emission_prob[state][char] /= total_emission if total_emission else 0

# 维特比算法求解最优状态序列
def viterbi(text, states, state_trans, emission_prob):
    dp = [{} for _ in range(len(text))]
    # 初始化第一个字
    for state in states:
        dp[0][state] = emission_prob[state].get(text[0], 0)
    # 递推计算
    for i in range(1, len(text)):
        for curr_state in states:
            dp[i][curr_state] = max(
                dp[i - 1][prev_state] * state_trans[prev_state].get(curr_state, 0) 
                for prev_state in states
            ) * emission_prob[curr_state].get(text[i], 0)
    # 找最优路径
    best_path = [max(dp[-1], key=dp[-1].get)]
    for i in range(len(text) - 2, -1, -1):
        best_path.insert(0, max(states, key=lambda s: dp[i][s] * state_trans[s].get(best_path[0], 0)))
    return best_path

text = "我爱自然"
states_seq = viterbi(text, states, state_trans, emission_prob)
# 依据状态序列分词
seg_result = []
word = ""
for char, state in zip(text, states_seq):
    if state in ["B", "S"]:
        if word:
            seg_result.append(word)
        word = char
    else:
        word += char
seg_result.append(word)
print(seg_result)  
# 输出: ['我', '爱', '自然'](假设状态序列匹配)

优缺点

  • 优点:能处理未登录词,通过序列标注挖掘字间关联;
  • 缺点:依赖高质量标注语料,训练成本高;状态定义和概率计算对分词效果影响大,复杂文本易出错。

四、混合分词:以jieba库为例

(一)原理

融合规则分词(词典匹配)与统计方法(HMM优化未登录词、歧义),先词典匹配,再用HMM校准。

(二)实例与代码

Python示例(jieba库使用)

import jieba

# 加载自定义词典(可选,增强规则分词)
jieba.load_userdict("custom_dict.txt")  
text = "深度学习助力自然语言处理发展"
# 分词(混合模式,默认启用)
seg_result = jieba.lcut(text)
print(seg_result)  
# 输出: ['深度学习', '助力', '自然语言处理', '发展']

内部流程简化说明

  1. 规则分词:用内置/自定义词典,匹配“深度学习”“助力”等词;
  2. 统计优化:对未匹配部分(如新词),用HMM模型标注字状态,识别“自然语言处理”等词;
  3. 融合结果:结合规则与统计结果,输出最终分词。

优缺点

  • 优点:兼顾词典匹配高效性与统计方法对新词、歧义的适应性,实际场景(如新闻、社交文本)表现好;
  • 缺点:需维护词典,HMM模型依赖训练,极端领域(如专业医学文本 )需定制化优化。

五、总结

中文分词技术中,规则分词(MM/RMM/BMM )逻辑清晰但依赖词典;统计分词(n - gram/HMM )适应新词但成本高;混合分词(jieba为代表 )融合二者优势,成为实际应用主流。开发时,需根据场景选方法:词典覆盖度高的领域(如法律文本 )用规则分词;网络动态文本用混合分词;科研探索语义建模用统计分词。掌握各方法步骤、代码与优缺点,可精准应对NLP分词需求,为上层应用筑牢基础。

(注:文中代码为简化演示,实际工程需结合大规模语料、高效概率计算优化,如用jieba等成熟库处理复杂场景 。)。

五、总结

中文分词技术从基于规则的简单匹配,到基于统计的概率求解,再到混合策略的高效应用,各有优劣。基于规则的方法简单快速,但对新词和歧义处理不足;基于统计的方法能利用语料信息,但依赖数据且计算复杂;混合分词(如jieba库)融合两者优势,在实际NLP任务中应用广泛。在实践中,需根据文本特点(如领域、新词数量 )选择合适的分词方法,或结合多种方法优化分词效果,为后续的词性标注、文本理解等任务提供准确的词语单元,推动NLP应用的深入发展。

读者可尝试构建不同领域的词典,测试jieba库在专业文本(如医疗、金融文本 )中的分词效果,对比不同分词技术在实际任务(如文本分类 )中的影响,进一步深化对中文分词技术的理解与应用。


网站公告

今日签到

点亮在社区的每一天
去签到