HMM(隐马尔可夫模型)不断学习中

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

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

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

HMM

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

weathersunnyrainycloudy
sunny0.60.10.3
rainy0.40.50.1
cloudy0.20.50.3

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

Weahter\actionwalkshoptidy
sunny0.60.30.1
rainy0.10.40.5
cloudy0.30.40.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
E0.90.10
5001
I00.90.1
emissionACGT
E0.250.250.250.25
50.0500.950
I0.40.10.10.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.

转载于:https://www.cnblogs.com/ylHe/p/6692704.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值