预测算法
1.1 近似算法
近似算法的想法是,在每个时刻
t
选择在该时刻最有可能出现的状态
给定隐马尔科夫模型
λ
和观测序列
O
,在时刻
在每一时刻
t
最有可能的状态
从而得到状态序列 I∗=(i∗1,i∗2,⋯,i∗T)
近似算法的优点是计算简单,其缺点是不能保障预测的状态序列整体是最有可能的状态序列,因为预测的状态序列可能有实际不发生的部分。事实上,上述方法得到的状态序列有可能存在转移概率为 0 的相邻状态,即对某些 i,j,aij=0 时,尽管如此,近似算法仍然是有用的。
1.2 维特比算法(Viterbi algorithm)
维特比算法实际是用动态规划解隐马尔科夫模型预测问题,即用动态规划求概率最大路径,这时一条路径对应着一个状态序列。
最优路径有这样的特性:如果最优路径在时刻
t
通过结点
根据动态规划的原理,我们只需从时刻
t=1
开始,递推地计算在时刻
t
状态为
首先,导入两个变量
δ
和
ψ
, 定义在时刻
t
状态为
由定义知:
定义在时刻
t
状态为
具体过程为:
输入: 模型
λ=(A,B,π)
和观测
O=(o1,o2,⋯,oT)
输出: 最优路径
I∗=(i∗1,⋯,i∗T)
初始化:
δ1(i)=πibi(o1),i=1,2,⋯,N
ψ1(i)=0,i=1,2,⋯,N递推,对 t=2,3,⋯,T
终止
P∗=max1≤i≤NδT(i)
i∗T=argmax1≤i≤N[δT(i)]最优路径的回溯,对 t=T−1,T−2,⋯,1
参考《统计学方法》上面的例题,写了一个代码如下
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<sstream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
double A[3][3] = {0.5,0.2,0.3,0.3,0.5,0.2,0.2,0.3,0.5};
double B[3][2] = {0.5,0.5,0.4,0.6,0.7,0.3};
double pi[3] = {0.2,0.4,0.4};
double sigma[3][3];
int psi[3][3];
int O[3] = {0,1,0};
int T = 3;
for (int i = 0; i < 3; ++i) {
sigma[0][i] = pi[i]*B[i][O[0]];
}
vector<int>path;
int best = 0;
for (int t = 1; t < T; ++t) {
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (sigma[t][i] < sigma[t-1][j]*A[j][i]*B[i][O[t]]) {
sigma[t][i] = sigma[t-1][j] * A[j][i] * B[i][O[t]];
psi[t][i] = j;
best = j;
}
}
}
}
for (int i = 2; i >= 0; --i) {
cout<<best+1<<' ';
best = psi[i][best];
}
cout<<endl;
cout<<"**********"<<endl;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j)
cout<<sigma[i][j]<<' ';
cout<<endl;
}
return 0;
}