Ref:
文中的例子和符號基本來自Ref[1]
基本概念:
Markov chain:隨機變量組成的序列,下一個序列狀態僅和當前狀態有關,而和過去的狀態無關。好比預測明天的天氣,僅考慮今天的氣候,而不用管昨天或以前的天氣情況。
Markov chain有助于計算可觀測序列狀態的概率,但很多時候,我們還關心那些無法直接觀測到的狀態序列。好比文本序列的pos tags,我們閱讀文字,然后再判斷這個文字是動詞,名詞還是其他,這些不可直接觀測的狀態,又稱為隱藏狀態(hidden state),HMM就是來幫助處理這種情況的。
Hidden Markov Model:有兩種隨機狀態序列,一種狀態可觀測,另一種狀態不可直接觀測,這個不可觀測的序列(下文用隱藏序列)服從Markov chain,且觀測序列依賴隱藏序列,HMM希望通過這些觀測序列來學習隱藏序列。
數學表達:
Y:可觀測狀態序列,下文的O
X:隱藏狀態序列,hidden state,下文的Q
假設:Y依賴X,在每個時間t, 僅依賴 ,和
,
無關,HMM的狀態之間的時序變化如下圖:
概念
- Markov assumption
對隱藏序列(對應上圖的X),有
- Transition probability matrix
狀態轉移矩陣,
表示從隱藏狀態i轉移到隱藏狀態j的概率,
- Initial probability distribution
初始概率分布,,表示隱藏序列從哪個狀態開始;
,注意,有些狀態可能為0;
- 觀測序列T
- Emission probability
發射概率,,表示隱藏狀態為i時,對應的觀測狀態為t的概率。
HMM:
2個假設:
- Markov assumption: 隱藏狀態i只和上一個隱藏狀態i-1有關,
- 觀測狀態僅依賴于當時的隱層狀態,而和之前的觀測狀態or之前的隱層狀態無關:
HMM可以看成3個問題:
- Likelihood:已知觀測序列O,參數
,計算likelihood
;
- Decoding:已知觀測序列O,參數
,找到最佳的隱藏序列Q,用Viterbi;
- Learning:已知觀測序列O,一系列的HMM狀態,學習參數
,用EM。
案例分析:吃冰淇淋與氣溫的關系,如下圖:
1. Likelihood computation:Forward algorithm
動態規劃算法,計算觀測的概率。
即,知道了一條觀測序列,所有可能的隱藏序列,觀測和隱藏序列之間的關系(轉移概率A和發射概率B),初始隱藏序列的概率分布(π),求這個觀測序列的likelihood。
輸入:觀測序列O,模型參數
輸出:
案例分析
https://web.stanford.edu/~jurafsky/slp3/A.pdf
- 2種氣候狀態(不可觀測):HOT,COLD,對應的初始概率為0.8,0.2,即熱天的概率為0.8,氣溫變冷的概率為0.2,從HOT轉到HOT的概率為0.6,HOT轉到COLD的概率為0.4,反之0.5,COLD轉到COLD的概率為0.5;
- 觀測狀態:Jason可能吃的冰淇淋數量,O = {1,2,3}。
- 觀測序列:吃了冰淇淋數量為[3,1,3];
- 氣候序列:[hot,hot,cold];
- 冰淇淋數量O和氣溫高低的關系:
,
,
https://web.stanford.edu/~jurafsky/slp3/A.pdf
計算條件概率 or likelihood:
但是實際上,我們并不知道真正的氣候序列是怎樣的,因此還要考慮實際的氣候序列(即隱藏序列):
因此,給定一條觀測序列和一條隱藏序列的聯合概率為:
而所有可能的隱藏序列對應的所有觀測序列的總概率為:
如果有N個隱藏狀態和T個觀測序列,則可能有個可能的隱藏序列。
太大,因此無法分別計算每一個隱藏狀態(N)下的觀測(T)的likelihood。因此,使用Forward algorithm。
算法
輸入:觀測狀態序列長度為T,隱藏狀態N
設,previous forward path probability:
則,在第t個狀態下,隱藏狀態為j的所有可能路徑概率和:
步驟:
- 初始化:
, given
- 迭代:
, given
- 終止:
案例分析
https://web.stanford.edu/~jurafsky/slp3/A.pdf
如上圖,,在時間t為2時,處于狀態2,產生的觀測序列為[3,1],有兩條路徑通向這個點,分別為:
![]()
代碼
def forward(obs,states, start_p, emission_p,trans_p):
"""
obs = ('ice_3','ice_1','ice_3')
states = ('HOT','COLD')
start_p = {'HOT':0.8,'COLD':0.2}
emission_p = {'HOT':{'ice_1':0.2,'ice_2':0.4,'ice_3':0.4},
'COLD':{'ice_1':0.5,'ice_2':0.4,'ice_3':0.1}}
trans_p = {'HOT': {'HOT':0.6,'COLD':0.4},
'COLD': {'HOT':0.5,'COLD':0.5}}
"""
fwd = [{}]
for state in states:
fwd[0][state] = start_p[state] * emission_p[state][obs[0]]
for t in range(1,len(obs)):
fwd.append({})
for state in states:
fwd[t][state] = sum((fwd[t-1][s]*trans_p[s][state]*emission_p[state][obs[t]]) for s in states)
prob = sum(fwd[len(obs)-1][s] for s in states)
return prob
2. Decoding:Viterbi algorithm
給定觀測序列O,參數 ,找到最佳的隱藏狀態序列Q,也就是找到最大的likelihood。一般來說,可以通過forward algorithm來計算某個隱藏狀態序列下的觀測序列的likelihood,然后再選擇likelihood最大的那條隱藏序列。
簡而言之,就是每個時間步下,都選擇最大的likelihood。
但是,正如之前提到的,序列狀態多種多樣,因此使用Viterbi algorithm。同前向算法,它也是個動態規劃問題。
算法
輸入:觀測狀態序列長度為T,隱藏狀態N,構造一條viterbi路徑概率矩陣[N,T]
輸出:最佳路徑,路徑概率
設,上一個時間步的Viterbi路徑概率previous Viterbi path probability:
則,時間步t時,隱藏狀態為j的Viterbi值為:
步驟:
- 初始化:
對:
,
- 迭代:
對:
- 終止:
best score:
start of backtrace:
案例分析
https://web.stanford.edu/~jurafsky/slp3/A.pdf
如上圖,對觀測序列[3,1,3],可能存在的隱藏序列路徑為:
START->H->H->H, START->H->C>H, START->H->C>C, START->H->H>C
SATRT ->C->C>C, START->C->H>C, START->C->H>J, START->C->C>H
Step t=1 時,觀測狀態為3,最大概率為0.32,最可能的路徑為START->H;
Step t=2 時,觀測狀態為1,最大概率為0.064,最可能的路徑為START->H->C;
Step t=3 時,觀測狀態為3,最大概率為0.0128,最可能的路徑為START->H->C>H。
因此,viterbi的輸出為:0.0128,START->H->C>H。
同時,viterbi還可以追溯,即H->C->H->START,如圖上藍色箭頭。
代碼
def viterbi(obs, states, start_p, emission_p, trans_p):
V = [{}]
path = {}
# 建立t0時刻個狀態概率
for state in states:
V[0][state] = start_p[state] * emission_p[state][obs[0]]
path[state] = [state]
# 沿著時間1, 2..t進行計算
for t in range(1, len(obs)):
V.append({})
newpath = {}
# 根據t-1時刻狀態概率,觀測概率矩陣和轉移概率矩陣計算t時刻最大概率轉態 記錄路徑
for state in states:
# 看前一個狀態中, 那個狀態轉移到當前狀態并且當前狀態噴射出當前觀測值的概率大, 誰大誰就做前一個狀態
(prob, next_state) = max([(V[t-1][s] * trans_p[s][state] * emission_p[state][obs[t]], s) for s in states])
V[t][state] = prob
newpath[state] = path[next_state] + [state] # state狀態概率最大: 前一個狀態 和 當前能噴射出最大概率的狀態
# print(V)
# print(newpath)
path = newpath
# 最后結果:
# (0.0128, ['HOT', 'COLD', 'HOT'])
(prob, next_state) = max([(V[len(obs) - 1][s], s) for s in states])
return (prob, path[next_state])
3. Learning:EM algorithm
已知觀測序列集O,一系列的HMM狀態,學習參數A,B。
注意,這里的觀測序列是無標簽的,也就是說,我們知道有哪些觀測值,但是觀測值的排列未知。同樣的,隱藏狀態已知,分布未知。
因此,對于前文提到的案例,我們的觀測序列,即吃的冰淇淋數量可能為:,以及知道存在的隱藏狀態為{HOT,COLD}。但不知道狀態轉移概率A和發射概率B。
EM(expectation-Maximization)algorithm:學習HMM的參數A和B。
EM是一種迭代算法,計算初始概率估計,然后使用這個估計去計算更好的估計,然后繼續根據這個估計再計算更好的估計。
案例分析
假如我們已經知道某幾天的氣溫以及冰淇淋的數量了,也就是說,已知:
ice cream count: temperature:
- 3->hot, 3->hot, 2->cold
- 1->cold, 1->cold, 2->cold
- 1->cold, 2->hot, 3->hot
則,初步判斷氣溫冷熱的初始化概率分布為:
然后,計算狀態轉移矩陣A:
發射概率B:
如果我們并不清楚冷熱氣溫背后的冰淇淋數量呢?
Forward-backward or Baum-Welch,EM中的一種特例算法,可以不斷迭代來計算冰淇淋的數量。
Baum-Welch 算法
設,時間t狀態為i時,backward probability:
則,
步驟:
- 初始化:
,
- 迭代:對
,
- 終止:
數學推理
估計轉移概率
(從狀態i轉移到狀態j的期望次數)/( 從狀態i轉移出去的期望次數)
其中,分子可用聯合概率表示:
因為:且
所以:
估計發射概率
(隱藏狀態為j時觀測為k的期望次數)/(隱藏狀態為j的期望次數)
首先,要知道在時間步t時,狀態為j的概率:
因此:
其中:
:對所有的時間步t,觀測到的狀態為k的總和。
EM算法
已經知道轉移概率和發射概率的估計方式,通過EM算法來求解HMM的A和B吧。
輸入:觀測狀態,序列長度為T,隱藏狀態集Q
輸出:HMM的
步驟:
初始化:
-
迭代直至收斂
E-step:根據,計算期望
M-step:根據期望,進行最大值估計,重新估計參數
返回估計的參數。
EM算法的初始化很重要,設置的不好,收斂不好。一般在實際應用時候,會根據經驗,手動初始化。
補充
知識點
- HMM的參數:初始概率
,轉移概率矩陣A,發射概率B
- 如果參數已知,還知道觀測序列,隱藏序列:
求某個時間步下觀測序列的likelihood,用forward算法;
求某個時間步下觀測序列對應的最可能的隱藏序列,用Viterbi算法; - 如果參數未知,就EM走起。
Viterbi 算法和Foward 算法異同:
- Viterbi計算的最可能的路徑,求的是max,輸出最可能的路徑和得分;而Foward計算的likelihood,求的是sum;
- Viterbi還多了個backpointers(Viterbi模塊圖示的藍色箭頭)。