维基百科: https://zh.wikipedia.org/wiki/维特比算法 (可能需要翻墙)
错误的例子一:http://blog.csdn.net/shijing_0214/article/details/51173887 (选择最佳路径后前推时使用了前向算法的公式)
错误的例子二:http://www.cnblogs.com/zhiranok/ ... /ymrkf_viterbi.html (用Python写的,没细看,但是结果不对)
Viterbi宏代码(例子的HMM已经写入代码):
%macro viterbi(obs);
proc iml;
/*Healthy Fever*/
a1={0.7 0.3};
a2={0.4 0.6};
a=a1//a2;
/*Normal Cold Dizzy */
b1={0.5 0.4 0.1};
b2={0.1 0.3 0.6};
b=b1//b2;
pi={0.6 0.4};
os={&os};
vec=i(2);
/*t=1*/
/*隐藏状态*/
hs=pi;
/*观察向量*/
obs=b[,os[1]]`;
cand=hs#obs;
ws=cand[<:>];
pr=cand`;
/*t>=2*/
do i=2 to ncol(os);
h_win=vec[ws[i-1],]#pr[i-1]`;
/*h_win=vec[ws[i-1],];*/
hs=h_win*a;
/*根据观察状态选择发射向量*/
obs=B[,os]`;
/*hs与os点积获得隐藏状态的比较集*/
cand=hs#obs;
/*获取获胜隐含状态及概率*/
ws=ws||cand[<:>];
pr=pr||cand`;
end;
print ws pr;
/*store pr;*/
quit;
%mend;
调用宏可以得到:
%viterbi(1 2 3)
结果:
说明:
ws中的1 1 2 代表healthy,healthy,fever
宏参数中的1 2 3 代表normal cold dizzy
pr则是每步的概率,结合GIF图可以对照验证。
例子解释:
想象一个乡村诊所。村民有着非常理想化的特性,要么健康要么发烧。他们只有问诊所的医生的才能知道是否发烧。 聪明的医生通过询问病人的感觉诊断他们是否发烧。村民只回答他们感觉正常、头晕或冷。
假设一个病人每天来到诊所并告诉医生他的感觉。医生相信病人的健康状况如同一个离散马尔可夫链。病人的状态有两种“健康”和“发烧”,但医生不能直接观察到,这意味着状态对他是“隐含”的。每天病人会告诉医生自己有以下几种由他的健康状态决定的感觉的一种:正常、冷或头晕。这些是观察结果。 整个系统为一个隐马尔可夫模型(HMM)。
病人连续三天看医生,医生发现第一天他感觉正常,第二天感觉冷,第三天感觉头晕。 于是医生产生了一个问题:怎样的健康状态序列最能够解释这些观察结果。
另外就是维基中例子使用Python写的,看着比C语言(UMDHMM)写的简洁一些。
除掉矩阵的定义部分以及里面的print语句,我做了一下程序长度对比,python vs iml =570:221,总体来说用iml是更简洁一些的。