机器学习-隐马尔科夫python实现及数学原理讲解

1. 隐马尔科夫

  隐马尔可夫模型(hidden Markov model,HMM)是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程。隐马尔可夫模型是一个生成模型,表示状态序列和观测序列的联合分布,但是状态序列是隐藏的,不可观测的.

2. 直观分析

在这里插入图片描述
  以婴儿的行为来分析隐马尔可夫模型。我们能观测到的婴儿的行为是“哭”、“没精神”和“找妈妈”,这是我们的观测序列。但是婴儿这一系列的行为其隐含的状态我们不知道。婴儿哭可能是饿了,没有精神,则可能是困了。我们可以看出,观测序列与隐含序列是概率相关的。这就是一个隐马尔可夫模型。
  隐马尔可夫模型涉及三个问题:

  • 概率计算问题:即已经模型参数,且知道观测序列,如婴儿“哭”→“找妈妈”→“没精神”,计算这些行为产生的概率。

  • 解码问题:即已经模型参数,且知道观测序列,如婴儿“哭”→“找妈妈”→“没精神”,计算婴儿最可能处于的状态。

  • 参数评估问题:通过婴儿“哭”、“找妈妈”,“没精神”这一系列的行为,来确定婴儿的状态转移概率。通过调整模型参数,是的该参数模型下,观测序列概率最大。

3. 数学原理

  数隐马尔可夫模型由初始概率分布、状态转移概率分布以及观测概率分布确定。隐马尔可夫模型的形式定义如下:
  设 Q Q Q是所有可能的状态的集合, V V V是所有可能的观测的集合。
Q = { q 1 , q 2 , ⋯   , q N } , V = { v 1 , v 2 , ⋯   , v M } Q=\left\{q_{1}, q_{2}, \cdots, q_{N}\right\}, \quad V=\left\{v_{1}, v_{2}, \cdots, v_{M}\right\} Q={q1,q2,,qN},V={v1,v2,,vM}
其中, N N N是可能的状态数, M M M是可能的观测数。
I = ( i 1 , i 2 , ⋯ i T ) , O = ( o 1 , o 2 , ⋯   , o T ) I=\left(i_{1}, i_{2}, \cdots i_{T}\right), \quad O=\left(o_{1}, o_{2}, \cdots, o_{T}\right) I=(i1,i2,iT),O=(o1,o2,,oT)
隐马尔可夫模型做了如下两个假设:
1)其次马尔科夫链假设。即任意时刻的隐藏状态只依赖于它前一个隐藏状态。如果在时刻 t t t的隐藏状态是 i t = q i i_{t}=q_{i} it=qi,在时刻 t + 1 t+1 t+1的隐藏状态是 i t + 1 = q j i_{t+1}=q_{j} it+1=qj,则从时刻 t t t到时刻 t + 1 t+1 t+1的HMM状态转移概率 a i j a_{ij} aij可以表示为:
a i j = P ( i t + 1 = q j ∣ i t = q i ) a_{i j}=P\left(i_{t+1}=q_{j} \mid i_{t}=q_{i}\right) aij=P(it+1=qjit=qi)
a i j a_{ij} aij组成马尔科夫链的状态转移矩阵 A A A
A = [ a i j ] N × N A=\left[a_{ij}\right]_{N \times N} A=[aij]N×N
2)观测独立性假设。即任意时刻的观察状态只仅仅依赖于当前时刻的隐藏状态,这也是一个为了简化模型的假设。如果在时刻 t t t的隐藏状态是 i t = q i i_{t}=q_{i} it=qi,而对应的观察状态为 o t = v k o_{t}=v_{k} ot=vk,则该时刻观察状态 v k v_{k} vk在隐藏状态 q i q_{i} qi下生成的概率为 b j ( k ) b_{j}(k) bj(k),满足:
b j ( k ) = P ( o t = v k ∣ i t = q j ) b_{j}(k)=P\left(o_{t}=v_{k} \mid i_{t}=q_{j}\right) bj(k)=P(ot=vkit=qj)
这样可以 b j ( k ) b_{j}(k) bj(k)组成观测状态生成的概率矩阵 B B B:
B = [ b j ( k ) ] N × M B=\left[b_{j}(k)\right]_{N \times M} B=[bj(k)]N×M
除此之外,我们需要一组在时刻t=1的隐藏状态概率分布 Π \Pi Π:
Π = [ π ( i ) ] N , 其中  π ( i ) = P ( i 1 = q i ) \Pi=[\pi(i)]_{N} \text {, 其中 } \pi(i)=P\left(i_{1}=q_{i}\right) Π=[π(i)]N其中 π(i)=P(i1=qi)
一个HMM模型,可以由隐藏状态初始概率分布 Π \Pi Π,状态转移概率矩阵 A A A和观测状态概率矩阵 A A A决定。 Π \Pi Π A A A决定状态序列, B B B决定观测序列。因此,HMM模型可以由一个三元组 λ \lambda λ表示如下:
λ = ( A , B , Π ) \lambda=(A, B, \Pi) λ=(A,B,Π)
用前向算法求HMM观测序列的概率:
输入: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|λ) P(Oλ)
1)计算时刻1的各个隐藏状态前向概率:
α 1 ( i ) = π i b i ( o 1 ) , i = 1 , 2 , ⋯   , N \alpha_{1}(i)=\pi_{i} b_{i}\left(o_{1}\right), \quad i=1,2, \cdots, N α1(i)=πibi(o1),i=1,2,,N
2)递推时刻2,3,…T时刻的前向概率:
α t + 1 ( i ) = [ ∑ j = 1 N α t ( j ) a j i ] b i ( o t + 1 ) , i = 1 , 2 , ⋯ N \alpha_{t+1}(i)=\left[\sum_{j=1}^{N} \alpha_{t}(j) a_{j i}\right] b_{i}\left(o_{t+1}\right), \quad i=1,2, \cdots N αt+1(i)=[j=1Nαt(j)aji]bi(ot+1),i=1,2,N
3)计算最终结果:
P ( o ∣ λ ) = ∑ i = 1 N α T ( i ) P(o \mid \lambda)=\sum_{i=1}^{N} \alpha_{T}(i) P(oλ)=i=1NαT(i)

