700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 机器学习知识点(二十四)隐马尔可夫模型HMM维特比Viterbi算法Java实现

机器学习知识点(二十四)隐马尔可夫模型HMM维特比Viterbi算法Java实现

时间:2024-07-12 22:27:01

相关推荐

机器学习知识点(二十四)隐马尔可夫模型HMM维特比Viterbi算法Java实现

1、隐马尔可夫模型HMM

学习算法,看中文不如看英文,中文喜欢描述的很高深。

p.leeds.ac.uk/roger/HiddenMarkovModels/html_dev/main.html

里面有HMM定义、前向算法、维特比算法、后向算法。

2、Viterbi是隐马尔科夫模型中用于确定(搜索)已知观察序列在HMM下最可能的隐藏序列。

Viterb采用了动态规划的思想,利用后向指针递归地计算到达当前状态路径中的最可能(局部最优)路径。

要理解,看wiki的一个动态图。

/wiki/File:Viterbi_animated_demo.gif

求解最可能的隐状态序列是HMM的三个典型问题之一,通常用维特比算法解决。

维特比算法就是求解HMM上的最短路径(-log(prob),也即是最大概率)的算法。

3、HMM五元组

1)obs:观测序列,m个;

2)states:隐状态,n个;

3)start_p:初始概率(隐状态)

4)trans_p:转移概率(隐状态),n*n矩阵,描述时间序列上的隐状态概率;

5)emit_p: 发射概率 (隐状态表现为显状态的概率),n*m矩阵;

要理解HMM模型的基本定义和三个基本问题。

4、Viterbi算法简单实现:

/hankcs/Viterbi/tree/master/src/com/hankcs/algorithm

算法本身理解是一回事,着手代码又是一回事,所以对于能够代码动手实现的,是很值得学习的,至少表明其深入理解了。

算法中的思路是从观测的序列得到最大概率的隐状态,关键就是这一时刻的隐状态能得出下一个时刻隐状态的概率以及这一时刻显状态的概率。

package sk.ml;/*** 维特比算法*/public class Viterbi {/*** 求解HMM模型* @param obs 观测序列* @param states 隐状态* @param start_p 初始概率(隐状态)* @param trans_p 转移概率(隐状态)* @param emit_p 发射概率 (隐状态表现为显状态的概率)* @return 最可能的序列*/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]];path[y][0] = y;}for (int t = 1; t < obs.length; ++t){int[][] newpath = new int[states.length][obs.length];for (int y : states){double prob = -1;int state;for (int y0 : states){double nprob = V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];if (nprob > prob){prob = nprob;state = y0;// 记录最大概率V[t][y] = prob;// 记录路径System.arraycopy(path[state], 0, newpath[y], 0, t);newpath[y][t] = y;}}}path = newpath;}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;}}return path[state];}}

5、网络上对HMM有两个比较经典的案例,一个是天气,一个是诊断。

诊断见知乎上文章:/question/6144

package sk.ml;import static sk.ml.DoctorExample.Status.*;import static sk.ml.DoctorExample.Feel.*;public class DoctorExample {enum Status{Healthy,//健康Fever,//感冒}enum Feel{normal,//舒服cold,//冷dizzy,//头晕}static int[] states = new int[]{Healthy.ordinal(), Fever.ordinal()};static int[] observations = new int[]{normal.ordinal(), cold.ordinal(), dizzy.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.5, 0.4, 0.1},{0.1, 0.3, 0.6},};public static void main(String[] args){int[] result = pute(observations, states, start_probability, transititon_probability, emission_probability);for (int r : result){System.out.print(Status.values()[r] + " ");}System.out.println();}}

执行结果:

Healthy Healthy Fever

天气见这里面的例子:p.leeds.ac.uk/roger/HiddenMarkovModels/html_dev/main.html

package sk.ml;import static sk.ml.WeatherExample.Weather.*;import static sk.ml.WeatherExample.Activity.*;public class WeatherExample {enum Weather//隐状态{Rainy,//下雨Sunny,//天晴}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 = pute(observations, states, start_probability, transititon_probability, emission_probability);for (int r : result){System.out.print(Weather.values()[r] + " ");}System.out.println();}}

执行结果:

Sunny Rainy Rainy

理解算法最好的就是代码和数学公式两边对应。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。