统计学习方法第10章.红球白球的案例
import numpy as np
def prepareData():
A=np.array([[0.5,0.2,0.3],
[0.3,0.5,0.2],
[0.2,0.3,0.5]
])
B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]) #红球和白球的几率
pi=np.array([0.2,0.4,0.4])
Ob=np.array(["红","白","红"])
return A,B,pi,Ob
class Hmm():
def __init__(self,A,B,pi,Ob):
self.A=A
self.B=B
self.pi=pi
self.Ob=Ob
def forard(self):
# 前向算法
alpha=self.multiplyB(self.pi,0)
for i in range(1,len(self.Ob)):
alpha=self.multiplyB(alpha.dot(self.A),i)
return alpha.sum()
def back(self):
# 后向算法
beta=np.ones(self.pi.size)
for i in range(len(self.Ob)):
index=len(self.Ob)-1-i
beta = self.multiplyB(beta.dot(self.A.T), index)
return (self.pi*beta).sum()
def multiplyB(self,xArray,obIndex):
color=self.Ob[obIndex]
if(color=="红"):
return np.multiply(xArray,self.B[:,0])
elif(color=="白"):
return np.multiply(xArray, self.B[:, 1])
else:
raise ValueError
def best_way(self):
# 维特比算法
delta=self.multiplyB(self.pi,0)
print("时刻1的最大状态:",delta)
bestway_dict=[]
for i in range(1,len(self.Ob)):
_delta=delta*self.A.T
col_index=np.argmax(_delta,axis=1)
bestway_dict.append(dict(enumerate(col_index)))
new_delta=np.ndarray(len(delta))
for j in range(len(col_index)):
new_delta[j]=_delta[j,col_index[j]]
delta=self.multiplyB(new_delta,i)
print("时刻{}的最大状态:{}".format(i+1,delta))
k=np.argmax(delta)
best_way=np.zeros(len(self.Ob))
best_way[len(self.Ob)-1]=k
for i in range(len(bestway_dict)):
index=len(bestway_dict)-1-i
k=bestway_dict[index][k]
best_way[index]=k
best_way=best_way+1
return best_way
def run():
A, B, pi, Ob=prepareData()
hmm=Hmm(A, B, pi, Ob)
res=hmm.forard()
print('前向算法概率是:{:.5f}'.format(res))
res=hmm.back()
print('后向算法概率是:{:.5f}'.format(res))
best_way=hmm.best_way()
print('最佳状态序列是:{}'.format(best_way))
if __name__ == '__main__':
import sys
run()
sys.exit(0)
运行结果
前向算法概率是:0.13022
后向算法概率是:0.13022
时刻1的最大状态: [0.1 0.16 0.28]
时刻2的最大状态:[0.028 0.0504 0.042 ]
时刻3的最大状态:[0.00756 0.01008 0.0147 ]
最佳状态序列是:[3. 3. 3.]