隐马尔科夫模型和维特比算法

隐马尔可夫模型(Hidden Markov Model,HMM)是统计模型,它用来描述一个含有隐含未知参数的马尔可夫过程。其难点是从可观察的参数中确定该过程的隐含参数。然后利用这些参数来作进一步的分析,例如模式识别。

The HMM is a generative probabilistic model, in which a sequence of observable X variables is generated by a sequence of internal hidden states Z. The hidden states are not be observed directly. The transitions between hidden states are assumed to have the form of a (first-order) Markov chain. They can be specified by the start probability vector π and a transition probability matrix A. The emission probability of an observable can be any distribution with parameters B conditioned on the current hidden state. The HMM is completely determined by π, A and B.

From http://hmmlearn.readthedocs.io/en/latest/tutorial.html

举例来说,假设对于隐居室内的人,天气是隐含状态,海藻是可观察状态,海藻的状态和天气之间存在联系,通过观察海藻的状态来预测天气的状态。

如果使用HMM模型,我们需要知道天气的初始状态,天气的状态转移矩阵和海藻的状态转移矩阵。

概念

  • A - 隐含状态转移概率矩阵。
    描述了HMM模型中各个状态之间的转移概率。其中Aij = P( Sj | Si ),1≤i,j≤N,表示在 t 时刻、状态为 Si 的条件下,在 t+1 时刻状态是 Sj 的概率。

  • B - 观测状态转移概率矩阵,也称为混淆矩阵
    令N代表隐含状态数目,M代表可观测状态数目,则:Bij = P( Oi | Sj ), 1≤i≤M,1≤j≤N,表示在 t 时刻、隐含状态是 Sj 条件下,观察状态为 Oi 的概率。

  • π - 初始状态概率矩阵
    表示隐含状态在初始时刻t=1的概率矩阵,(例如t=1时,P(S1)=p1、P(S2)=P2、P(S3)=p3,则初始状态概率矩阵 π=[ p1 p2 p3 ].

对于包含M个客观察状态和N个隐含状态的HMM模型来说,用**λ={ π, A, B }**来表示HMM的参数。

HMM可以解决的问题

  • 根据可观察状态的序列找到一个最可能的隐藏状态序列

一个广泛使用的例子,就是使用HMM+Viterbi算法完成词性标注任务。

  • 已知模型参数,计算某一给定可观察状态序列的概率

  • 根据观察到的序列集来找到一个最有可能的 HMM
    Given just the observed data, estimate the model parameters.

The first and the second problem can be solved by the dynamic programming algorithms known as the Viterbi algorithm and the Forward-Backward algorithm, respectively. The last one can be solved by an iterative Expectation-Maximization (EM) algorithm, known as the Baum-Welch algorithm.

三个重要假设

这三个假设并不现实。

假设1:马尔可夫假设(状态构成一阶马尔可夫链)

假设2:不动性假设(状态与具体时间无关)

假设3:输出独立性假设(输出仅与当前状态有关)

举例说明

医生给村民看病,不能直接确定是"感冒"还是"健康",医生问诊村民有三种结果:正常,冷和发烧。

有没有病和村民的回答有关联,已知在有病的情况下,村民感觉正常,冷和发烧的概率。也知道在没病情况下对应的正常,冷和发烧的概率。

村民也告知了医生过去三天的情况是:正常,冷,发烧。

问题:过去三天,村民的健康状况?

分析

假设时间序列为t0, t1, t2. 那么有病和没病可以获得的可观察状态为:

每天可计算出六个概率,由"有病"导致的"正常"或者"无病"导致的"正常"会有两个概率,这时我们选择概率较大的作为第一天的状态。然后,计算t1。

根据马尔可夫链原则,t1只和t0的状态有关,对所有状态进行遍历,求从前一时刻的状态过渡到遍历状态,并且输出了观察状态的概率。

对每一个当前时刻的遍历状态:
p = 前一时刻某一状态的概率 X 状态转移矩阵中前一时刻某一状态的转移概率 X 发射矩阵中输出观察状态的概率

max§ = 对前一时刻各种状态按上公式求概率,然后使用最大值。在求最大值的同时也就确定了路径。

Codes: Github

# -*- coding: utf-8 -*-
# Python3
states = ('Healthy', 'Fever')
observations = ('normal', 'cold', 'dizzy')
start_probability = {'Healthy': 0.6, 'Fever': 0.4}

transition_probability = {
   'Healthy' : {'Healthy': 0.7, 'Fever': 0.3},
   'Fever' : {'Healthy': 0.4, 'Fever': 0.6},
   }

emission_probability = {
   '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):
    print("    "),
    for i in range(len(V)): print("%7d" % i,)

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

def viterbi(obs, states, start_p, trans_p, emit_p):
    V = [{}]
    path = {}

    # Initialize base cases (t == 0)
    for y in states:
        V[0][y] = start_p[y] * emit_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] * emit_p[y][obs[t]], y0) for y0 in states])
            V[t][y] = prob
            newpath[y] = path[state] + [y]

        print("t%d's path" % t, newpath)
        # 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,
                   start_probability,
                   transition_probability,
                   emission_probability)
print(example())

运行结果:

通俗理解

A序列是已知的,状态有限,比如:a1, a2, a1, a3。B序列也是状态有限,但是不知道B序列的排列。A序列及B序列内在有联系,得知在B序列状态转移会对应A序列状态转移的一个概率矩阵。维特比就是计算在这种情况下,B序列的最大可能序列。

维特比算法依赖于假设条件:A,B序列中每个值只和它前一个值相关,也就是A,B序列都是一阶马尔可夫链。从B状态观察A的状态和时间无关。

Refers

[Rabiner89] Lawrence R. Rabiner “A tutorial on hidden Markov models and selected applications in speech recognition”, Proceedings of the IEEE 77.2, pp. 257-286, 1989.

[Bilmes98] Jeff A. Bilmes, “A gentle tutorial of the EM algorithm and its application to parameter estimation for Gaussian mixture and hidden Markov models.”, 1998.

维特比算法

隐马尔可夫模型(HMM)攻略

王海良@Chatopera 聊天机器人 机器学习 智能客服
Chatopera 联合创始人 & CEO,运营聊天机器人平台 https://bot.chatopera.com,让聊天机器人上线!2015年开始探索聊天机器人的商业应用,实现基于自然语言交互的流程引擎、语音识别、自然语言理解,2018年出版《智能问答与深度学习》一书。