HMM隐马尔科夫模型(附维特比代码)

背景知识:马尔科夫模型

1 马尔科夫的局限性

在一些情况下,我们并不能直接得到观测的结果,比如在天气系统中,我们不能直接得到天气的状态,但是我们有一堆蚂蚁,可以从蚂蚁的行为状态找到天气变化的关系规律。此时我们就有两组状态:

  • 观察的状态(即蚂蚁的行为状态)
  • 隐藏的状态(天气状态)

在这种情况下,我们希望设计出一个模型,在不能直接观测到天气状态的情况下,通过观测蚂蚁的状态,预测出下一天气状态。这就是隐马尔可夫模型(hidden Markov Model)的思想。

2 隐马尔可夫模型

1 介绍

隐马尔可夫模型(Hidden Markov Models, HMM)描述由一个隐藏的马尔可夫链随机生成的不可观测的状态序列,再由各个状态生成一个观测而产生观测随机序列的过程,属于生成模型(同属于生成模型的还有朴素贝叶斯)关于生成/判别模型,点这里查看更多介绍

HMM(隐马尔可夫模型)是结构最简单的动态贝叶斯网,是一种著名的有向(无环)图模型,主要用于时序数据建模(语音识别、自然语言处理等)

在马尔可夫模型中,状态对于观察者来说是直接可见的。唯一的参数就是状态转移概率。而在隐马尔可夫模型中,状态并不是直接可见的,但受状态影响的某些变量是可见的。每一个状态在可能输出的符号上都有一概率分布,因此输出符号的序列能够透露出状态序列的一些信息,由此形成了双重随机过程:

  • 不仅仅是状态之间转移的随机
  • 还是状态到观测变量之间的随机。

其难点是从可观察的参数中确定该过程的隐含参数,然后利用这些参数来作进一步的分析。

2 概率图表示

在这里插入图片描述
该图分为上下两行,上面那行就是一个隐含的马尔科夫转移过程,称作隐藏状态(如词性、天气);下面这一行则是可以观察到的输出值,称为观察状态(词、蚂蚁行为情况)。

3 两个假设

1、齐次马尔可夫假设
隐藏的马尔可夫链在任意时刻t的状态只和上一时刻的状态有关,与其他状态和观测无关,也与时刻t无关。
2、观测独立性假设
任意时刻的观测只和当前时刻的状态有关

4 举例

有三个不同的骰子,对应的面数和数值如下图:
在这里插入图片描述
接下来随机掷骰子,从三个骰子随机取出一个并掷骰,记录正面数值,10次之后,可能得到一个这样的序列(1 6 3 5 2 7 3 5 2 4),这个序列就是可观测序列,而相对的隐含的状态链就是选取骰子的顺序,是由D6,D4,D8的组合。

由于是随机选取,所以 D i 到 D j D_i到D_j DiDj的概率都是1/3,当然如果加入一定的规则,这个概率也是可以改变的。

同样的,我们知道各个状态到观测变量之间的概率,例如D6到1,2,3,4,5,6观测的概率都是1/6。同样也可以对这个概率进行定义。

这样一来,我们就得到了:
初始概率分布 π = ( 1 / 8 , 1 / 8 , . . . , 1 / 8 ) \pi=(1/8,1/8,...,1/8) π=(1/8,1/8,...,1/8)
状态转移概率分布: A = [ 1 / 3 1 / 3 1 / 3 1 / 3 1 / 3 1 / 3 1 / 3 1 / 3 1 / 3 ] A = \begin{bmatrix} 1/3 & 1/3 & 1/3 \\ 1/3 & 1/3 & 1/3 \\ 1/3 & 1/3 & 1/3 \end{bmatrix} A=1/31/31/31/31/31/31/31/31/3
概念转移概率分布: B = [ 1 / 6 1 / 6 1 / 6 1 / 6 1 / 6 1 / 6 0 0 1 / 4 1 / 4 1 / 4 1 / 4 0 0 0 0 1 / 8 1 / 8 1 / 8 1 / 8 1 / 8 1 / 8 1 / 8 1 / 8 ] B = \begin{bmatrix} 1/6&1/6 &1/6&1/6&1/6&1/6&0&0 \\ 1/4&1/4 &1/4&1/4&0&0&0&0 \\ 1/8&1/8 &1/8&1/8&1/8&1/8&1/8&1/8 \end{bmatrix} B=1/61/41/81/61/41/81/61/41/81/61/41/81/601/81/601/8001/8001/8

以上就是一个简单的隐马尔可夫模型 λ = ( A , B , π ) \lambda=(A,B,\pi) λ=(A,B,π)

5 观测序列的生成

输入:一个HMM : λ = ( A , B , π ) \lambda=(A,B,\pi) λ=(A,B,π)
输出:观测序列 O = ( o 1 , o 2 , . . . , o T ) O=(o_1,o_2,...,o_T) O=(o1,o2,...,oT)