4. 实现

  调用hmm函数来构造隐马尔可夫模型,通过decode函数进行解码。以课本《统计学习方法》例10.3上维特比解码的案例来进行分析。由运行结果可以看出,在已知观测序列O={红,白,红},即球来自于哪个盒子{box1,box2,box3}下的最大概率。其最大概率为{box3,box3,box3},即三次都是从第三个盒子中取出来的。其概率为对数概率,经计算与课本例10.3最优路径概率概率0.0147相等。
在这里插入图片描述

4.1 代码

# 导入基本库
import numpy as np
from hmmlearn import hmm

# 创建状态序列
states = ["box 1", "box 2", "box3"]
n_states = len(states)

# 创建可观测序列
observations = ["red", "white"]
n_observations = len(observations)

# 创建初始状态概率
start_probability = np.array([0.2, 0.4, 0.4])

# 创建状态转移概率
transition_probability = np.array([
  [0.5, 0.2, 0.3],
  [0.3, 0.5, 0.2],
  [0.2, 0.3, 0.5]
])

# 创建观测概率
emission_probability = np.array([
  [0.5, 0.5],
  [0.4, 0.6],
  [0.7, 0.3]
])

# 创建离散式隐马尔可夫模型
model = hmm.MultinomialHMM(n_components=n_states)

# 赋值
model.startprob_=start_probability
model.transmat_=transition_probability
model.emissionprob_=emission_probability
seen = np.array([[0,1,0]]).T# 转置

# 使用维特比的方式进行解码
logprob, box = model.decode(seen, algorithm="viterbi")

# 打印
print("The ball picked:", ", ".join(map(lambda x: observations[x], seen.T[0])))
print("The hidden box", ", ".join(map(lambda x: states[x], box)))
print(logprob)
  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值