一.背景说明:
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,但risk与unrisk的概率差在逐渐减小;
三.通用的处理方式
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]