(1)按照初始分布 π , 产 生 i 1 , t = 1 \pi,产生i_1,t=1 πi1t=1
(2)按照状态 i t i_t it的观测概率分布 b i t ( k ) 生 成 o t b_{i_t}(k)生成o_t bit(k)ot
(3)按照状态 i t i_t it的状态转移概率生成状态 i t + 1 i_{t+1} it+1
(4)令t = t+1,当t<T时,返回step2,否则,终止。

3 HMM的三个基本问题

1 概率计算问题

已知:

  • HMM模型 λ = ( A , B , π ) \lambda=(A,B,\pi) λ=(A,B,π)
  • 观测序列 O = ( o 1 , o 2 , . . . , o T ) O=(o_1,o_2,...,o_T) O=(o1,o2,...,oT)

计算:

  • 观测序列出现的概率,即: P ( O ∣ λ ) P(O|\lambda) P(Oλ)

这个问题的意义更多在于验证我们的模型是否正确,通常使用前向算法和后向算法。

前向算法

定义前向概率:给定HMM模型 λ \lambda λ,定义到时刻t的部分观测序列为 o 1 , o 2 , . . , o t o_1,o_2,..,o_t o1,o2,..,ot,且状态为 q i q_i qi的概率为前向概率,记作:
α t ( i ) = P ( o 1 , o 2 , . . , o t , i t = q i ∣ λ ) \alpha_t(i)=P(o_1,o_2,..,o_t,i_t=q_i|\lambda) αt(i)=P(o1,o2,..,ot,it=qiλ)
通过递推即可以得到观测序列 P ( O ∣ λ ) P(O|\lambda) P(Oλ)


算法:
Step1:初值:
α 1 ( i ) = π i b i ( o 1 ) \alpha_1(i)=\pi_ib_i(o_1) α1(i)=πibi(o1)
Step2:递推,对于t=1,2,…,T
α t + 1 ( i ) = [ ∑ α t ( j ) a j i ] b i ( o t + 1 ) , i = 1 , 2 , 3... N \alpha_{t+1}(i)=[\sum\alpha_t(j)a_{ji}]b_i(o_{t+1}),i = 1,2,3...N αt+1(i)=[αt(j)aji]bi(ot+1),i=1,2,3...N

Step3:终止
P ( O ∣ λ ) = ∑ α T ( i ) P(O|\lambda) = \sum\alpha_T(i) P(Oλ)=αT(i)

后向算法

定义后概率:给定HMM模型 λ \lambda λ,定义t到时刻T的部分观测序列为 o t + 1 , o t + 2 , . . , o T o_{t+1},o_{t+2},..,o_T ot+1,ot+2,..,oT,且状态为 q i q_i qi的概率为前向概率,记作:
β t ( i ) = P ( o t + 1 , o t + 2 , . . , o T ∣ i t = q i , λ ) \beta_t(i)=P(o_{t+1},o_{t+2},..,o_T|i_t=q_i,\lambda) βt(i)=P(ot+1,ot+2,..,oTit=qi,λ)
通过递推即可以得到观测序列 P ( O ∣ λ ) P(O|\lambda) P(Oλ)


后向计算算法

在这里插入图片描述

2 学习问题

使用极大似然方法进行参数估计,这是最常见的问题也是很重要的问题。
已知:

  • 观测序列 O = ( o 1 , o 2 , . . . , o T ) O=(o_1,o_2,...,o_T) O=(o1,o2,...,oT)

估计:

  • λ = ( A , B , π ) \lambda=(A,B,\pi) λ=(A,B,π)参数

监督学习算法

假设给定了S个长度相同的观测序列和对应的状态序列: ( O 1 , I 1 ) , ( O 2 , I 2 ) , . . . , ( O S , I S ) {(O_1,I_1),(O_2,I_2),...,(O_S,I_S)} (O1,I1),(O2,I2),...,(OS,IS),可以使用伯努利大数定律来进行参数估计下,即频数等价于概率。

伯努利大数定理:设μ是n次试验中A发生的次数,一次试验中A发生的概率为 p ,则对任意正数 ε \varepsilon ε有:
在这里插入图片描述

1)状态转移概率估计:根据频数统计概率
α i j = A i j / ∑ j = 1 N A i j \alpha_{ij}=A_{ij}/\displaystyle\sum_{j=1}^{N}A_{ij} αij=Aij/j=1NAij

2)观测概率 b j ( k ) b_j(k) bj(k)的估计
同样根据已知数据的频数来统计.
β j ( k ) = B j k / ∑ k = 1 M B j k \beta_{j}(k)=B_{jk}/\displaystyle\sum_{k=1}^{M}B_{jk} βj(k)=Bjk/k=1MBjk
3)初始状态概率 π i \pi_i πi的估计,就是初始状态的频率。

