隐马尔科夫模型及Viterbi算法的应用

隐马尔科夫模型及Viterbi算法的应用

作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4335810.html

一个例子:

韦小宝使用骰子进行游戏,他有两种骰子一种正常的骰子,还有一种不均匀的骰子,来进行出千。

开始游戏时他有2/5的概率出千。

对于正常的骰子A,每个点出现的概率都是1/6.

对于不均匀的骰子B,5,6两种出现的概率为3/10,其余为1/10.

出千的随机规律如下图所示:

 

 

我们观测到的投掷结果为:ob={1,3,4,5,5,6,6,3,2,6}

请判断韦小宝什么时候出千了?

我们可以这样建模 xi 表示第 i 次投掷的骰子的种类, yi 表示第 i 次投掷出的点数, λ 表示各个概率参数。

那么第 t 次使用第 i 种骰子投掷的概率 δt(i) 等于

δt(i)=maxx1,,xt1P(x1,,xt1,xt=i,y1,,yt|λ)(1)

其实 δt+1(i) 可以由 δt(i) 推倒得出:

δt+1(i)==maxx1,,xtP(x1,,xt,xt+1=i,y1,,yt+1|λ)maxjδt(j)αjiβi(yt+1)(2)(3)

其中 αji 表示从第 j 个骰子转移到第 i 个骰子的概率。

βi(yt+1) 表示使用第i个骰子投出点 yt+1 的概率。

从而可以使用上述利用动态规划算法进行逐次递推计算。

得到的结果为:

 

t yt δt(A) Ψt(A) δt(B) Ψt(B)
1 1 0.1 A 0.04 A
2 3 0.0133333 A 0.0036 B
3 4 0.00177778 A 0.000324 B
4 5 0.000237037 A 0.000106667 A
5 5 3.16049e-05 A 2.88e-05 B
6 6 4.21399e-06 A 7.776e-06 B
7 6 5.61866e-07 A 2.09952e-06 B
8 3 7.49154e-08 A 1.88957e-07 B
9 2 9.98872e-09 A 1.70061e-08 B
10 6 1.33183e-09 A 4.59165e-09 B


从而从 Ψt(A) Ψt(B) 中选择 δt() 较大的骰子,从而预测骰子种类序列为:AAAAABBBBB 

代码如下所示:

复制代码
 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <string>
 5 #include <iostream>
 6 using namespace std;
 7 double initP[2] = {0.6, 0.4};//骰子A,B的初始概率
 8 double transferMatrix[2][2] = {{0.8, 0.2}, {0.1, 0.9}};//骰子之间的转移概率
 9 double EmissionP[2][6]={{1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0},//骰子A的发射概率
10                         {0.1, 0.1, 0.1, 0.1, 0.3, 0.3}};//骰子B的发射概率
11 double dp[10][2];//dp[i][j]第i步时,使用第j个骰子的最大概率
12 double dpS[10][2];//dpS[i][j]第i步时,使用第j个骰子,得到的最大概率时,使用的骰子种类, 0->A, 1->B
13 int ob[10] = {1, 3, 4, 5, 5, 6, 6, 3, 2, 6};//观测点数
14 bool diceArray[10];//预测骰子使用序列
15 void Viterbi()
16 {
17     memset(dp,0,sizeof(dp));
18     memset(dpS,0,sizeof(dpS));
19     memset(diceArray,0,sizeof(diceArray));
20     dp[0][0] = initP[0]* EmissionP[0][ob[0]-1];
21     dp[0][1] = initP[1]* EmissionP[1][ob[0]-1];
22     for( int i = 1 ; i < 10 ; i++ )//投掷次数
23     {
24         for( int j = 0 ; j < 2 ; j++ )//当前状态
25         {
26             for( int k = 0 ; k < 2 ; k++ )//上一个状态
27             {
28                 double tempP = dp[i-1][k] * transferMatrix[k][j] * EmissionP[j][ob[i]-1] ;
29                 if( dp[i][j] < tempP )
30                 {
31                     dp[i][j] = tempP;
32                     dpS[i][j] = k;
33                 }
34             }
35         }
36         if( dp[i][0] < dp[i][1] )
37         {
38             diceArray[i] = dpS[i][1];
39         }
40         else
41         {
42             diceArray[i] = dpS[i][0];
43         }
44     }
45 }
46 int main(int argc, char *argv[])
47 {
48     Viterbi();
49     cout<<"每步每个状态下的概率和骰子种类:"<<endl;
50     for( int i = 0 ; i < 10 ; i++ )
51     {
52         for( int j = 0 ; j < 2 ; j++ )
53         {
54             cout<<dp[i][j]<<" "<<dpS[i][j]<<"    ";
55         }
56         cout<<endl;
57     }
58     cout<<"预测骰子种类,0->A, 1->B : "<<endl;
59     for( int i = 0 ; i < 10 ; i++ )
60     {
61         cout<<diceArray[i]<<" ";
62     }
63     cout<<endl;
64 }
复制代码

 

分类:  机器学习
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值