其他分享
首页 > 其他分享> > 统计学习方法--隐马尔可夫模型

统计学习方法--隐马尔可夫模型

作者:互联网

1.隐马尔可夫模型简介

隐马尔可夫模型由一个状态序列,一个观测序列组成,其中状态序列是不可观测的,因此叫做隐马尔可夫模型(HMM)。
几个重要的参数:Q,V,A,B,O, π \pi π,
Q是所有可能出现的状态的集合(可能的状态由N个),V是所有可能出现的观测结果的集合(可能的观测结果由M个),A是状态转移概率矩阵,是一个NN维的方针,B是一个观测概率矩阵,是一个NM维度的矩阵,O是观测序列,长度为T, π \pi π是初始的状态概率向量,是一个N*1的向量。

2.python代码实现

在这部分的代码中包含了HMM的3个算法:前向,后向以及viterbi算法。
其中viterbi算法适合于求解最优路径,适合动态路径规划的求解。

# 定义马尔可夫类
# 包含前向、后向以及维特比三个算法
# 难点是循环部分的代码,书中的公式是求和,这里可以直接用矩阵的内积简单计算
# 在计算时,维度要对齐
import numpy as np 
class HMM:
    def __init__(self):
        self.alpha = None
        self.farward_p = None
        self.back_p = None

    def farward(self,Q,V,A,B,O,PI):
        N = len(Q)
        M = len(O)
        alpha = np.zeros((N,M))

        T= M
        for t in range(T):
            index = V.index(O[t])
             ## 接下来是遍历每一个状态
             ## 先是遍历每一个时刻,接下来是遍历每一个状态
            for i in range(N):
                if t == 0:
                    alpha[i][t] = PI[t][i]*B[i][index]  # PI这里的索引存在疑问
                    print('alnpha1(%d) = p%db%db(o1) = %f' %
                          (i + 1, i, i, alpha[i][t]))
                else:
                    alpha[i][t] = np.dot(alpha[:,t-1],A[:,i]) * B[i][index]
                    print('alpha%d(%d) = [sigma alpha%d(i)ai%d]b%d(o%d) = %f' %
                          (t + 1, i + 1, t - 1, i, i, t, alpha[i][t]))
        self.farward_p = np.sum(alpha[:,-1])
        self.alpha = alpha
        print('==========================================')
        print('Backward P(O|lambda): %.6f' % self.farward_p)
        print('==========================================')

    def backward(self,Q,V,A,B,O,PI):
        # 后向算法过程用到了一个后向排序的过程
        # for i in range(M - 2, -1, -1)
        N = len(Q)
        M = len(O)
        beta = np.zeros((N,M))        
        T = M
        for t in range(T-1,-1,-1):            
            for i in range(N):
                if t == M-1:
                    beta[i,-1] = 1
                    print('Beta[%d][%d]= %f' % (t+1,i+1,beta[i,-1]))
                else:
                    index = V.index(O[t+1])
                    beta[i][t] = np.dot(np.multiply(A[i,:],B[:,index]),beta[:,t+1])
                    print('Beta[%d][%d]= %f' % (t+1,i+1,beta[i,t]))

        index_1 = V.index(O[0])
        back_p = [B[i][index_1]*PI[0][i]*beta[i][0] for i in range(N)]
        # print(np.sum(back_p))
        self.back_p = np.sum(back_p)
        print('==========================================')
        print('Backward P(O|lambda): %.6f' % self.back_p)
        print('==========================================')

    def viterbi(self,Q,V,A,B,O,PI):
        N = len(Q)
        M = len(O)
        T = M
        delta =np.zeros((N,T))  
        phai = np.zeros((N,T))

        # 遍历每一个时刻,相当于前向传播的计算
        for t in range(T):
            for i in range(N):
                if t == 0:
                    index = V.index(O[t])
                    delta[i][t] = PI[0][i] * B[i,index]
                    phai[i][t] = 0
                else:
                    index = V.index(O[t])
                    delta[i][t] = np.max(np.multiply(delta[:,t-1],A[:,i]))*B[i,index]
                    phai[i][t] = np.argmax(np.multiply(delta[:,t-1],A[:,i]))

        p_star = np.max(delta[:,-1])
        i_T = np.argmax(delta[:,-1])
        path = np.zeros(T)
        path[-1] = i_T+1
        # 第四步是最优路径的回溯,返回去寻找最优的路径
        for t in range(T-2,-1,-1):
            i_t = phai[int(i_T),t+1]
            path[t] = i_t + 1
            i_T = i_t        
        print('==========================================')
        print('Viterbi P(O|lambda): %.6f' % p)
        print('The best path is: %s-->%s-->%s-->%s' % (int(path[0]),int(path[1]),int(path[2]),int(path[3])))
        # print('Backward Algorithm P(O|lambda): %.6f' % p)
        print('==========================================')

结合李航《统计学习方法》书中的p13课后习题1,下面分别实现前向、后向以及维特比算法。

if __name__ == '__main__':
    #习题10.1
    Q = [1, 2, 3]
    V = ['红', '白'] ## 一共有几种观测结果,表示的只是不同结果的个数
    ## 3个不同的盒子就是3个不同的状态;
    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]])

    # O = ['红', '白', '红', '红', '白', '红', '白', '白']
    O = ['红', '白', '红','白',]    #习题10.1的例子
    PI = [[0.2, 0.4, 0.4]]
    my_hmm = HMM()
    my_hmm.farward(Q,V,A,B,O,PI)
    my_hmm.backward(Q,V,A,B,O,PI)
    my_hmm.viterbi(Q,V,A,B,O,PI)

前向算法结果:
在这里插入图片描述

后向算法结果:
在这里插入图片描述
维特比算法结果:
在这里插入图片描述

标签:index,--,模型,print,马尔可夫,np,alpha,PI,self
来源: https://blog.csdn.net/LuminCynthia_/article/details/122690443