隐马尔科夫模型——概率计算问题

谈到这个很经典的模型,首先普及一下基本知识:马尔科夫马尔科夫链

隐马尔科夫模型是关于时序的概率模型,描述由一个隐藏的马尔科夫链随机生成不可观测的状态随机序列,再由各个状态生成一个由观测而产生观测随机序列的过程。隐藏的马尔科夫链随机生成的状态的序列成为状态序列(state sequence),每个状态会生成一个观测,由此产生的序列成为观测序列(observation sequence)。序列的每一个位置可以看做是一个时刻。

如下图所示,q为状态序列的每个节点,o为对应的q产生的观测节点。

hmm1_1

隐马尔科夫模型有三要素:初始状态概率π,节点在初始状态下处于某个状态的概率;观测概率B,节点在状态q下生成观测o的概率;状态转移概率A,在t时刻节点从状态qt转移到t+1时刻为状态qt+1。

隐马尔科夫模型建立于两个基本假设上:

1)任意时刻状态只和前一刻状态有关,与其他状态无关

2)任意时刻的观测序列只依赖于该时刻的状态序列。

我们玩隐马尔可夫模型主要要解决隐三类问题:

  1. 概率计算问题,给定三要素和观测序列,计算观测序列出现的概率。
  2. 学习问题,已知观测序列,估计三要素参数π、B、A。
  3. 预测问题,也称作解码问题。已知模型和观测序列,求对给定的观测序列对应概率最大的状态序列。

先说第一个问题:计算观测序列的概率,有两种快速实现方法:前向传播(forward)和后向传播(backword)算法,本文先实现了前向传播算法并用《统计学习方法》第10章的例子进行了验证。输入时隐马尔科夫模型的三要素参数,和观测序列,输出的是观测序列在模型下的概率。

大致思路就是,先从观测序列的第一个节点,推出该观测节点可能对应的所有状态节点的概率。然后递推下一个节点,并将之前一个节点(只要之前的一个!!!)所出现的概率累加上去,以此类推直到最后一个节点。最后将概率累加,得出结果。具体还是看书上的公式吧,讲的很清楚。下面贴代码:

public static void main(String args[]){
	double [][]a = {{0.5,0.2,0.3},{0.3,0.5,0.2},{0.2,0.3,0.5}};
	double [][]b = {{0.5,0.5},{0.4,0.6},{0.7,0.3}};
	double []pi = {0.2,0.4,0.4};
	int []observation = {0,1,0};
	double result = forward(a,b,pi,observation);
	System.out.println(result);
}

/**
 * 
   * @Name: forward 前向传播算法 ,预测观测序列(暂不考虑隐含状态发射概率问题)
   * @Description: @param a 状态转移概率矩阵
   * @Description: @param b 观测概率矩阵
   * @Description: @param pi 初始状态概率向量
   * @Description: @param observation 观测序列
 */
public static double forward(double [][]a,double [][]b,double []pi,int []observation){
	//存储临时数据,每行为一个观察序列节点的所有可能性
	double [][] data = new double[observation.length][pi.length];
	
	for (int i = 0; i < observation.length; i++) {
		if(i == 0){
			for (int j = 0; j < pi.length; j++) {
				data[i][j] = pi[j]*b[j][observation[i]];
				System.out.println(data[i][j]);
			}
		}
		else {
			for (int j = 0; j < pi.length; j++) {
				double temp = 0;
				for (int k = 0; k < pi.length; k++) {
					temp = temp + data[i-1][k]*a[k][j];
				}
				data[i][j] = temp*b[j][observation[i]];
				System.out.println(data[i][j]);
				}
			}

		}

	double result = 0;
	for (int i = 0; i < data[data.length-1].length; i++) {
		result += data[data.length-1][i];
	}
	return result;
}

输入的接口感觉还可以优化,先跑通 后面有时间再慢慢优化了,如果有写的不对的地方欢迎指正。

——Snake

snake

作者: snake

我们需要为这个社会做一点贡献,失去了才懂得去珍惜。

《隐马尔科夫模型——概率计算问题》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注