您的位置:首页 > 其它

隐马尔可夫模型(HMM)

2016-01-06 20:08 351 查看
隐马尔可夫模型是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的转态随机序列,再由各个转态生成一个观测而产生观测随机序列的过程。隐藏的马尔可夫链随机生成的状态的序列,称为状态序列;每个状态生成一个观测,而由此产生的观测的随机序列,称为观测序列,序列的每一个位置又可以看作一个时刻。

隐马尔可夫模型由初始概率分布,状态转移概率分布以及观测概率分布确定。

HMM=(A,B,pai)

状态转移概率矩阵A和初始状态概率向量pai确定了隐藏的马尔可夫链,生成不可观测的状态序列。观测概率矩阵B确定了如何从状态生成观测,与状态序列综合确定了如何产生观测序列。

隐马尔可夫模型做了两个基本假设:

(1)齐次马尔可夫性假设,即假设隐藏的马尔可夫链在任意时刻t的状态只依赖于前一时刻状态,与其他时刻的状态及观测无关,也与时刻t无关。

(2)观测独立性假设,即假设任意时刻的观测只依赖于该时刻的马尔可夫链的转态,与其他观测及状态无关。

隐藏马尔可夫模型可以用于标注,这时状态对应着标记,标注问题是给定观测的序列预测其对应的标记序列。可以假设标注问题的数据是由隐马尔可夫模型生成的。这样我们就可以利用隐马尔可夫模型的学习与预测算法进行标注。

隐马尔可夫模型的三个基本问题:

1.概率计算问题。给定模型M=(A,B,pai)和观测序列O=(o1,o2,..on),计算在模型下观测序列O出现的概率

P(O|M)

2.学习问题。已知观测序列O=(o1,o2,..on),估计模型M=(A,B,pai)参数,使得在该模型下观测序列P(O|M)最大。即用极大似然估计的方法估计参数

3.预测问题,也成为解码(decoding)。已知模型M=(A,B,pai)和观测序列O=(o1,o2,..on),求对给定观测序列条件概率P(I|O)最大的状态序列I=(i1,i2,..in).即给定观测序列,求最有可能的对应的状态序列。

概率计算问题:

前向算法:给定隐马尔可夫模型模型M,定义到时刻t部分观测序列为o1,o2,...,ot且状态为qi的概率为前向概率,记做:at(i) = P(o1,o2,...,ot,it=qi|M)

可以递推地求得前向概率at(i)以及观测序列P(O|M)。

后向算法:

后向概率:给定隐马尔可夫模型,定义在时刻t状态为qi的条件下,从t+1到T的部分观测序列为ot+1,ot+2,..oT的概率记做后向概率。

学习算法:

隐马尔可夫模型的学习,根据训练数据是包括观测序列和对应的状态序列还是只有观测序列,可以分别由监督学习与非监督学习实现。

1.监督学习方法

假设已给训练数据包含S个长度相同的观测序列和对应的状态序列{(o1,I1),...,(On,In)},可以用极大似然估计方法来估计隐马尔可夫模型的参数。

2.非监督学习方法

假设给定训练数据只包含S个长度为T的观测序列{(O1,...,Os)}而没有对应的状态序列,目标是学习隐马尔可夫模型M=(A,B,pai)的参数。

预测算法

近似算法和维特比算法。

维特比算法实际是用动态规划解隐马尔可夫模型预测问题,即用动态规划求概率最大路径。

我们只需要从时刻t=1开始,递推地计算在时刻t状态为i的各部分路径的最大概率,直至得到时刻t=T状态为i的各条路径的最大概率。时刻T的最大概率即为最优路径的概率P*,最优路径的终结点iT*也同时得到。之后为了找出最优路径的各个节点,从终结点iT*开始,由后向前逐步求得节点iT-1*,...,i1*,得到最优路径。这就是维特比算法。

java实现代码:

public class Viterbi {
public static int[] compute(int[] obs, int[] states, double[] start_p, double[][] trans_p, double[][] emit_p)
{
double[][] V = new double[obs.length][states.length];
int[][] path = new int[states.length][obs.length];

for (int y : states)
{
V[0][y] = start_p[y] * emit_p[y][obs[0]];
}

for (int t = 1; t < obs.length; ++t)
{
for (int y : states)
{
double prob = -1, tmp=-1;
int state = -1;
for (int y0 : states)
{
double nprob = V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];
double nstate = V[t-1][y0]*trans_p[y0][y];
if (nprob > prob)
{
prob = nprob;
}

if(nstate > tmp) {
state = y0;
tmp = nstate;
}

}

V[t][y] = prob;
path[y][t-1] = state;
}

}

double prob = -1;
int state = 0;
for (int y : states)
{
if (V[obs.length - 1][y] > prob)
{
prob = V[obs.length - 1][y];
state = y;
}
}

int[] ans = new int[obs.length];
int cnt = obs.length-1;
ans[cnt--] = state;

while (cnt >= 0) {
state = path[state][cnt];
ans[cnt--] = state;
}
return ans;
}
}


public class Main {
static enum Weather
{
Rainy,
Sunny,
}
static enum Activity
{
walk,
shop,
clean,
}

static int[] states = new int[]{Rainy.ordinal(), Sunny.ordinal()};
static int[] observations = new int[]{walk.ordinal(), shop.ordinal(), clean.ordinal()};
static double[] start_probability = new double[]{0.6, 0.4};
static double[][] transititon_probability = new double[][]{
{0.7, 0.3},
{0.4, 0.6},
};
static double[][] emission_probability = new double[][]{
{0.1, 0.4, 0.5},
{0.6, 0.3, 0.1},
};

public static void main(String[] args)
{
int[] result = Viterbi.compute(observations, states, start_probability, transititon_probability, emission_probability);
for (int r : result)
{
System.out.print(Weather.values()[r] + " ");
}
System.out.println();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: