游乐游手机版
首页/AI热点日报/热点详情

基于HMM的中文词性标注统计机器学习方法

类型:热点整理2026-07-09
最近在重温李航老师的《统计学习方法》,尝试将其核心理论与NLP实际场景相结合,通过具体任务来深化对公式的理解,因此形成了这个「统计学习方法 for NLP」系列。本文专门探讨隐马尔可夫模型(HMM),目标是将原理彻底讲透,并基于HMM完成一个中文词性标注的实战项目。 HMM到底是什么?从事NLP的研

最近在重温李航老师的《统计学习方法》,尝试将其核心理论与NLP实际场景相结合,通过具体任务来深化对公式的理解,因此形成了这个「统计学习方法 for NLP」系列。本文专门探讨隐马尔可夫模型(HMM),目标是将原理彻底讲透,并基于HMM完成一个中文词性标注的实战项目。

HMM到底是什么?从事NLP的研究者几乎都绕不开这个经典模型。它是一种生成式模型,通过学习隐变量与观测变量的联合概率分布来建模。模型基于两个核心假设:一是齐次马尔可夫性,即t时刻的隐变量仅依赖于t-1时刻的隐变量;二是观测独立性,即任意时刻的观测变量只取决于当前时刻的隐变量。在这两条假设下,整个模型可以表示为一个有向图,联合概率等于图上各边概率的乘积。

训练阶段,通过极大似然估计从数据中学习三个参数:初始概率向量(π)、隐变量之间的转移概率矩阵(A)、以及隐变量到观测变量的发射概率矩阵(B)。预测阶段则是在给定观测序列的条件下,找出使条件概率最大的隐变量序列。理论上需要穷举所有可能的隐变量序列,若步长为N,隐变量状态数为M,总路径数为M的N次方,呈指数级复杂度——穷举完全不现实。因此引入维特比算法进行剪枝。

维特比算法的核心思路很简单:提前终止那些不可能成为最优的路径。具体实现方式为,在每一步遍历所有M个节点时,对每个节点只保留上一步M个节点中概率最大的那条路径,其余全部裁剪。这样时间复杂度降为O(N×M²),相比指数级别已非常可接受。值得一提的是,在深度学习时代,解码过程基本不再使用维特比算法,而是采用beam search。原因在于维特比依赖齐次马尔可夫性假设——当前节点只与上一个节点有关,路径整体概率可以分解为子路径概率的乘积;而深度学习的解码不满足这一假设,需要整体考虑上下文,beam search则始终保留整体最优的K个结果。

基于HMM的词性标注

词性标注,就是给一个已经完成分词的句子中的每个词打上词性标签,例如名词、动词、形容词。这是最基础的NLP任务之一,能为信息抽取、语音识别等高级任务提供关键先验信息。在该任务中,隐变量就是词性(名词、动词等),观测变量就是中文词语,我们需要建模p(隐变量, 观测变量)的联合分布。

数据处理

这里采用的是1998年人民日报词性标注语料库(PFR),包含44个基本词性标记和19484个句子。PFR语料库严格按照人民日报日期、版序、文章顺序编排,每个词语都带有词性标记。标记集涵盖26个基本词类,同时增加了专有名词(人名nr、地名ns、机构名称nt、其他专有名词nz)等,总共40多个标记。数据可以直接从公开渠道下载使用。

模型训练

根据数据估计HMM参数:全部词性集合、全部词集合、初始概率向量、词性到词性的转移矩阵A、词性到词的发射矩阵B。直接使用频率估计概率,会出现大量零概率,因此需要做拉普拉斯平滑处理。下面是核心统计代码:

# 统计words和tags
words = set()
tags = set()
for words_with_tag in sentences:
    for word_with_tag in words_with_tag:
        word, tag = word_with_tag
        words.add(word)
        tags.add(tag)
words = list(words)
tags = list(tags)

# 统计 词性到词性转移矩阵A 词性到词转移矩阵B 初始向量pi
# 先初始化
A = {tag: {tag: 0 for tag in tags} for tag in tags}
B = {tag: {word: 0 for word in words} for tag in tags}
pi = {tag: 0 for tag in tags}

# 统计A,B
for words_with_tag in sentences:
    head_word, head_tag = words_with_tag[0]
    pi[head_tag] += 1
    B[head_tag][head_word] += 1
    for i in range(1, len(words_with_tag)):
        A[words_with_tag[i-1][1]][words_with_tag[i][1]] += 1
        B[words_with_tag[i][1]][words_with_tag[i][0]] += 1

# 拉普拉斯平滑处理并转换成概率
sum_pi_tag = sum(pi.values())
for tag in tags:
    pi[tag] = (pi[tag] + 1) / (sum_pi_tag + len(tags))
    sum_A_tag = sum(A[tag].values())
    sum_B_tag = sum(B[tag].values())
    for next_tag in tags:
        A[tag][next_tag] = (A[tag][next_tag] + 1) / (sum_A_tag + len(tags))
    for word in words:
        B[tag][word] = (B[tag][word] + 1) / (sum_B_tag + len(words))

训练完成后,可以观察词性转移矩阵的可视化结果:

模型预测

预测阶段采用维特比算法进行解码。以下是实现代码:

def decode_by_viterbi(sentence):
    words = sentence.split()
    sen_length = len(words)
    T1 = [{tag: float('-inf') for tag in tags} for i in range(sen_length)]
    T2 = [{tag: None for tag in tags} for i in range(sen_length)]
    # 先进行第一步
    for tag in tags:
        T1[0][tag] = math.log(pi[tag]) + math.log(B[tag][words[0]])
    # 继续后续解码
    for i in range(1, sen_length):
        for tag in tags:
            for pre_tag in tags:
                current_prob = T1[i-1][pre_tag] + math.log(A[pre_tag][tag]) + math.log(B[tag][words[i]])
                if current_prob > T1[i][tag]:
                    T1[i][tag] = current_prob
                    T2[i][tag] = pre_tag
    # 获取最后一步的解码结果
    last_step_result = [(tag, prob) for tag, prob in T1[sen_length-1].items()]
    last_step_result.sort(key=lambda x: -1*x[1])
    last_step_tag = last_step_result[0][0]
    # 向前解码
    step = sen_length - 1
    result = [last_step_tag]
    while step > 0:
        last_step_tag = T2[step][last_step_tag]
        result.append(last_step_tag)
        step -= 1
    result.reverse()
    return list(zip(words, result))

简单测试一下效果:

decode_by_viterbi('我 和 我 的 祖国')
[('我', 'r/代词'),
 ('和', 'c/连词'),
 ('我', 'r'/代词),
 ('的', 'u'/助词),
 ('祖国', 'n'/名词)]

decode_by_viterbi('中国 经济 迅速 发展 , 对 世界 经济 贡献 很 大')
[('中国', 'ns/地名'),
 ('经济', 'n/名词'),
 ('迅速', 'ad/形容词'),
 ('发展', 'v/动词'),
 (',', 'w/其他'),
 ('对', 'p/介词'),
 ('世界', 'n/名词'),
 ('经济', 'n/名词'),
 ('贡献', 'n/名词'),
 ('很', 'd'/副词),
 ('大', 'a'/形容词)]

可以看到结果基本正确。根据相关文献,使用HMM进行中文词性标注的准确率通常能达到85%以上。

当然,HMM的缺陷也很明显:两个强假设在实际应用中往往不成立。隐变量不仅跟前一个状态有关,还跟之前全部的隐变量和观测变量有关;同时观测变量也不只依赖于当前隐变量。这正是后来RNN等深度学习模型尝试解决的问题。

来源:https://m.elecfans.com/article/1929802.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。