隱馬爾可夫模型 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.]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章