隐马尔科夫模型

隐马尔科夫模型(hidden Markov model,HMM)是可用来解决标注问题的统计学模型。

HMM由初始状态概率分布π、状态转移矩阵A、状态观测概率矩阵B组成,称为HMM的三要素,表示为这里写图片描述。此外,定义所有可能状态的几何Q,所有可能观测的集合V,以及一个随机生成的状态序列I和对应的观测序列O。
对这些变量怎么理解呢?下面举个例子。
假设有3个盒子( 这里写图片描述),每个盒子装有红白两色的球( 这里写图片描述),各个盒子的红白球数由下表列出:
隐马尔科夫模型_第1张图片
由上表知,状态观测概率矩阵为:
隐马尔科夫模型_第2张图片
其中盒子1传到盒子2概率为1,盒子2传到盒子1和3概率分别为0.4和0.6,盒子3停留在盒子3和传到盒子2概率均为0.5。因此状态转移矩阵为:
隐马尔科夫模型_第3张图片
初始状态选择各个盒子的概率均等( 这里写图片描述,π是隐藏的,并且随时间变化),由当前盒子取出一个球并记录颜色,放回,接着由转移概率确定下一状态的盒子,取出一个球并记录颜色,以此列推。由此得到的观测序列 这里写图片描述(其中一种可观测状态)。
HMM有2个基本假设:
(1)齐次马尔科夫性假设,即任意时刻t的状态只与前一时刻 相关,与其他时刻的状态和观测无关。
(2)观测独立性假设,即任意时刻的观测只与当前时刻的状态有关,与其他时刻的状态和观测无关。
HMM有3个基本的问题:
(1)概率计算问题:计算给定模型 这里写图片描述下观测序列O出现的概率 这里写图片描述。(前向、后向算法求解,但本质都是穷举+概率运算)
(2)学习问题:给定观测序列O,求出模型这里写图片描述 极大似然估计下的参数。(Baum-Welch算法,类似于EM算法)
(3)预测问题:也称解码问题,给定模型这里写图片描述 和观测序列O,求概率 这里写图片描述最大的状态序列(近似算法和维特比算法)。
近似算法是贪婪算法,在每一时刻找寻从当前到下一状态的最大概率,这样往往得到的只是局部最优解,因此较不合理。
维特比算法是用动态规划的方法计算概率最大路径(路径即状态序列)和观测值生成概率,解法类似于最短路算法。算法步骤:
(1)初始化,确定初始观测值(t=1)由各个状态生成的概率;
(2)递推,对观测t=2,3,…T分别计算每个状态产生观测值t的概率最大路径,并记录概率最大路径的前一状态。
(3)比较,在t=T的观测值对应的概率最大路径即为观测序列参数的最优路径,确定最优路径的终点。
(4)倒推,由最优路径终点倒推得到路径上记录的各个状态。
Python实例:将上述的盒子中取球的例子用python程序实现,下表是产生的实验结果表。
隐马尔科夫模型_第4张图片
最后附上python程序:

# encoding: utf-8
import numpy as np
import pdb
def forward_viterbi(obs, states, start_p, trans_p, emit_p):
  T = {}
  for state in states:
    T[state] = (start_p[state]*emit_p[state][obs[0]], [state], start_p[state]*emit_p[state][obs[0]])
  for i in range(1, len(obs)):
    output = obs[i]
    U = {}
    for next_state in states:
       total = 0
       argmax = None
       valmax = 0
       for source_state in states:
           (prob, v_path, v_prob) = T[source_state]
           p = emit_p[source_state][output] * trans_p[source_state][next_state]
           prob *= p
           v_prob *= p
           total += prob
           if v_prob > valmax:
               argmax = v_path + [next_state]
               valmax = v_prob
       U[next_state] = (total, argmax, valmax)
    T = U
  total = 0
  argmax = None
  valmax = 0
  for state in states:
     (prob, v_path, v_prob) = T[state]
     total += prob
     if v_prob > valmax:
         argmax = v_path
         valmax = v_prob
  return total, argmax, valmax

def main():
  states_set = ('box1', 'box2', 'box3') #状态集合Q:盒子列表
  observations_set = ('red', 'white')  #观测集合V:小球颜色
  start_probability = {
    'box1': 0.33,
                       'box2': 0.33,
                       'box3': 0.33} #初始概率分布pi
  transition_probability = {
     'box1' : {
    'box1': 0, 'box2': 1, 'box3':0},
     'box2' : {
    'box1': 0.4, 'box2':0, 'box3':0.6},
     'box3' : {
    'box1': 0, 'box2': 0.5, 'box3':0.5}
     } 
  emission_probability = {
     'box1' : {
    'red': 0.5, 'white': 0.5},
     'box2' : {
    'red': 0.3, 'white': 0.7},
     'box3' : {
    'red': 0.8, 'white': 0.2}
     }   
  observations =['white', 'white', 'white']#观测集合V:小球颜色
  ret = forward_viterbi(observations,
                        states_set,
                        start_probability,
                        transition_probability,
                        emission_probability)
  print 'observations      : %r' %observations
  print 'obs_probability   : %.3f' %float(ret[0])
  print 'optimum_rounts    : %r' %ret[1]
  print 'OR_probability    : %.3f' %float(ret[2])

if __name__ == '__main__':
  main()

你可能感兴趣的:(数据分析,统计学,python,HMM)