HMM:Hidden Markov Model 代码讲解
HMM:Hidden Markov Model,是用来描述隐含未知参数的统计模型,由显状态(可观测序列)、隐状态、发射概率(隐状态产生显状态的概率)、转移概率(显状态之间的转换)、初始概率(通常指隐状态)五部分构成,关于HMM的原理,这里我不便过多赘述,有原理不清的同学,建议大家参考这边博客,写得十分详细:https://www.cnblogs.com/skyme/p/4651331.html
那么给定一个显状态序列(观测状态),我们如何根据给定内容来推断隐状态序列呢?我们这里就来介绍(Viterbi)维特比算法
这里我们通过一个十分著名的例子来理解维特比算法思想,以及代码部分:
例:一个东京的朋友每天根据天气{下雨,天晴}决定当天的活动{公园散步,购物,清理房间}中的一种,我每天只能在twitter上看到她发的推“啊,我前天公园散步、昨天购物、今天清理房间了!”,那么我可以根据她发的推特推断东京这三天的天气。在这个例子里,显状态是活动,隐状态是天气。
现在我们已知:
初始概率:{'Rainy': 0.6, 'Sunny': 0.4}
转换概率:{ 'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3}, 'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},}
发射概率:{ 'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5}, 'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},}
让我们来预测东京的天气。
思路:例,第一天晴的概率P(一,晴) = P(晴) * P(散步 | 晴),即初始概率 * 发射概率。分别计算第一天晴和阴的概率来更新初始化概率。
第二天晴的概率 = P(一,晴) * P(晴->晴) * P(购物 | 晴),即初始概率 * 转换概率 * 发射概率。注意,这里的初始化:这里会在第一天的基础上计算4组,两组晴天概率,两组阴天概率,选各组的最大值作为最终结果,并更新初始化概率。
第三天依然如此,要在上一天的基础上计算四组,如果第三天是序列最后一个值,则计算4组中的唯一一个最大值作为结果,并回溯,得到隐状态预测序列,算法结束。否则重复:‘两组晴天概率,两组阴天概率,选各组的最大值作为最终结果,并更新初始化概率 ’操作。
值得注意的是,这里的回溯选择和回溯可以说是维特比算法的经典,也是维特比算法不同于前向传播的地方,大家要注意这一点。
代码:这里的代码链接:https://github.com/hankcs/Viterbi
现在我们来看代码:
#初始化条件 states = ('Rainy', 'Sunny')observations = ('walk', 'shop', 'clean')start_probability = {'Rainy': 0.6, 'Sunny': 0.4}transition_probability = {'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},}emission_probability = {'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1}, }# 打印每一次计算的保留值,对应到本题即晴天,阴天各自的最大值 def print_dptable(V):print " ",for i in range(len(V)): print "%7d" % i,printfor y in V[0].keys():print "%.5s: " % y,for t in range(len(V)):print "%.7s" % ("%f" % V[t][y]),printdef viterbi(obs, states, start_p, trans_p, emit_p):""":param obs:观测序列:param states:隐状态:param start_p:初始概率(隐状态):param trans_p:转移概率(隐状态):param emit_p: 发射概率 (隐状态表现为显状态的概率):return:"""# 路径概率表 V[时间][隐状态] = 概率V = [{}]# 一个中间变量,代表当前状态是哪个隐状态path = {}# 初始化初始状态 (t == 0),即第一天的计算在这里进行for y in states:V[0][y] = start_p[y] * emit_p[y][obs[0]]path[y] = [y]# 对第二天及以后应用维特比算法for t in range(1, len(obs)):V.append({})newpath = {}for y in states:#这里即为计算每一组中的最大值,即前一天阴天的的情况下今天是y的概率,以及前一天晴天时今天是y的概率中选择一个最大值#隐状态概率 = 前状态是y0的概率 * y0转移到y的概率 * y在t状态是为当前状态的概率(prob, state) = max([(V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states])# 记录最大概率V[t][y] = prob# 记录路径,这里为了方便回溯,记录回溯结果newpath[y] = path[state] + [y]# 记录回溯结果path = newpathprint_dptable(V)(prob, state) = max([(V[len(obs) - 1][y], y) for y in states])return (prob, path[state])def example():return viterbi(observations,states,start_probability,transition_probability,emission_probability)print example()运行结果:
0 1 2 Rainy: 0.06000 0.03840 0.01344 Sunny: 0.24000 0.04320 0.00259 (0.01344, ['Sunny', 'Rainy', 'Rainy'])通过这样一个简单的例子我们就能明白维特比算法的原理了。
总结
以上是生活随笔为你收集整理的HMM:Hidden Markov Model 代码讲解的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: RuntimeError 之 : CUD
- 下一篇: 思科模拟器,计算机网络实验三之:静态路由