HMM向前算法

1. HMM的第一個問題:已知一個HMM模型\lambda = (A, B, \Pi),  即狀態轉移矩陣, 發射矩陣, 初始狀態概率矩陣已知,給定一個觀察值序列O = (O_1, O_2,...O_T),  求這個觀察序列發生的概率P(O|\lambda)

2. 算法思路:實質上是動態規劃算法,關鍵是找到遞推公式

2.1 計算時刻1的各種狀態的向前概率: \alpha_1(i) = \pi_ib_i(o_1)i = 1, 2,...N

2.2 遞推2,3...T時刻的概率:\alpha_{t+1}(i) = \Big[\sum\limits_{j=1}^N\alpha_t(j)a_{ji}\Big]b_i(o_{t+1}),\; i=1,2,...N

2.3 計算最終結果:P(O|\lambda) = \sum\limits_{i=1}^N\alpha_T(i)

 

3.c++代碼:

// 已知:HMM隱含狀態數量,狀態轉換概率,狀態的發射概率,以及初始狀態概率分佈,根據指定可見狀態鏈,
// 求: 這種狀態鏈發生的概率
// 使用前向算法(forward)求解時間複雜度會降低很多
// 以下是C++版本forward算法過程
#include <iostream>
using namespace std;

void forward(double TransProbMatrix[][3], int irow, int icol,
			 double EmitProbMatrix[][2], int jrow, int jcol,
			 double PI[], int piLength,
			 int ObservedChain[], int obLength)
{
    // 構建結果矩陣, 每一列代表每一步各狀態的運算結果
	const int row = piLength;
	const int col = obLength;
	double** resultMatrix = new double*[row];
	for (int i = 0; i < row; i++)
		resultMatrix[i] = new double [col];
	for (int i = 0; i < row; i++){
		for (int j = 0; j <col; j++)
			resultMatrix[i][j] = 0;
	}

	// 第一步初始化,後面的步數根據遞推公式獲得
	for (int i = 0; i < col; i++){
		if (i == 0){
			for (int j = 0; j < row; j++){
				resultMatrix[j][0] = PI[j]*EmitProbMatrix[j][0];
			}
		}
		else{
			for (int j = 0; j < row; j++){
				for (int k = 0; k < row; k++){
				    resultMatrix[j][i] += resultMatrix[k][i-1] * TransProbMatrix[k][j] * EmitProbMatrix[j][ObservedChain[i]];
				}
			}
		}
	}
	cout<<"step matrix="<<endl;
	// 顯示結果矩陣
	double pro = 0;
	for (int i = 0; i < row; i++){
		for (int j = 0; j <col; j++){
			cout<<resultMatrix[i][j]<<" ";
			if (j == col-1)
			    pro += resultMatrix[i][j];
		}
		cout<<endl;
	}
	cout<<"pro="<<pro<<endl;
}
int main()
{
	// 狀態轉移矩陣
	double TransProbMatrix[][3] =
	{{0.5,0.2,0.3},
	{0.3,0.5,0.2},
	{0.2,0.3,0.5}};
	int tRow = sizeof(TransProbMatrix)/sizeof(*TransProbMatrix);
	int tCol = sizeof(*TransProbMatrix)/sizeof(**TransProbMatrix);
	// 發射矩陣
	double EmitProbMatrix[][2] = 
	{{0.5,0.5},
	{0.4,0.6},
	{0.7,0.3}};
	int eRow = sizeof(EmitProbMatrix)/sizeof(*EmitProbMatrix);
	int eCol = sizeof(*EmitProbMatrix)/sizeof(**EmitProbMatrix);
	// 初始狀態概率分佈
	double PI[] = {0.2, 0.4, 0.4};
	int piLen = sizeof(PI)/sizeof(*PI);
	// 觀察鏈
	int ObservedChain[] = {0, 1, 0, 1, 0, 1, 0};
	int obLen = sizeof(ObservedChain)/sizeof(*ObservedChain);
	// 傳入參數
	forward(TransProbMatrix, 3, 3, EmitProbMatrix, 3, 2, PI, 3, ObservedChain, obLen);
}

結果爲:

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