用Python写一个基于统计的隐马尔可夫模型+viterbi动态规划算法 ——完成序列标注任务

序列标注是自然语言处理的基本任务,而隐马尔可夫模型前向算法是序列标注任务中的经典算法,在序列标注任务中,观测状态:词序列;隐状态:词性标注序列。

隐马尔可夫模型前向算法一般用于解决三类问题
<1>给定隐马尔可夫模型M=(A,B),计算某个观测序列O出现的概率,即计算P(O|M) (A表示转移概率,B表示发射概率)<2> 给定一个观测序列O和一个HMM模型M,寻找最好的隐序列Q以便最好的解释观测值 (解码)
<3>使用基于统计的方法,学习最佳HMM参数模型A和B.(学习)

对于第一个任务,只要学习过贝叶斯定理就知道如何计算概率值。
第二个任务的详细解析、及C++实现的源代码
今天完成第三个任务,使用传统的基于统计的方法来进行参数估计、构建模型、并根据我们自己训练的模型对于给定的任意观测序列O,输出最佳隐序列。

概念回顾: 一个隐马尔可夫模型µ(A,B,π):
µ初始概率分布 隐藏状态的初始概率分布 :一句话中第一个词是什么词性的概率 [词性]
A转移概率分布 隐藏状态之间的转移 [词性][词性]
B发射概率分布 从观测状态转移到隐状态的概率 [词性][单词]

1.使用已经标注好的人民日报语料库
显然 语料库中第一行是中文分词后的词序列 第二行是对应的词性标注
在这里插入图片描述

2.读入文件

f = open("199801_dependency_treebank_2003pos2103230114.txt","r")
txt = f.read() # 一次性读入全部
f.close()

3.使用nltk工具包创建频率分布 nltk.FreqDist()

lines = txt.split("\n") # 按行切割

row = 0 # 源文本文件从第一行开始每隔四行为词汇统计行 中文分词结果
list_vocab=[]
while row<len(lines):
    for word in lines[row].split(): #将分好的词全部加进list_vocab中
        list_vocab.append(word)
    row+=5
import nltk
fdist_vocab = nltk.FreqDist(w for w in list_vocab) #创建词汇的频率分布

row = 1 # 源文本文件从第二行开始每隔四行为词性标注统计行
list_pos=[]
while row<len(lines):
    for pos in lines
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HMM是一种常见的统计模型,用于描述随机生成的序列Viterbi算法是一种在HMM中进行解码的动态规划算法,用于寻找最可能的隐藏状态序列。下面是HMM的MATLAB实现,包括Viterbi算法。 首先,我们需要定义一个HMM模型。我们假设这个模型有3个隐藏状态和2个可见状态。我们使用矩阵A表示隐藏状态之间的转移概率,矩阵B表示每个隐藏状态生成每个可见状态的概率,向量pi表示初始隐藏状态的概率分布。 ```matlab % 定义HMM模型参数 A = [0.5 0.2 0.3; 0.3 0.5 0.2; 0.2 0.3 0.5]; B = [0.5 0.5; 0.4 0.6; 0.7 0.3]; pi = [0.2 0.4 0.4]; ``` 接下来,我们需要生成一个可见序列。我们使用HMM模型中的随机过程生成一个长度为10的可见序列。 ```matlab % 生成可见序列 T = 10; q = zeros(1, T); o = zeros(1, T); q(1) = randsrc(1, 1, [1:3; pi]); o(1) = randsrc(1, 1, [1:2; B(q(1), :)]); for t = 2:T q(t) = randsrc(1, 1, [1:3; A(q(t-1), :)]); o(t) = randsrc(1, 1, [1:2; B(q(t), :)]); end ``` 接下来,我们使用Viterbi算法解码这个可见序列,得到最可能的隐藏状态序列。我们定义一个矩阵V表示每个时间步的最大概率,以及一个矩阵path表示每个时间步的最大概率对应的前一个状态。 ```matlab % Viterbi算法解码 V = zeros(3, T); path = zeros(3, T); V(:, 1) = pi' .* B(:, o(1)); for t = 2:T for j = 1:3 [V(j, t), path(j, t)] = max(V(:, t-1) .* A(:, j)); V(j, t) = V(j, t) * B(j, o(t)); end end ``` 最后,我们找到最可能的隐藏状态序列。我们首先找到最后一个时间步的最大概率对应的隐藏状态,然后从后往前依次寻找每个时间步的最大概率对应的隐藏状态,最终得到整个隐藏状态序列。 ```matlab % 找到最可能的隐藏状态序列 [~, q(T)] = max(V(:, T)); for t = T-1:-1:1 q(t) = path(q(t+1), t+1); end ``` 完整代码如下: ```matlab % 定义HMM模型参数 A = [0.5 0.2 0.3; 0.3 0.5 0.2; 0.2 0.3 0.5]; B = [0.5 0.5; 0.4 0.6; 0.7 0.3]; pi = [0.2 0.4 0.4]; % 生成可见序列 T = 10; q = zeros(1, T); o = zeros(1, T); q(1) = randsrc(1, 1, [1:3; pi]); o(1) = randsrc(1, 1, [1:2; B(q(1), :)]); for t = 2:T q(t) = randsrc(1, 1, [1:3; A(q(t-1), :)]); o(t) = randsrc(1, 1, [1:2; B(q(t), :)]); end % Viterbi算法解码 V = zeros(3, T); path = zeros(3, T); V(:, 1) = pi' .* B(:, o(1)); for t = 2:T for j = 1:3 [V(j, t), path(j, t)] = max(V(:, t-1) .* A(:, j)); V(j, t) = V(j, t) * B(j, o(t)); end end % 找到最可能的隐藏状态序列 [~, q(T)] = max(V(:, T)); for t = T-1:-1:1 q(t) = path(q(t+1), t+1); end ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值