HMM模型

隱馬爾可夫模型(Hidden Markov Model,HMM)是統計模型,它用來描述一個含有隱含未知參數的馬爾可夫過程。其難點是從可觀察的參數中確定該過程的隱含參數。隱馬爾可夫模型(HMM)可以用五個元素來描述,包括2個狀態集合和3個概率矩陣:1. 隱含狀態 S、2. 可觀測狀態 O、3. 初始狀態概率矩陣 π、4. 隱含狀態轉移概率矩陣 A、5. 觀測狀態轉移概率矩陣 B 。
在這裏插入圖片描述

馬爾科夫鏈

對於一個馬爾可夫鏈來說,第n+1刻的狀態只跟第n刻的狀態有關,與第n-1,n-2,n-3,…等時刻的狀態是沒有任何關係的。

隱馬爾科夫模型

對於上圖,有兩個行數據,這兩列數據分佈的特點,第一行是x行,第二行是o行,x行的某一個狀態依賴於前一個狀態,x行的每一個都指向o行其中的一個.

對於上圖,一般把x行稱爲狀態序列,o行稱爲觀測序列,狀態序列和觀測序列是什麼?
狀態序列:隱藏的馬爾科夫鏈隨機生成的狀態序列,稱爲狀態序列。
觀測序列:每個狀態生成一個觀測,而由此產生的觀測的隨機序列,稱爲觀測序列
所以有馬爾科夫模型定義:隱馬爾可夫模型是一個關於時序的概率模型,它描述了一個由隱藏的馬爾可夫鏈生成狀態序列,再由狀態序列生成觀測序列的過程。其中,狀態之間的轉換以及觀測序列和狀態序列之間都存在一定的概率關係。

HMM 表示

設Q是所有可能的狀態的集合,V是所有可能的觀測的集合。

Q=q1,q2,…,qN,V=v1,v2,…,vM
其中,N是可能的狀態數,M是可能的觀測數。

I是長度爲T的狀態序列,O是對應的觀測序列。

I=(i1,i2,…,iT),O=(o1,o2,…,oT)
A是狀態轉移矩陣:A=[aij]N×N
i=1,2,…,N;j=1,2,…,N
其中,在時刻t,處於qi 狀態的條件下在時刻t+1轉移到狀態qj 的概率:

aij=P(it+1=qj|it=qi)
B是觀測概率矩陣:B=[bj(k)]N×M
k=1,2,…,M;j=1,2,…,N
其中,在時刻t處於狀態qj 的條件下生成觀測vk 的概率:

bj(k)=P(ot=vk|it=qj)
π是初始狀態概率向量:π=(πi)
其中,πi=P(i1=qi)
隱馬爾科夫模型由初始狀態概率向量π、狀態轉移概率矩陣A和觀測概率矩陣B決定。π和A決定狀態序列,B決定觀測序列。因此,隱馬爾科夫模型λ可以由三元符號表示,即:λ=(A,B,π)。A,B,π稱爲隱馬爾科夫模型的三要素。

兩個假設

(1):設隱馬爾科夫鏈在任意時刻t的狀態只依賴於其前一時刻的狀態,與其他時刻的狀態及觀測無關,也與時刻t無關。(齊次馬爾科夫性假設)

(2):假設任意時刻的觀測只依賴於該時刻的馬爾科夫鏈的狀態,與其他觀測和狀態無關。(觀測獨立性假設)

示例