这就直接估计出参数。

无监督学习算法(Baum-Welch算法)

当给定的个数据只有观测数据 O = ( o 1 , o 2 , . . . , o S ) O=(o_1,o_2,...,o_S) O=(o1,o2,...,oS),而没有对应的状态序列时,这也是最常见的情况,那么隐马尔可夫模型就是一个含隐变量的概率模型。
P ( O ∣ λ ) = ∑ I P ( O ∣ I , λ ) P ( I ∣ λ ) P(O|\lambda)=\displaystyle\sum_{I}P(O|I,\lambda)P(I|\lambda) P(Oλ)=IP(OI,λ)P(Iλ)

Baum-Welch也就是EM算法,可以见这篇EM算法,我写的非常好理解EM。

3 预测(解码)问题

给定观测序列,求最可能对应的状态序列
已知:

  • HMM模型 λ = ( A , B , π ) \lambda=(A,B,\pi) λ=(A,B,π)
  • 观测序列 O = ( o 1 , o 2 , . . . , o T ) O=(o_1,o_2,...,o_T) O=(o1,o2,...,oT)

计算:

  • 给定观测序列O的条件概率 P ( I ∣ O ) P(I|O) P(IO)最大的状态序列 I = ( i 1 , i 2 , . . . , i T ) I=(i_1,i_2,...,i_T) I=(i1,i2,...,iT)

我们可以计算出所有中结果的可能性,那就是N!种预测结果,所以不切实际。

近似算法

在每个时刻都计算该时刻最可能出现的状态,从而得到一个预测状态序列作为输出结果。
优点在于:计算简单
缺点:不能保证每一时刻的最优就是全局的最优。
尽管如此,近似算法仍然是有效的。

维特比算法(Viterbi)

Viterbi就是动态规划算法用在HMM问题,本质上还是Dynamic Programming。
动态规划思想:对于一条最佳路径o1-ot,其部分路径oi-ot也是从i-t之间的最优路径。否则该部分就存在最优路径的替代,产生矛盾。
算法解读见维特比算法

根据这一原理,可以快速高效的计算出最大的概率的路径,也就是待预测的状态转移序列。
在这里插入图片描述

Viterbi代码实现

Hidden_states = ('Healthy', 'Fever') # 隐状态集合
 
Observations_states = ('normal', 'cold', 'dizzy') # 观测状态集合
 
Start_probability = {'Healthy': 0.6, 'Fever': 0.4} # 表示病人第一次到访时医生认为其所处的HMM状态,他唯一知道的是病人倾向于是健康的(可以理解为这是基于一个对大众身体信息的了解得出的初始状态)
 
Hidden_transition_probability = { # 隐马尔可夫链中身体状态的状态转移概率,我们能够看到,当天健康的人,第二天有30%的概率会发烧
   'Healthy' : {'Healthy': 0.7, 'Fever': 0.3},
   'Fever' : {'Healthy': 0.4, 'Fever': 0.6},
   }
 
Hidden_observations_probability = {    # 原来叫emission_probability。这里表示病人每天的感觉的可能性。即,如果他是一个健康人,有50%的可能会感觉正常,40%觉得冷,10%觉得头晕
   'Healthy' : {'normal': 0.5, 'cold': 0.4, 'dizzy': 0.1},
   'Fever' : {'normal': 0.1, 'cold': 0.3, 'dizzy': 0.6},
   }

# Helps visualize the steps of Viterbi.
def print_dptable(V): # 打印dp矩阵
    print ("    "),
    for i in range(len(V)): 
        print("%7d" % i)
    print()

    for y in V[0].keys():
        print ("%.5s: " % y)
        for t in range(len(V)):
            print ("%.7s" % ("%f" % V[t][y]))
        print()

def viterbi(obs, states, start_p, trans_p, h2o_p): # Viterbi算法
    V = [{}]
    path = {}

    # Initialize base cases (t == 0)
    for y in states:
        V[0][y] = start_p[y] * h2o_p[y][obs[0]]
        path[y] = [y]

    # Run Viterbi for t > 0
    for t in range(1,len(obs)):
        V.append({})
        newpath = {}

        for y in states:
            (prob, state) = max([(V[t-1][y0] * trans_p[y0][y] * h2o_p[y][obs[t]], y0) for y0 in states])
            V[t][y] = prob
            newpath[y] = path[state] + [y]

        # Don't need to remember the old paths
        path = newpath

    print_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,
                   Hidden_states,
                   Start_probability,
                   Hidden_transition_probability,
                   Hidden_observations_probability)
print(example())

Reference:

1.https://blog.csdn.net/pipisorry/article/details/50722178

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Weiyaner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值