隐马尔可夫模型 demo

统计学习方法第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.]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值