wiki上面有一個預測病人是否感冒的例子
想象一個鄉村診所,村名的身體狀況要麼健康要麼發燒,他們只有問診所的醫生的才能知道是否發燒。醫生通過詢問村名的感覺去診斷他們是否發燒。村民自身的感覺有正常、頭暈或冷。
假設一個病人每天來到診所並告訴醫生他的感覺。假設病人的健康狀況是一個離散馬爾可夫鏈。病人的狀態有兩種:健康和發燒,但醫生不能直接觀察到,這意味着狀態對醫生是不可見的。
每天病人會告訴醫生自己有以下幾種由他的健康狀態決定的感覺的一種:正常、冷或頭暈。這些是觀察結果。 整個系統爲一個隱馬爾可夫模型(HMM)。
現狀:醫生知道村民的總體健康狀況,還知道發燒和沒發燒的病人通常會表明自己有什麼症狀。 換句話說,醫生知道隱馬爾可夫模型的參數。
根據收集到的信息,得出以下的數據。
病人的狀態,也就是Q(‘Healthy’, ‘Fever’)
病人的感覺,即觀測狀態,也就是V:(‘normal’, ‘cold’, ‘dizzy’)
π是初始狀態概率向量:{‘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},
   }

起始概率start_probability 表示病人第一次到訪時醫生認爲其所處的HMM狀態,他唯一知道的是病人傾向於是健康的。這裏用到的特定概率分佈不是均衡的,如轉移概率大約是{‘Healthy’: 0.57, ‘Fever’: 0.43}。 轉移概率transition_probability表示潛在的馬爾可夫鏈中健康狀態的變化。
在這個例子中,當天健康的病人僅有30%的機會第二天會發燒。放射概率emission_probability表示每天病人感覺的可能性。假如他是健康的,50%會感覺正常。如果他發燒了,有60%的可能感覺到頭暈。
如圖所示:
在這裏插入圖片描述

HMM的三個問題

1:評估問題
已知模型λ=(A,B,π) 和觀測序列O=o1,o2,…,oT,計算在模型λ下某種觀測序列O出現的概率P(O|λ)
也就是HMM模型參數A,B,π已知。求病人出現一系列症狀的概率?
2:學習問題
已知觀測序列O=o1,o2,…,oT,估計模型參數λ=(A,B,π),使P(O|λ)最大。即用極大似然法的方法估計參數,採用EM思想、
也就是通過病人表現的一系列的症狀,估計出現這一系列症狀的最佳模型參數。
3:預測問題(解碼問題)
已知觀測序列O=o1,o2,…,oT 和模型參數λ=(A,B,π),求給定觀測序列條件概率P(I|O)最大的狀態序列I=(i1,i2,…,iT),即給定觀測序列,求最有可能的對應的狀態序列。
也就是通過觀測V的狀態鏈,去預測這幾天病人是否有感冒等狀態。

維特比算法

病人連續三天都去看醫生,醫生髮現他這三天的感覺依次是:感覺正常,感覺冷,感覺頭暈。醫生想知道怎樣的健康狀態序列最能夠解釋這系列的觀察結果。這個時候就需要用到維特比算法來解決這個問題。
維特比算法代碼

def print_dptable(V):
    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, 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]

        # 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])

對維特比的參數解釋如下: obs 爲觀察結果序列, 例如 [‘normal’, ‘cold’, ‘dizzy’]; states 爲一組隱含狀態; start_p 爲起始狀態概率; trans_p 爲轉移概率; 而 emit_p 爲放射概率。 爲了簡化代碼,我們假設觀察序列 obs 非空且 trans_p[i][j] 和 emit_p[i][j] 對所有狀態 i,j 有定義。
給出維特比的參數

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},
   }

求解

def example():
    return viterbi(observations,
                   states,
                   start_probability,
                   transition_probability,
                   emission_probability)
print example()

總結

維特比算法揭示了通過觀察結果 [‘normal’, ‘cold’, ‘dizzy’] ,找到最有可能由狀態序列 [‘Healthy’, ‘Healthy’, ‘Fever’]產生。 換句話說,對於觀察到的活動, 病人第一天感到正常,第二天感到冷時都是健康的,而第三天發燒了。
維特比路徑本質上是穿過格式結構的最長路徑。 診所例子的格式結構如下, 黑色加粗的是維特比路徑:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章