1. 程式人生 > >HMM學習筆記(三):動態規劃與維特比演算法

HMM學習筆記(三):動態規劃與維特比演算法

學習隱馬爾可夫模型(HMM),主要就是學習三個問題:概率計算問題,學習問題和預測問題。在前面講了概率計算問題:前後向演算法推導Baum-Welch演算法。最後在這裡講最後的一個問題,預測問題。

預測問題:給定HMM引數 λ = { π , A

, B } \lambda=\{\pi,A,B\} ,觀測序列 O = { o
1 , o 2 , . . . , o
T
} O=\{o_1,o_2,...,o_T\}
,求條件概率 P ( I O , λ ) P(I|O,\lambda) ,即給定觀測序列求最優可能的狀態序列。

記: Q = { q 1 , q 2 , . . . , q N } Q=\{q_1,q_2,...,q_N\} 表示所有可能的狀態集合(後面可能也會直接用數字來表示), V = { v 1 , v 2 , . . . , v M } V=\{v_1,v_2,...,v_M\} 表示所有可能的觀測集合。

I = { i 1 , i 2 , . . . , i T } I=\{i_1,i_2,...,i_T\} 表示狀態序列, O = { o 1 , o 2 , . . . , o N } O=\{o_1,o_2,...,o_N\} 為對應的觀測序列。

下面給出HMM預測問題的兩種演算法:近似演算法和維特比演算法

近似演算法

近似演算法的思想是,在每個時刻 t t 選擇最有可能的狀態 i t i^*_{t} t t 從1開始直到 T T ,所以可以求出狀態序列 I = ( i 1 , i 2 , . . . , i T ) I^*=(i^*_{1},i^*_{2},...,i^*_{T}) ,將 I I^* 作為預測結果。

γ t ( i ) = P ( i t = q i O , λ ) \gamma_t(i)=P(i_t=q_i|O,\lambda) ,即已知模型 λ \lambda ,給定觀測序列條件下,在 t t 時刻狀態為 q i q_i 的概率,根據前後向演算法得出的結論1、2中有:

γ t ( i ) = α t ( i ) β t ( i ) i = 1 N α t ( i ) β t ( i ) \gamma_t(i)=\frac{\alpha_t(i)\beta_t(i)}{\sum\limits_{i=1}^{N}\alpha_t(i)\beta_t(i)}

那麼在每一時刻 t t 最有可能的狀態 i t i^*_t 為:

i t = arg max i γ t ( i ) i^*_t=\arg\max\limits_{i}\gamma_t(i)

從而得到最有可能的狀態序列 I = ( i 1 , i 2 , . . . , i T ) I^*=(i^*_{1},i^*_{2},...,i^*_{T})
該演算法簡單,但是不能保證整體是最有可能的預測狀態序列。

維特比演算法

維特比演算法實際上是用動態規劃(dp)來求解HMM預測問題。

關於動態規劃,也就是將大問題分解分眾多小問題,通過小問題的解來得到大問題的解。對各個小問題進行求解後,會將結果填入表中,下次要用的時候就不用再去計算而是直接拿來用了,這樣能有效避免重複計算問題(以空間換時間),基本上都會涉及到遞推。具體的可以去leetcode上刷兩題感受一下,下面寫個常見機器人走格子的動態規劃問題。

在這裡插入圖片描述

首先定義一個二維的表 int[][] dp,其中dp[i][j]表示從初始位置走到 ( i , j ) (i,j) 位置有多少種走法。現在我們需要得到的是 dp[m-1][n-1],即從初始位置走到終點有多少種走法。初始有dp[0][0]=1,那麼遞推公式是怎樣的呢?考慮dp[i][j],由於到 ( i , j ) (i,j) 位置只能從該位置的左邊或者上邊走過來,左邊走過來的方法數為dp[i][j-1],上邊走過來的方法數為dp[i-1][j],兩者之和就是走到該位置的方法數。根據dp[i][j-1],dp[i-1][j],需要初始化表的第一行和第一列。

class Solution {
    //dp[i][j]表示從左上角走到i,j位置的路徑數 dp[i][j] = dp[i-1][j]+dp[i][j-1]
    //因為(i,j)位置只能由它上面走過來和左邊走過來
    public int uniquePaths(int m, int n) {
		int[][] dp = new int[m][n];
		for(int i = 0; i < m; i ++){
			dp[i][0] = 1;
		}
		for(int j = 1; j < n; j ++){
			dp[0][j] = 1;
		}
		for(int i = 1; i < m; i ++){
			for(int j = 1; j < n; j ++){
				dp[i][j] = dp[i-1][j] + dp[i][j-1];
			}
		}
		return dp[m-1][n-1];
    }
}

再來看維特比演算法

定義變數 δ t ( i ) \delta_t(i) :表示在 t t 時刻,狀態為 i i 的所有路徑中,概率的最大值。

δ t ( i ) = max i 1 , i 2 , . . . , i t 1 P ( i t = i , i t 1