HMM-viterbi

.背景说明:


HMM:包含2状态,3概率


模拟如下场景:


- 隐藏状态:{有风险,无风险}


- 观测状态:{多头数>20,记为'' 20>多头数>10 计为'',多头数<10 记为 '' }


- 隐藏状态初始化概率 {有风险:0.3,无风险:0.7}


- 隐藏状态到隐藏状态-即状态转移概率矩阵{

有风险->有风险:0.9

有风险->无风险: 0.1

无风险->有风险:0.3

无风险->无风险: 0.7

}


- 隐藏状态到观测状态- 即发生概率矩阵


{

有风险->高:0.6  有风险->中:0.3  有风险-> 0.1

无风险->高:0.2  无风险->中:0.3  无风险->  0.5

}


.分步骤计算


import  numpy as np

stats=['risk','norisk']
obs=['high','middle','low'] #观测到3期,当然也可以更多
pi0=np.array([0.3,0.7])
transforms=np.array([
         #risk,unrisk
    [0.9,0.3], #risk
    [0.1,0.7]   #unrisk
])

emit=np.array([
         #risk,unrisk
     [0.6,0.2],#high
     [0.3,0.3],#middle
     [0.1,0.5] #low
])

# t0时刻,观察值为high,计算risk->high unrisk->high

p_risk_high_t0=pi0[0]*emit[0,0]
p_unrisk_high_t0=pi0[1]*emit[0,1]

print(p_risk_high_t0)
print(p_unrisk_high_t0)
print("\n")

#--->有风险<----

# t1时刻,观察值为middle:
p_risk_risk_middle_t1=p_risk_high_t0*transforms[0,0]*emit[1,0]  #t0时刻unrisk-> t1时刻unrisk -> t1时刻发射 middle
p_risk_unrisk_middle_t1=p_risk_high_t0*transforms[1,0]*emit[1,1]  #t0时刻risk-> t1时刻 unrisk -> t1时刻发射 middle

print(p_risk_risk_middle_t1)
print(p_risk_unrisk_middle_t1)
print("\n")
#--->有风险<----

#t2 时刻 ,观察值为middle,这里注意下markov的性质,t2状态只与t1的状态有关系,与t0没关系

p_risk_risk_low_t2=p_risk_risk_middle_t1*transforms[0,0]*emit[2,0] #t1时刻unrisk-> t2时刻unrisk -> t1时刻发射 middle
p_risk_unrisk_low_t2=p_risk_risk_middle_t1*transforms[1,0]*emit[2,1] #t1时刻unrisk-> t2时刻 risk -> t1时刻发射 middle

print(p_risk_risk_low_t2)
print(p_risk_unrisk_low_t2)
print("\n")

#--->有风险<----

#路径:有风险->有风险->有风险

输出:

0.18

0.13999999999999999


0.0486

0.005399999999999999


0.004374

0.00243


我们的观测值从high->middle->low,尽管3个时刻预测的状态为risk,但riskunrisk的概率差在逐渐减小;





.通用的处理方式


import  numpy as np

stats=['risk','norisk']
obs=['high','middle','low'] #观测到3期,当然也可以更多
pi0=np.array([0.3,0.7])
transforms=np.array([
         #risk,unrisk
    [0.9,0.3], #risk
    [0.1,0.7]   #unrisk
])

emit=np.array([
         #risk,unrisk
     [0.6,0.2],#high
     [0.3,0.3],#middle
     [0.1,0.5] #low
])


n=len(obs)
m=len(stats)
obs_index={}     #主要用于定位发射矩阵的哪一行
stats_index={}  #主要用于定位转移矩阵的哪一列
index_stats={}

for i in range(n):
    obs_index[obs[i]]=i
for i in range(m):
    stats_index[stats[i]]=i
for i in range(m):
    index_stats[i]=stats[i]

first_index=np.argmax(pi0*emit[obs_index[obs[0]],:])
first_value=np.max(pi0*emit[obs_index[obs[0]],:])
first=index_stats[first_index]
#print(first)
path=[]        #记录隐藏状态路径
path_value=[]  #记录隐藏状态
path.append(first)
path_value.append(first_value)

for i in range(1,n):
    start=path[i-1]
    index=stats_index[start]
    prob=max(path_value[i-1]*transforms[:,index]*emit[obs_index[obs[i]],:])
    path_value.append(prob)
    index1=np.argmax(path_value[i-1]*transforms[:,index]*emit[obs_index[obs[i]],:])
    path.append(index_stats[index1])

print(path)
print(path_value)  

输出:

['risk', 'risk', 'risk']

[0.18, 0.0486, 0.004374]











猜你喜欢

转载自blog.csdn.net/huangqihao723/article/details/79153945
今日推荐