zoukankan      html  css  js  c++  java
  • HMM(隐马尔可夫模型)不断学习中

    HMM(隐马尔可夫模型)是用来描述隐含未知参数的统计模型,举一个经典的例子:一个东京的朋友每天根据天气{下雨,天晴}决定当天的活动{公园散步,购物,清理房间}中的一种,我每天只能在twitter上看到她发的推“啊,我前天公园散步、昨天购物、今天清理房间了!”,那么我可以根据她发的推特推断东京这三天的天气。在这个例子里,显状态是活动,隐状态是天气。

    马尔可夫模型的学习笔记。

    简单的介绍下马尔科夫链,描述的是状态空间中经过一个状态到另一个状态的转换的随机过程,该过程要求具备“无记忆”的性质,即下一状态的概率分布智能友当前状态觉得,在时间序列中它前面的事件均与之无关。

    HMM

    从天气模型来说明。
    天气
    在这个马尔可夫模型中,存在三个状态,sunny,rainy,cloudy,图示中的箭头所向意味着状态之间的相互转换。
    状态转移矩阵A:

    weathersunnyrainycloudy
    sunny 0.6 0.1 0.3
    rainy 0.4 0.5 0.1
    cloudy 0.2 0.5 0.3

    假设某一天有三种不同的行为,散步、购物和收拾房间,但是这些行为受天气的影响。如下表格来描述,观测矩阵B:

    Weahteractionwalkshoptidy
    sunny 0.6 0.3 0.1
    rainy 0.1 0.4 0.5
    cloudy 0.3 0.4 0.3

    此外还有初始状态概率向量Pi,即为第一天不同天气的概率。观测序列,即为观测值(此处为干了什么)
    到此HMM基本要素:

    1. 初始概率向量π
    2. 状态转移矩阵
    3. 观测矩阵
    4. 观测序列

    现在利用HMM来解决实际问题:
    第一个问题,现在模型已知,你的朋友连续三天做的事情分别是:购物,散步和收拾。
    根据模型计算产生这些行为的概率是多少,很简单的概率计算。

    • 第一种计算方法,枚举法。
      计算出所有可能的类型,总共有3^3 种类型,其时间复杂度为N^T 。这种情况如果是观测序列变大,计算量会变得非常大。
    from numpy import *
    class HMM:
    def __init__(self):
    self.A = array([[0.6,0.1,0.3],[0.4,0.5,0.1],[0.2,0.5,0.1]])#状态矩阵
    self.B = array([[0.6,0.3,0.1],[0.1,0.4,0.5],[0.3,0.4,0.3]])#状态转移矩阵
    self.Pi = array([0.4,0.4,0.2])#初始概率
    self.o = [0,1,2]#观测序列
    self.ol = len(self.o)#观测序列长度
    self.m = len(self.A)#状态集合个数
    self.n = len(self.B[0])#观测项目个数
    def enumeration(self):
    tmp = 0
    for i in range(self.m):
    for k in range(self.m):
    for j in range():
    tmp += self.Pi[i]*self.B[i][self.o[0]]*self.A[i][k]*self.B[k][self.o[1]]*self.A[k][j]*self.B[j][self.o[2]]
    print tmp
    if __name__ == '__main__':
    RUN = HMM()
    RUN.enumeration()
    • 第二种解决方法是前向算法。
      前向变量αt(i):在t时刻,HMM输出序列为O1O2..OT,在第t时刻位于状态si的概率。
      在这个问题中,
      1. 在t1时刻,a1(1) = πsunny Bsunny(shop) , a1(2) = πrainy Brainy(shop) , a1(3) = πcloudy* Bcloudy(shop)
      2. 在t2时刻,a2(1) = a1(1) A1(1) Bsunny(walk) , a2(2) = a1(2) A1(2) Brainy(walk) , a2(3) = a1(3)* A1(3)Bcloudy(walk)
      3. ……以此类推,P(O|M) = an(1) + an(2) +…+an(n)

    计算某一时间的某个状态的前向变量需要看前一时刻的N个状态,此时的时间复杂度为O(N),而每个时刻有N个状态,又有T个观测向量,所以时间复杂度为O(N^2 T)

    def forward(self):
    self.x = array(zeros((self.ol,self.m))
    for i in range(self.m):
    self.x[0][i] = self.Pi[i]*self.B[i][self.o[0]]
    for x in range(1,self.ol):
    for y in range(self.m):
    tmp = 0
    for k in range(self.m):
    tmp += self.x[x-1][y]*self.A[k][i]
    self.x[i][y] = tmp*self.B[i][self.o[j]]
    res = 0
    for i in range(self.m):
    res += self.x[self.t-1][i]
    print self.x #前向概率矩阵
    print res #最终可能概率
    • 第三种解决方法是后向算法
      先介绍后向变量βt(i):给定模型μ=(A,B,π),在时间t 状态为Si的前提下,输出序列为O1O2..OT的概率,即βt(i)=P(Ot+1Ot+2…OT|qt=Si,μ)。
      后向概率的直观解释就是在t-1时刻输出到t时刻Ot状态下的概率。这里是参考网址
    def reverse(self):
    self.x = array(zeros((self.ol,self.m))
    for i in range(self.m):
    self.x[self.ol-1][i] = 1 #Ot+1为必然事件所以为1
    j = self.ol -2
    while j >=0:
    for i in range(self.m):
    for v in range(self.m):
    self.x[j][i] = self.A[i][v]*self.B[v][self.o[j+1]]*self.x[j+1][v]
    j = j - 1
    print self.x #后向矩阵
    res = 0
    for i in range(self.m):
    res += self.Pi[i]*self.B[i][self.o[0]]*self.x[0][i]
    print res #输出结果

    第二个问题,根据你的朋友的行为,猜测这几天最有可能的天气是怎样。

    • 有两个解决方法,第一个是算出每种状态下的发生概率,取最大的一个。但是这个方法忽略了状态之间的可转移性,有可能在两个状态下转移概率为0

    • 第二种解决方法是维特比算法,定义维特比变量δt(i):在时间t,HMM沿着一条路径到达状态si,并输出观测序列O=O(1)O(2)…Oa(T)的最大概率:δt(i) = max P(q1q2…qt=si,O1O2…Ot|μ)

    def viterbi(self):
    self.q = array(zeros((self.ol,self.m))#最大概率记录矩阵
    self.w = array(zeros((self.ol,self.m))#前一状态矩阵
    self.L = array(zeros(self.ol))
    for i in range(self.m):
    self.q[0][i] = self.Pi[i] * self.B[i][self.o[0]]
    self.w[0][i] = 0
    for k in range(1,self.ol):
    for i in range(self.m):
    self.q[k,i] = self.B[i][self.o[k]] * array([self.q[k-1][j] * self.A[j][i] for i in range(self.m)]).argmax()
    self.w[k,i] = array([self.q[k-1][j] * self.A[j][i] for j in range(self.m)]).argmax()
    P = self.q[self.ol-1].max()
    print P #发生这种行为的最大概率
    self.L[self.ol - 1] = delta[self.ol - 1].argmax()#获得最大概率的index,此个index记录了上一最大概率所处状态。
    for i in range(self.ol -2, -1, -1):
    I[t] = self.w[i + 1, self.L[i + 1]] # 从后往前,
    print I

    应用

    输入预测

    HMM模型有三个组成,μ = (A,B,π)。隐马尔科夫模型python实现简单拼音输入法

    • 统计初始化概率矩阵π,也就是找出所有文字出现在句首的概率。也就是你打开手机输入法后不作任何输出第一排显示的问题。
    • 状态转移矩阵A,假设你点击了一个字,输入法就要根据输入内容来预测你下一个想输入的字来更新推荐栏。
    • 发射概率矩阵,在输出拼音的情况下,根据使用频率来推荐字。

      解决生物学问题

      预测5‘剪切位点

    SR Eddy - ‎2004

    Eddy SR. What is a hidden Markov model? Nat Biotechnol. 2004;22(10):1315-1316. doi:10.1038/nbt1004-1315.

    hidden_states = [E,5,I]
    obervations = [A,C,G,T]

    transitionE5I
    E 0.9 0.1 0
    5 0 0 1
    I 0 0.9 0.1
    emissionACGT
    E 0.25 0.25 0.25 0.25
    5 0.05 0 0.95 0
    I 0.4 0.1 0.1 0.4

    解释下该图,假设你有一个DNA序列,同时包含了内含子(I)和外显子(E)。我们要进行5’的剪切位点的预测,假设我们已建立HMM模型μ=(A,B,π),该图最上面已经包含了所有的状态转移矩阵A、观测状态矩阵和初始概率π,要进行预测的DNA序列中的每个碱基就是我们的观测向量。和上面解决天气模型一直,已知动作判断天气,现在是已知序列判断那个是外显子和内含子的分界岭,输出概率最大的一个,一般使用lgP表示。
    同样的我们可以预测新物种的基因编码区,基因的结构域,

    前向算法伪代码:

    To use the example follow these steps :

    1. Enter a number of valid observed states in the input field.
    2. Press 'Set' to initialise the matrix.
    3. Use either 'Run' or 'Step' to make the calculations.
      • 'Run' will calculate the a's for each and every node and return the probability of the HMM.
      • 'Step' will calculate the a value for the next node only. Its value is displayed in the output window.
  • 相关阅读:
    JAVA 框架
    npm安装超时,使用淘宝镜像
    使用vite搭建Vue3项目
    前端常用框架
    vue发布自己的组件库-vue3
    vue2升级vue3-基础教程
    Navicat Premium 15破解失败解决方案
    大屏
    vue使用高德地图
    vue生命周期及钩子函数
  • 原文地址:https://www.cnblogs.com/ylHe/p/6692704.html
Copyright © 2011-2022 走看看