隱馬爾可夫模型及Viterbi算法

隱馬爾可夫模型(HMM,hidden Markov model)是可用於標註問題的統計學模型,描述由隱藏的馬爾可夫鏈隨機生成觀測序列的過程,屬於生成模型。HMM模型主要用於語音識別,天然語言處理,生物信息,模式識別等領域。

引入

  某天,你的女神告訴你說,她放假三天,將要去上海遊玩,準備去歡樂谷、迪士尼和外灘(不必定三個都會去)。
  她呢,會選擇在這三個地方中的某幾個逗留並決定是否購物,並且天天只待在一個地方。根據你對她的瞭解,知道她去哪一個地方,僅取決於她去的上一個地方,且是否購物的機率僅取決於她去的地方。已知她去的三個地方的轉移機率表以下:算法

  歡樂谷 迪士尼 外灘
歡樂谷 0.8 0.05 0.15
迪士尼 0.2 0.6 0.3
外灘 0.2 0.3 0.5

稍微對這個表格作些說明,好比第一行,前一天去了歡樂谷後,次日還待在歡樂谷的機率爲0.8,去迪士尼的機率爲0.05,去外灘的機率爲0.15。
她在每一個地方的購物機率爲:app

地點 購物機率
歡樂谷 0.1
迪士尼 0.8
外灘 0.3

  在出發的時候,她跟你說去每一個地方的可能性相同。後來,放假回來後,你看了她的朋友圈,發現她的購物狀況以下:第一天不購物,第二三天都購物了。因而,你很好奇,她這三天都去了哪些地方。
  怎麼樣,聰明的你能求解出來嗎?atom

HMM的模型參數

  接下來,咱們將會介紹隱馬爾可夫模型(HMM)。
  隱馬爾可夫模型是關於時序的機率模型,描述由一個隱藏的馬爾可夫鏈隨機生成不可觀測的狀態隨機序列,再由各個狀態生成一個觀測而產生觀測隨機序列的過程。隱藏的馬爾可夫鏈隨機生成的狀態的序列,稱爲狀態序列;每一個狀態生成一個觀測,而由此產生的觀測的隨機序列,稱爲觀測序列。序列的每個位置又能夠看做是一個時刻。
  隱馬爾可夫模型由初始機率分佈、狀態轉移機率分佈以及觀測機率分佈肯定。隱馬爾可夫模型的形式定義以下:
  設Q是全部可能的狀態的集合,V是全部可能的觀測的集合,也就是說,Q是不可見的,而V是可見的,是咱們觀測到的可能結果。spa

其中,N是可能的狀態數,M是可能的觀測數。
  在剛纔的例子中,Q是不可見的狀態集合,應爲Q={},而V是能夠觀測的集合,應爲V={購物,不購物}。
  I是長度爲T的狀態序列,O是對應的觀測序列。
code

在剛纔的例子中,I這個序列是咱們須要求解的,即女生去了哪些地方,而O是你知道的序列,O={不購物,購物,購物}。
  A是狀態轉移機率矩陣:xml

N是在時刻t處於狀態qi的條件下在時刻t+1轉移到狀態qj的機率。在剛纔的例子中,轉移機率矩陣爲:blog

  B是觀測機率矩陣:遞歸

N是在時刻t處於狀態qj的條件下生成觀測vk的機率。在剛纔的例子中:utf-8

綜上,咱們已經講完HMM中的基本概念。同時,咱們能夠知道,隱馬爾可夫模型由初始狀態機率向量π,狀態轉移機率矩陣A和觀測機率矩陣B決定。π和A決定狀態序列,B決定觀測序列。所以,隱馬爾可夫模型λλ可用三元符號表示,即it

 

A,B,π稱爲HMM的三要素。
  固然,隱馬爾可夫模型之因此被稱爲馬爾可夫模型,是由於它使用了兩個基本的假設,其中之一爲馬爾可夫假設。它們分別是:

  1. 齊次馬爾科夫假設,即假設隱藏的馬爾可夫鏈在任意時刻t的狀態只依賴於其前一時刻的狀態,與其餘時刻的狀態及觀測無關,也與時刻t無關。

    

  1. 觀測獨立性假設,即假設任意時刻的觀測只依賴於該時刻的馬爾可夫鏈的狀態,與其餘觀測及狀態無關。

    

  在剛纔的假設中,咱們對應的兩個假設分別爲:她去哪一個地方,僅取決於她去的上一個地方;是否購物的機率僅取決於她去的地方。前一個條件爲齊次馬爾科夫假設,後一個條件爲觀測獨立性假設。
  以上,咱們就介紹了HMM的基本概念及假設。而HMM的三個基本問題以下:

  

上面的例子即爲HMM的第三個基本問題,也就是,給定觀測序列{不購物,購物,購物},結果最有可能的狀態序列,即遊玩的地方。

Viterbi算法

  求解HMM的第三個基本問題,會用到大名鼎鼎的維特比算法(Viterbi Algorithm)。
  維特比算法是一個特殊但應用最廣的動態規劃(dynamic programming)算法,利用動態規劃,能夠解決任何一個圖中的最短路徑問題,同時,它也是求解HMM描述的第三個基本問題的算法。

Python代碼實現

  下面,對於剛纔給出的例子,咱們將使用Python,來寫代碼實現Viterbi算法,同時求解剛纔的問題。

# -*- coding: utf-8 -*-
# HMM.py
# Using Vertibi algorithm
import numpy as np
def Viterbi(A, B, PI, V, Q, obs):
    N = len(Q)
    T = len(obs)
    delta = np.array([[0] * N] * T, dtype=np.float64)
    phi = np.array([[0] * N] * T, dtype=np.int64)
    # 初始化
    for i in range(N):
        delta[0, i] = PI[i]*B[i][V.index(obs[0])]
        phi[0, i] = 0
    # 遞歸計算
    for i in range(1, T):
        for j in range(N):
            tmp = [delta[i-1, k]*A[k][j] for k in range(N)]
            delta[i,j] = max(tmp) * B[j][V.index(obs[i])]
            phi[i,j] = tmp.index(max(tmp))
    # 最終的機率及節點
    P = max(delta[T-1, :])
    I = int(np.argmax(delta[T-1, :]))
    # 最優路徑path
    path = [I]
    for i in reversed(range(1, T)):
        end = path[-1]
        path.append(phi[i, end])
    hidden_states = [Q[i] for i in reversed(path)]
    return P, hidden_states

def main():
    # 狀態集合
    Q = ('歡樂谷', '迪士尼', '外灘')
    # 觀測集合
    V = ['購物', '不購物']
    # 轉移機率: Q -> Q
    A = [[0.8, 0.05, 0.15],
         [0.2, 0.6, 0.2],
         [0.2, 0.3, 0.5]
        ]
    # 發射機率, Q -> V
    B = [[0.1, 0.9],
         [0.8, 0.2],
         [0.3, 0.7]
         ]
    # 初始機率
    PI = [1/3, 1/3, 1/3]
    # 觀測序列
    obs = ['不購物', '購物', '購物']
    P, hidden_states = Viterbi(A,B,PI,V,Q,obs)
    print('最大的機率爲: %.5f.'%P)
    print('隱藏序列爲:%s.'%hidden_states)
main()

輸出結果以下:

最大的機率爲: 0.02688.
隱藏序列爲:['外灘', '迪士尼', '迪士尼'].

如今,你有很大的把握能夠肯定,你的女神去了外灘和迪士尼。

相關文章
相關標籤/搜索