全部文章

隐马模型HMM(马尔科夫)

EM算法

EM算法也称期望最⼤化(Expectation-Maximum,简称EM)算法。

它是⼀个基础算法,是很多机器学习领域算法的基础,⽐如隐式⻢尔科夫算法(HMM)等等。

EM算法是⼀种迭代优化策略,由于它的计算⽅法中每⼀次迭代都分两步:

  • 期望步(E步)
  • 极⼤步(M步)

所以算法被称为EM算法(Expectation-Maximization Algorithm)。

EM算法受到缺失思想影响,最初是为了解决数据缺失情况下的参数估计问题,其算法基础和收敛有效性等问题在Dempster、Laird和Rubin三⼈于1977年所做的⽂章《Maximum likelihood from incomplete data via the EM algorithm》中给出了详细的阐述。其基本思想是:

⾸先根据⼰经给出的观测数据,估计出模型参数的值

然后再依据上⼀步估计出的参数值估计缺失数据的值,再根据估计出的缺失数据加上之前⼰经观测到的数据重新再对参数值进⾏估计;然后反复迭代,直⾄最后收敛,迭代结束。

EM算法计算流程:

极大似然估计

详细参照:https://www.cnblogs.com/luzhanshi/articles/18880583极大似然估计篇章

多数情况下,我们是根据已知条件来推算结果,⽽极⼤似然估计是已知结果,寻求使该结果出现的可能性最⼤的条件,以此作为估计值。

总的来说:极⼤似然估计就是⽤来估计模型参数的统计学⽅法。

EM算法描述

看不懂的话,先看下面的实例

我们⽬前有100个男⽣和100个⼥⽣的身⾼,但是我们不知道这200个数据中哪个是男生的身⾼,哪个是女生的身高,即抽取得到的每个样本都不知道是从哪个分布中抽取的。

这个时候,对于每个样本,就有两个未知量需要估计:

(1)这个身⾼数据是来⾃于男⽣数据集合还是来⾃于⼥⽣?

(2)男⽣、⼥⽣身⾼数据集的正态分布的参数分别是多少?

具体问题如下图:

对于具体的身高问题使⽤EM算法求解步骤如下:

(1)初始化参数:先初始化男⽣身⾼的正态分布的参数:如均值=1.65,⽅差=0.15;

(2)计算分布:计算每⼀个⼈更可能属于男⽣分布或者⼥⽣分布;

(3)重新估计参数:通过分为男⽣的n个⼈来重新估计男⽣身⾼分布的参数(最⼤似然估计),⼥⽣分布也按照相同的⽅式估计出来,更新分布。

(4)这时候两个分布的概率也变了,然后重复步骤(1)⾄(3),直到参数不发⽣变化为⽌

3 EM算法流程

输⼊:

  • n个样本观察数据:x=(x1,x2,...xn),未观察到的隐藏数据:(z1,z2...zn)
  • 联合分布(p,x;θ),条件分布(z|x,θ),最大迭代次数J

算法步骤:

1)随机初始化模型参数θ的初值θ0

2)j = 1, 2, ..., J 开始EM算法迭代:

E步:计算联合分布的条件概率期望:

M步:极⼤化l(θ,θj),得到θj+1:

θj+1=argmaxl(θ,θj)

argmax 代表 "argument of the maximum"(最大值对应的自变量/参数)。​​ 它的核心目标不是找出一个函数的最大值是多少,而是找出​​当函数取得这个最大值时,对应的输入值(自变量、参数)是什么​​。

换句话说:

  • max (最大值) 问:​​函数最高能达到多少?​
  • argmax (最大值点) 问:​​函数在哪个(或哪些)输入点上达到这个最高值?​

如果l(θ,θj)已经收敛,则算法结束。否则继续进⾏E步和M步进⾏迭代。

输出:模型参数θ。

EM算法实例

1 ⼀个超级简单的案例

假设现在有两枚硬币1和2,,随机抛掷后正⾯朝上概率分别为P1,P2。为了估计这两个概率,做实验,每次取⼀枚硬币,连掷5下,记录下结果,如下:

硬币 结果 统计
1 正正反正反 3 正 - 2 反
2 反反正正反 2 正 - 3 反
1 正反反反反 1 正 - 4 反
2 正反反正正 3 正 - 2 反
1 反正正反反 2 正 - 3 反

以很容易地估计出P1和P2,如下:

P1 = (3+1+2)/ 15 = 0.4

P2= (2+3)/10 = 0.5

到这⾥,⼀切似乎很美好,下⾯我们加⼤难度。

2 加入隐变量z后的求解

还是上⾯的问题,现在我们抹去每轮投掷时使⽤的硬币标记,如下:

硬币 结果 统计
Unknown 正正反反正 3 正 - 2 反
Unknown 反反正正反 2 正 - 3 反
Unknown 正反反反反 1 正 - 4 反
Unknown 正反反正正 3 正 - 2 反
Unknown 反正正反反 2 正 - 3 反

好了,现在我们的⽬标没变,还是估计P1P2,要怎么做呢?

显然,此时我们多了⼀个隐变量z,可以把它认为是⼀个5维的向量(z1,z2,z3,z4,z5),代表每次投掷时所使⽤的硬币,⽐如z1,就代表第⼀轮投掷时使⽤的硬币是1还是2。但是,这个变量z不知道,就⽆法去估计P1和P2,所以,我们必须先估计出z,然后才能进⼀步估计P1和P2。

但要估计z,我们⼜得知道P1和P2,这样我们才能⽤最⼤似然概率法则去估计z,这不是鸡⽣蛋和蛋⽣鸡的问题吗,如何破?

答案就是先随机初始化⼀个P1和P2,⽤它来估计z,然后基于z,去估计新的P1和P2,如果新的P1和P2和我们初始化的P1和P2⼀样,请问这说明了什么?(此处思考1分钟)

这说明我们初始化的P1和P2是⼀个相当靠谱的估计!

就是说,我们初始化的P1和P2,按照最⼤似然概率就可以估计出z,然后基于z,按照最⼤似然概率可以反过来估计出P1和P2,当与我们初始化的P1和P2⼀样时,说明是P1和P2很有可能就是真实的值。这⾥⾯包含了两个交互的最⼤似

然估计。

如果新估计出来的P1和P2和我们初始化的值差别很⼤,怎么办呢?就是继续⽤新的P1和P2迭代,直⾄收敛。

这就是下⾯的EM初级版。

2.1 EM初级版

我们不妨这样,先随便给P1和P2赋⼀个值,⽐如:

  • P1 = 0.2
  • P2 = 0.7

然后,我们看看第⼀轮抛掷最可能是哪个硬币。

  • 如果是硬币1,得出3正2反的概率为 0.2 ∗ 0.2 ∗ 0.2 ∗ 0.8 ∗ 0.8 = 0.00512
  • 如果是硬币2,得出3正2反的概率为0.7 ∗ 0.7 ∗ 0.7 ∗ 0.3 ∗ 0.3 = 0.03087

然后依次求出其他4轮中的相应概率。做成表格如下:

轮数 若是硬币 1 若是硬币 2
1 0.00512 0.03087
2 0.02048 0.01323
3 0.08192 0.00567
4 0.00512 0.03087
5 0.02048 0.01323

按照最⼤似然法则:

  • 第1轮中最有可能的是硬币2
  • 第2轮中最有可能的是硬币1
  • 第3轮中最有可能的是硬币1
  • 第4轮中最有可能的是硬币2
  • 第5轮中最有可能的是硬币1

我们就把上⾯的值作为z的估计值。然后按照最⼤似然概率法则来估计新的P1和P2。

  • P1 = (2+1+2)/15 = 0.33
  • P2=(3+3)/10 = 0.6

设想我们是全知的神,知道每轮抛掷时的硬币就是如本⽂第1部分(1 ⼀个超级简单的案例)标示的那样,那么,P1和P2的最⼤似然估计就是0.4和0.5(下⽂中将这两个值称为P1和P2的真实值)。那么对⽐下我们初始化的P1和P2和新估计出的P1和P2:

初始化的 P1 估计出的 P1 真实的 P1
0.2 0.33 0.4
初始化的 P2 估计出的 P2 真实的 P2
0.7 0.6 0.5

到没?我们估计的P1和P2相⽐于它们的初始值,更接近它们的真实值了!

可以期待,我们继续按照上⾯的思路,⽤估计出的P1和P2再来估计z,再⽤z来估计新的P1和P2,反复迭代下去,就可以最终得到P1 = 0.4,P2=0.5,此时⽆论怎样迭代,P1和P2的值都会保持0.4和0.5不变,于是乎,我们就找到了P1和P2的最⼤似然估计。

这⾥有两个问题:

1、新估计出的P1和P2⼀定会更接近真实的P1和P2?

答案是:没错,⼀定会更接近真实的P1和P2,数学可以证明,但这超出了本⽂的主题,请参阅其他书籍或⽂章。

2、迭代⼀定会收敛到真实的P1和P2吗?

答案是:不⼀定,取决于P1和P2的初始化值,上⾯我们之所以能收敛到P1和P2,是因为我们幸运地找到了好的初始化值。

2.2 EM进阶版

下⾯,我们思考下,上⾯的⽅法还有没有改进的余地?

我们是⽤最⼤似然概率法则估计出的z值,然后再⽤z值按照最⼤似然概率法则估计新的P1和P2。也就是说,我们使⽤了⼀个最可能的z值,⽽不是所有可能的z值。

如果考虑所有可能的z值,对每⼀个z值都估计出⼀个新的P1和P2,将每⼀个z值概率⼤⼩作为权重,将所有新的P1和P2分别加权相加,这样的P1和P2应该会更好⼀些。

所有的z值有多少个呢?

显然,有25= 32种,需要我们进⾏32次估值??

不需要,我们可以⽤期望来简化运算。

轮数 若是硬币 1 若是硬币 2
1 0.00512 0.03087
2 0.02048 0.01323
3 0.08192 0.00567
4 0.00512 0.03087
5 0.02048 0.01323

利⽤上⾯这个表,我们可以算出每轮抛掷中使⽤硬币1或者使⽤硬币2的概率。

⽐如第1轮,使⽤硬币1的概率是:

0.00512/(0.00512 + 0.03087) = 0.14

使⽤硬币2的概率是1-0.14=0.86

依次可以算出其他4轮的概率,如下:

轮数 \(z_i=\)硬币 1 \(z_i=\)硬币 2
1 0.14 0.86
2 0.61 0.39
3 0.94 0.06
4 0.14 0.86
5

0.61

0.39

上表中的右两列表示期望值。看第⼀⾏,0.86表示,从期望的⻆度看,这轮抛掷使⽤硬币2的概率是0.86。相⽐于前⾯ 的⽅法,我们按照最⼤似然概率,直接将第1轮估计为⽤的硬币2,此时的我们更加谨慎,我们只说,有0.14的概率是硬1,有0.86的概率是硬币2,不再是⾮此即彼。这样我们在估计P1或者P2时,就可以⽤上全部的数据,⽽不是部分的数据,显然这样会更好⼀些。

这⼀步,我们实际上是估计出了z的概率分布,这步被称作E步。

结合下表:

硬币 结果 统计
Unknown 正正反反正 3 正 - 2 反
Unknown 反反正正反 2 正 - 3 反
Unknown 正反反反反 1 正 - 4 反
Unknown 正反反正正 3 正 - 2 反
Unknown 反正正反反 2 正 - 3 反

我们按照期望最⼤似然概率的法则来估计新的P1和P2:

以P1估计为例,第1轮的3正2反相当于

  • 0.14*3=0.42正
  • 0.14*2=0.28反

依次算出其他四轮,列表如下:

轮数 正面 反面
1 0.42 0.28
2 1.22 1.83
3 0.94 3.76
4 0.42 0.28
5 1.22 1.83
总计 4.22 7.98

P1=4.22/(4.22+7.98)=0.35

可以看到,改变了z值的估计⽅法后,新估计出的P1要更加接近0.4。原因就是我们使⽤了所有抛掷的数据,⽽不是之前只使⽤了部分的数据。

这步中,我们根据E步中求出的z的概率分布,依据最⼤似然概率法则去估计P1和P2,被称作M步。

马尔科夫链

在机器学习算法中,⻢尔可夫链(Markov chain)是个很重要的概念。⻢尔可夫链(Markov chain),⼜称离散时间⻢尔 可夫链(discrete-time Markov chain,因俄国数学家安德烈·⻢尔可夫(俄语:Андрей Андреевич Марков)得名。

简介

⻢尔科夫链即为状态空间中从⼀个状态到另⼀个状态转换的随机过程。

该过程要求具备⽆记忆的性质:

  • 下⼀状态的概率分布只能由当前状态决定,在时间序列中它前⾯的事件均与之⽆关。这种特定类型的“⽆记忆性”称作⻢尔可夫性质

⻢尔科夫链作为实际过程的统计模型具有许多应⽤。

在⻢尔可夫链的每⼀步,系统根据概率分布,可以从⼀个状态变到另⼀个状态,也可以保持当前状态。

状态的改变叫做转移,与不同的状态改变相关的概率叫做转移概率。

⻢尔可夫链的数学表示为:

既然某⼀时刻状态转移的概率只依赖前⼀个状态,那么只要求出系统中任意两个状态之间的转移概率,这个⻢尔科夫链的模型就定了。

2 经典举例

下图中的⻢尔科夫链是⽤来表示股市模型,共有三种状态:⽜市(Bull market), 熊市(Bear market)和横盘(Stagnant market)。

每⼀个状态都以⼀定的概率转化到下⼀个状态。⽐如,⽜市以0.025的概率转化到横盘的状态。

这个状态概率转化图可以以矩阵的形式表示。

如果我们定义矩阵P某⼀位置P(i, j)的值为P(j|i),即从状态i变为状态j的概率。

另外定义⽜市、熊市、横盘的状态分别为0、1、2,这样我们得到了⻢尔科夫链模型的状态转移矩阵为:

这个状态转移矩阵P确定以后,整个股市模型就已经确定!

隐马尔可夫模型HMM

隐⻢尔可夫模型(Hidden Markov Model,HMM)是统计模型,它⽤来描述⼀个含有隐含未知参数的⻢尔可夫过程。

其难点是从可观察的参数中确定该过程的隐含参数。然后利⽤这些参数来作进⼀步的分析,例如模式识别。

简单案例

下⾯我们⼀起⽤⼀个简单的例⼦来阐述:

假设我⼿⾥有三个不同的骰⼦。

第⼀个骰⼦是我们平常⻅的骰⼦(称这个骰⼦为D6),6个⾯,每个⾯(1,2,3,4,5,6)出现的概率是1/6。

第⼆个骰⼦是个四⾯体(称这个骰⼦为D4),每个⾯(1,2,3,4)出现的概率是1/4。

第三个骰⼦有⼋个⾯(称这个骰⼦为D8),每个⾯(1,2,3,4,5,6,7,8)出现的概率是1/8。

我们开始掷骰⼦,我们先从三个骰⼦⾥挑⼀个,挑到每⼀个骰⼦的概率都是1/3。

然后我们掷骰⼦,得到⼀个数字,1,2,3,4,5,6,7,8中的⼀个。不停的重复上述过程,我们会得到⼀串数字,每个数字都是1,2,3,4,5,6,7,8中的⼀个。

例如我们可能得到这么⼀串数字(掷骰⼦10次):1 6 3 5 2 7 3 5 2 4

这串数字叫做可见状态链。

但是在隐⻢尔可夫模型中,我们不仅仅有这么⼀串可⻅状态链,还有⼀串隐含状态链

在这个例⼦⾥,这串隐含状态链就是你⽤的骰⼦的序列。

⽐如,隐含状态链有可能是:D6 D8 D8 D6 D4 D8 D6 D6 D4 D8

⼀般来说,HMM中说到的马尔可夫链其实是指隐含状态链,因为隐含状态(骰⼦)之间存在转换概率(transitionprobability)。

在我们这个例⼦⾥,D6的下⼀个状态是D4,D6,D8的概率都是1/3。D4,D8的下⼀个状态是D4,D6,D8的转换概率也都⼀样是1/3。

这样设定是为了最开始容易说清楚,但是我们其实是可以随意设定转换概率的。

  • ⽐如,我们可以这样定义,D6后⾯不能接D4,D6后⾯是D6的概率是0.9,是D8的概率是0.1。
  • 这样就是⼀个新的HMM。

同样的,尽管可⻅状态之间没有转换概率,但是隐含状态和可⻅状态之间有⼀个概率叫做输出概率(emissionprobability)。

  • 就我们的例⼦来说,六⾯骰(D6)产⽣1的输出概率是1/6。产⽣2,3,4,5,6的概率也都是1/6。
  • 我们同样可以对输出概率进⾏其他定义。⽐如,我有⼀个被赌场动过⼿脚的六⾯骰⼦,掷出来是1的概率更⼤,是1/2,掷出来是2,3,4,5,6的概率是1/10。

其实对于HMM来说,如果提前知道所有隐含状态之间的转换概率和所有隐含状态到所有可⻅状态之间的输出概率,做模拟是相当容易的。但是应⽤HMM模型时候呢,往往是缺失了⼀部分信息的。

  • 有时候你知道骰⼦有⼏种,每种骰⼦是什么,但是不知道掷出来的骰⼦序列;
  • 有时候你只是看到了很多次掷骰⼦的结果,剩下的什么都不知道。

如何应⽤算法去估计这些缺失的信息,就成了⼀个很重要的问题。这些算法我会在后⾯详细讲。

2 案例进阶

2.1 问题阐述

和HMM模型相关的算法主要分为三类,分别解决三种问题:

1)知道骰⼦有⼏种(隐含状态数量),每种骰⼦是什么(输出概率),根据掷骰⼦掷出的结果(可⻅状态链),我想知道每次掷出来的都是哪种骰⼦(隐含状态链)。

  • 这个问题呢,在语⾳识别领域呢,叫做解码问题。
  • 这个问题其实有两种解法,会给出两个不同的答案。每个答案都对,只不过这些答案的意义不⼀样。
    • 第⼀种解法求最⼤似然状态路径,说通俗点呢,就是我求⼀串骰⼦序列,这串骰⼦序列产⽣观测结果的概率最⼤。
    • 第⼆种解法呢,就不是求⼀组骰⼦序列了,⽽是求每次掷出的骰⼦分别是某种骰⼦的概率。⽐如说我看到结果后,我可以求得第⼀次掷骰⼦是D4的概率是0.5,D6的概率是0.3,D8的概率是0.2。

2)知道骰⼦有⼏种(隐含状态数量),每种骰⼦是什么(输出概率),根据掷骰⼦掷出的结果(可⻅状态链), 我想知道掷出这个结果的概率。

  • 看似这个问题意义不⼤,因为你掷出来的结果很多时候都对应了⼀个⽐较⼤的概率。
  • 问这个问题的⽬的呢,其实是检测观察到的结果和已知的模型是否吻合。
  • 如果很多次结果都对应了⽐较⼩的概率,那么就说明我们已知的模型很有可能是错的,有⼈偷偷把我们的骰⼦給换了。

3)知道骰⼦有⼏种(隐含状态数量),不知道每种骰⼦是什么(输出概率),观测到很多次掷骰⼦的结果(可⻅状态链),我想反推出每种骰⼦是什么(输出概率)。

  • 这个问题很重要,因为这是最常⻅的情况。
  • 很多时候我们只有可⻅结果,不知道HMM模型⾥的参数,我们需要从可⻅结果估计出这些参数,这是建模的⼀个必要步骤。

2.2 问题解决

2.2.1 ⼀个简单问题【对应问题⼆】

其实这个问题实⽤价值不⾼。由于对下⾯较难的问题有帮助,所以先在这⾥提⼀下。

  • 知道骰⼦有⼏种,每种骰⼦是什么,每次掷的都是什么骰⼦,根据掷骰⼦掷出的结果,求产⽣这个结果的概率。

解法⽆⾮就是概率相乘:

2.2.2 看见不可见的,破解骰⼦序列【对应问题⼀】

这⾥我说的是第⼀种解法,解最⼤似然路径问题。

举例来说,我知道我有三个骰⼦,六⾯骰,四⾯骰,⼋⾯骰。我也知道我掷了⼗次的结果(1 6 3 5 2 7 3 5 2 4),我不知道每次用了那种骰⼦,我想知道最有可能的骰⼦序列。

其实最简单⽽暴⼒的⽅法就是穷举所有可能的骰⼦序列,然后依照上⼀个问题的解法把每个序列对应的概率算出来。然后我们从⾥⾯把对应最⼤概率的序列挑出来就⾏了。

如果⻢尔可夫链不⻓,当然可⾏。如果⻓的话,穷举的数量太⼤,就很难完成了。

另外⼀种很有名的算法叫做维特比算法(Viterbi algorithm. 要理解这个算法,我们先看⼏个简单的列⼦。 ⾸先,如果我们只掷⼀次骰⼦:

看到结果为1.对应的最⼤概率骰⼦序列就是D4,因为D4产⽣1的概率是1/4,⾼于1/6和1/8.

把这个情况拓展,我们掷两次骰⼦:

结果为1,6.这时问题变得复杂起来,我们要计算三个值,分别是第⼆个骰⼦是D6,D4,D8的最⼤概率。显然,要取到最⼤概率,第⼀个骰⼦必须为D4。这时,第⼆个骰⼦取到D6的最⼤概率是:

同样的,我们可以计算第⼆个骰⼦是D4或D8时的最⼤概率。我们发现,第⼆个骰⼦取到D6的概率最⼤。⽽使这个概率最⼤时,第⼀个骰⼦为D4。所以最⼤概率骰⼦序列就是D4 D6。 继续拓展,我们掷三次骰⼦:

同样,我们计算第三个骰⼦分别是D6,D4,D8的最⼤概率。我们再次发现,要取到最⼤概率,第⼆个骰⼦必须为D6。

这时,第三个骰⼦取到D4的最⼤概率是:

同上,我们可以计算第三个骰⼦是D6或D8时的最⼤概率。我们发现,第三个骰⼦取到D4的概率最⼤。⽽使这个概率最⼤时,第⼆个骰⼦为D6,第⼀个骰⼦为D4。所以最⼤概率骰⼦序列就是D4 D6 D4。

写到这⾥,⼤家应该看出点规律了。既然掷骰⼦⼀、⼆、三次可以算,掷多少次都可以以此类推。

我们发现,我们要求最⼤概率骰⼦序列时要做这么⼏件事情。

  • ⾸先,不管序列多⻓,要从序列长度为1算起,算序列⻓度为1时取到每个骰⼦的最⼤概率。
  • 然后,逐渐增加⻓度,每增加⼀次⻓度,重新算⼀遍在这个⻓度下最后⼀个位置取到每个骰⼦的最⼤概率。因为上⼀个⻓度下的取到每个骰⼦的最⼤概率都算过了,重新计算的话其实不难。
  • 当我们算到最后⼀位时,就知道最后⼀位是哪个骰⼦的概率最⼤了。然后,我们要把对应这个最⼤概率的序列从后往前推出来。

2.2.3 谁动了我的骰⼦?【对应问题三】

⽐如说你怀疑⾃⼰的六⾯骰被赌场动过⼿脚了,有可能被换成另⼀种六⾯骰,这种六⾯骰掷出来是1的概率更⼤,是1/2,掷出来是2,3,4,5,6的概率是1/10。你怎么办么?

答案很简单,算⼀算正常的三个骰⼦掷出⼀段序列的概率,再算⼀算不正常的六⾯骰和另外两个正常骰⼦掷出这段序列的概率。如果前者⽐后者⼩,你就要⼩⼼了。

⽐如说掷骰⼦的结果是:

要算⽤正常的三个骰⼦掷出这个结果的概率,其实就是将所有可能情况的概率进⾏加和计算。

同样,简单⽽暴⼒的⽅法就是把穷举所有的骰⼦序列,还是计算每个骰⼦序列对应的概率,但是这回,我们不挑最⼤值了,⽽是把所有算出来的概率相加,得到的总概率就是我们要求的结果。这个⽅法依然不能应⽤于太⻓的骰⼦序列(⻢尔可夫链)。 我们会应⽤⼀个和前⼀个问题类似的解法,只不过前⼀个问题关⼼的是概率最⼤值,这个问题关⼼的是概率之和。解决这个问题的算法叫做前向算法(forward algorithm)。

⾸先,如果我们只掷⼀次骰⼦:

看到结果为1.产⽣这个结果的总概率可以按照如下计算,总概率为0.18:

把这个情况拓展,我们掷两次骰⼦:

看到结果为1,6.产⽣这个结果的总概率可以按照如下计算,总概率为0.05:

继续拓展,我们掷三次骰⼦:

看到结果为1,6,3.产⽣这个结果的总概率可以按照如下计算,总概率为0.03:

同样的,我们⼀步⼀步的算,有多⻓算多⻓,再⻓的⻢尔可夫链总能算出来的。

⽤同样的⽅法,也可以算出不正常的六⾯骰和另外两个正常骰⼦掷出这段序列的概率,然后我们⽐较⼀下这两个概率⼤⼩,就能知道你的骰⼦是不是被⼈换了。

1 什么样的问题需要HMM模型

⾸先我们来看看什么样的问题解决可以⽤HMM模型。使⽤HMM模型时我们的问题⼀般有这两个特征:

  • 1)我们的问题是基于序列的,⽐如时间序列,或者状态序列。
  • 2)我们的问题中有两类数据,
    • ⼀类序列数据是可以观测到的,即观测序列
    • ⽽另⼀类数据是不能观察到的,即隐藏状态序列,简称状态序列

有了这两个特征,那么这个问题⼀般可以⽤HMM模型来尝试解决。这样的问题在实际⽣活中是很多的。

⽐如:我现在给⼤家写课件,我在键盘上敲出来的⼀系列字符就是观测序列,⽽我实际想写的⼀段话就是隐藏状态序列,输⼊法的任务就是从敲⼊的⼀系列字符尽可能的猜测我要写的⼀段话,并把最可能的词语放在最前⾯让我选择,这就可以看做⼀个HMM模型了。

再举⼀个,假如我上课讲课,我发出的⼀串连续的声⾳就是观测序列,⽽我实际要表达的⼀段话就是隐藏状态序,你⼤脑的任务,就是从这⼀串连续的声⾳中判断出我最可能要表达的话的内容。

从这些例⼦中,我们可以发现,HMM模型可以⽆处不在。但是上⾯的描述还不精确,下⾯我们⽤精确的数学符号来表述我们的HMM模型。

HMM模型的定义

以下内容看着很绕,但是对着定义看,就很简单,或者抛开定义直接看后面的例子

对于HMM模型,⾸先我们假设Q是所有可能的隐藏状态的集合,V是所有可能的观测状态的集合,即:

  • Q = q1, q2, ..., qN
  • V = v1, v2, ...vM

其中,N是可能的隐藏状态数,M是所有的可能的观察状态数。

对于⼀个⻓度为T的序列,i是对应的状态序列, O是对应的观察序列,即:

  • i = i1,i2, ...,iT
  • O = o1, o2, ...oT

其中,任意⼀个隐藏状态it Q, 任意⼀个观察状态ot V

HMM模型做了两个很重要的假设如下:

1) 齐次马尔科夫链假设。

任意时刻的隐藏状态只依赖于它前⼀个隐藏状态。

  • 当然这样假设有点极端,因为很多时候我们的某⼀个隐藏状态不仅仅只依赖于前⼀个隐藏状态,可能是前两个 或者是前三个。
  • 但是这样假设的好处就是模型简单,便于求解。
  • 如果在时刻t的隐藏状态是i t = q i ,在时刻t + 1的隐藏状态是i t+1= q j , 则从时刻t到时刻t+1的HMM状态转移概率a ij 可以表示为:
  • 这样a ij  可以组成⻢尔科夫链的状态转移矩阵A:

2) 观测独立性假设。

即任意时刻的观察状态只仅仅依赖于当前时刻的隐藏状态,这也是⼀个为了简化模型的假设。

  • 如果在时刻t的隐藏状态是i t = q i , ⽽对应的观察状态为o t = v k , 则该时刻观察状态v k在隐藏状态q i下⽣成的概率为b j (k),满⾜:
  • 这样b (k)可以组成观测状态⽣成的概率矩阵B:
  • 除此之外,我们需要⼀组在时刻t=1的隐藏状态概率分布Π :

⼀个HMM模型,可以由隐藏状态初始概率分布Π , 状态转移概率矩阵A和观测状态概率矩阵B决定

Π和A决定状态序列,B决定观测序列。

因此,HMM模型可以由⼀个三元组λ 表示如下:

λ = (A, B, Π) = (状态序列,观测序列,初始状态概率分布)

3 ⼀个HMM模型实例

下⾯我们⽤⼀个简单的实例来描述上⾯抽象出的HMM模型。这是⼀个盒⼦与球的模型。

例⼦来源于李航的《统计学习⽅法》。

假设我们有3个盒⼦,每个盒⼦⾥都有红⾊和⽩⾊两种球,这三个盒⼦⾥球的数量分别是:

盒子 1 2 3
红球数 5 4 7
白球数 5 6 3

按照下⾯的⽅法从盒⼦⾥抽球,开始的时候,

  • 从第⼀个盒⼦抽球的概率是0.2,
  • 从第⼆个盒⼦抽球的概率是0.4,
  • 从第三个盒⼦抽球的概率是0.4。

以这个概率抽⼀次球后,将球放回。

然后从当前盒⼦转移到下⼀个盒⼦进⾏抽球。规则是:

  • 如果当前抽球的盒⼦是第⼀个盒⼦,则以0.5的概率仍然留在第⼀个盒⼦继续抽球,以0.2的概率去第⼆个盒⼦抽球,以0.3的概率去第三个盒⼦抽球。
  • 如果当前抽球的盒⼦是第⼆个盒⼦,则以0.5的概率仍然留在第⼆个盒⼦继续抽球,以0.3的概率去第⼀个盒⼦抽球,以0.2的概率去第三个盒⼦抽球。
  • 如果当前抽球的盒⼦是第三个盒⼦,则以0.5的概率仍然留在第三个盒⼦继续抽球,以0.2的概率去第⼀个盒⼦抽球,以0.3的概率去第⼆个盒⼦抽球。

如此下去,直到重复三次,得到⼀个球的颜⾊的观测序列:

O={红,⽩,红}

注意在这个过程中,观察者只能看到球的颜色序列,却不能看到球是从哪个盒⼦⾥取出的。

那么按照我们前⾯HMM模型的定义,我们的观察状态集合是:

V={红,⽩},M=2

我们的隐藏状态集合是:

Q={盒⼦1,盒⼦2,盒⼦3},N=3

⽽观察序列和状态序列的⻓度为3.

初始状态分布Π为:

状态转移概率分布A矩阵为:

观测状态概率B矩阵为:

4 HMM观测序列的生成

从上⾯的例⼦,我们也可以抽象出HMM观测序列⽣成的过程。

  • 输⼊的是HMM的模型λ = (A, B, Π),观测序列的⻓度T
  • 输出是观测序列O = o1, o2, ...oT

⽣成的过程如下:

  • 1)根据初始状态概率分布Π⽣成隐藏状态i1
  • 2) for t from 1 to T
    • 按照隐藏状态 it 的观测状态分布bit(k)⽣成观察状态ot
    • 按照隐藏状态 it 的状态转移概率分布 ait , 产⽣隐藏状态 it+1

所有的ot⼀起形成观测序列O = o1, o2, ...oT

5 HMM模型的三个基本问题

HMM模型⼀共有三个经典的问题需要解决:

1)评估观察序列概率 —— 前向后向的概率计算

  • 即给定模型λ = (A, B, Π)和观测序列O = {o1, o2, ...oT },计算在模型 λ 下某⼀个观测序列O出现的概率P(O|λ )。
  • 这个问题的求解需要⽤到前向后向算法,是HMM模型三个问题中最简单的。

2)预测问题,也称为解码问题 ——维特比(Viterbi)算法

  • 即给定模型λ = (A, B, Π)和观测序列O = {o1, o2, ...oT },求给定观测序列条件下,最可能出现的对应的状态序列。
  • 这个问题的求解需要⽤到基于动态规划的维特⽐算法,是HMM模型三个问题中复杂度居中的算法。

3)模型参数学习问题 —— 鲍姆-⻙尔奇(Baum-Welch)算法(状态未知) ,这是⼀个学习问题

  • 即给定观测序列O = {o1, o2, ...oT },估计模型λ = (A, B, Π)的参数,使该模型下观测序列的条件概率P(Oλ)最⼤。
  • 这个问题的求解需要⽤到基于EM算法的鲍姆-⻙尔奇算法,是HMM模型三个问题中最复杂的。

接下来的三节,我们将基于这个三个问题展开讨论。

⼩结

什么样的问题可以⽤HMM模型解决:

  • 基于序列的,⽐如时间序列;
  • 问题中包含两类数据,⼀类是可以观测到的观测序列;另⼀类是不能观察到的隐藏状态序列。

HMM模型的两个重要假设:

  • 齐次⻢尔科夫链假设
  • 观测独⽴性假设

HMM模型的三个基本问题:

  • 评估观察序列概率—— 前向后向的概率计算
  • 预测问题,也称为解码问题 ——维特比(Viterbi)算法
  • 模型参数学习问题 —— 鲍姆-⻙尔奇(Baum-Welch)算法

前向后向算法——评估观察序列概率

1 回顾HMM问题⼀:求观测序列的概率

⾸先我们回顾下HMM模型的问题⼀。这个问题是这样的。

我们已知HMM模型的参数λ = (A, B, Π)。

其中A是隐藏状态转移概率的矩阵,

B是观测状态⽣成概率的矩阵,

Π 是隐藏状态的初始概率分布。

同时我们也已经得到了观测序列O = {o1, o2, ...oT },

现在我们要求观测序列O在模型λ 下出现的条件概率P(Oλ)。

乍⼀看,这个问题很简单。因为我们知道所有的隐藏状态之间的转移概率和所有从隐藏状态到观测状态⽣成概率,那么我们是可以暴⼒求解的。

我们可以列举出所有可能出现的⻓度为T的隐藏序列i = {i1,i2, ...,iT },分别求出这些隐藏序列与观测序列O = {o1, o2, ...oT }的联合概率分布P(O,iλ),这样我们就可以很容易的求出边缘分布P(Oλ)了。

具体暴⼒求解的⽅法是这样的:

  • ⾸先,任意隐藏序列i = i1,i2, ...,iT 出现的概率是:

  • 对于固定的状态序列i = i1,i2, ...,iT,我们要求的观察序列O = o1, o2, ...oT 出现的概率是:

  • 则O和i联合出现的概率是:

  • 然后求边缘概率分布,即可得到观测序列O在模型λ 下出现的条件概率P(O|λ )P(O|λ ):

虽然上述⽅法有效,但是如果我们的隐藏状态数N⾮常多的那就麻烦了,此时我们预测状态有N 种组合,算法的时间复杂度是O(T N T)阶的。

因此对于⼀些隐藏状态数极少的模型,我们可以⽤暴⼒求解法来得到观测序列出现的概率,但是如果隐藏状态多,则上述算法太耗时,我们需要寻找其他简洁的算法。

前向后向算法就是来帮助我们在较低的时间复杂度情况下求解这个问题的。

2 前向算法求HMM观测序列的概率

前向后向算法是前向算法和后向算法的统称,这两个算法都可以⽤来求HMM观测序列的概率。我们先来看看前向算法是如何求解这个问题的。

2.1 流程梳理

前向算法本质上属于动态规划的算法,也就是我们要通过找到局部状态递推的公式,这样⼀步步的从⼦问题的最优解拓展到整个问题的最优解。

  • 在前向算法中,通过定义“前向概率”来定义动态规划的这个局部状态。
  • 什么是前向概率呢, 其实定义很简单:定义时刻t时隐藏状态为q i  , 观测状态的序列为o1 , o2 , ...ot 的概率为前向概率。

记为:

  • 既然是动态规划,我们就要递推了,现在假设我们已经找到了在时刻t时各个隐藏状态的前向概率,现在我们需要递推出时刻t+1时各个隐藏状态的前向概率。
  • 我们可以基于时刻t时各个隐藏状态的前向概率,再乘以对应的状态转移概率,即α t( j )a ji 就是在时刻t观测到的o1 , o 2, ...ot ,并且时刻t隐藏状态q j , 时刻t+1隐藏状态q i 的概率。
  • 如果将下⾯所有的对应的概率求和,即 就是在时刻t观测到o1 , o 2, ...ot  ,并且时刻t+1隐藏状态q i 的概率。

 

  • 继续⼀步,由于观测状态o 只依赖于t+1时刻隐藏状态q i , 这样就是在时刻t+1观测到o1 , o 2, ...ot  , o t+1,并且时刻t+1隐藏状态q i 的概率。
  • ⽽这个概率,恰恰就是时刻t+1对应的隐藏状态i的前向概率,这样我们得到了前向概率的递推关系式如下:

  • 我们的动态规划从时刻1开始,到时刻T结束,由于α ( i )表示在时刻T观测序列为o1 , o 2, ...oT  ,并且时刻T隐藏状态q i 的概率,我们只要将所有隐藏状态对应的概率相加,即就得到了在时刻T观测序列为o1 , o 2, ...ot  的概率。

2.2 算法总结。

  • 输⼊:HMM模型λ = (A, B, Π),观测序列O = (o1 , o 2, ...oT )
  • 输出:观测序列概率P(Oλ)
    • 1) 计算时刻1的各个隐藏状态前向概率:

    • 2) 递推时刻2,3,... ...T时刻的前向概率:

    • 3) 计算最终结果:

从递推公式可以看出,我们的算法时间复杂度是O(T N2),⽐暴⼒解法的时间复杂度O(T NT )少了⼏个数量级。

3 HMM前向算法求解实例

这⾥我们⽤前⾯盒⼦与球的例⼦来显示前向概率的计算。 我们的观察集合是:

我们的状态集合是:

⽽观察序列和状态序列的⻓度为3.

初始状态分布为:

状态转移概率分布矩阵为:

观测状态概率矩阵为:

球的颜⾊的观测序列:

按照我们上⼀节的前向算法。⾸先计算时刻1三个状态的前向概率:

时刻1是红⾊球,

  • 隐藏状态是盒⼦1的概率为:

  • 隐藏状态是盒⼦2的概率为:

  • 隐藏状态是盒⼦3的概率为:

现在我们可以开始递推了,⾸先递推时刻2三个状态的前向概率:

时刻2是⽩⾊球,

  • 隐藏状态是盒⼦1的概率为:

  • 隐藏状态是盒⼦2的概率为:

  • 隐藏状态是盒⼦3的概率为:

继续递推,现在我们递推时刻3三个状态的前向概率:

时刻3是红⾊球,

  • 隐藏状态是盒⼦1的概率为:

  • 隐藏状态是盒⼦2的概率为:

  • 隐藏状态是盒⼦3的概率为:

最终我们求出观测序列:O=红,⽩,红的概率为:

4 ⽤后向算法求HMM观测序列的概率

4.1 流程梳理

熟悉了⽤前向算法求HMM观测序列的概率,现在我们再来看看怎么⽤后向算法求HMM观测序列的概率。

后向算法和前向算法⾮常类似,都是⽤的动态规划,唯⼀的区别是选择的局部状态不同,后向算法⽤的是“后向概率”。

4.2 后向算法流程

以下是后向算法的流程,注意下和前向算法的相同点和不同点:

  • 输⼊:HMM模型λ = (A, B, Π),观测序列O = (o1, o2, ...oT)
  • 输出:观测序列概率P(Oλ)
    • 初始化时刻T的各个隐藏状态后向概率:

    • 递推时刻T−1,T−2,...1时刻的后向概率:

    • 计算最终结果:

此时我们的算法时间复杂度仍然是O(T N 2 )

5 ⼩结

前向算法求HMM观测序列

  • 输⼊:HMM模型λ = (A, B, Π),观测序列O = (o1, o2, ...oT)
  • 输出:观测序列概率P(Oλ)
    • 1) 计算时刻1的各个隐藏状态前向概率:

    • 2) 递推时刻2,3,... ...T时刻的前向概率:

    • 3) 计算最终结果:

后向算法求HMM观测序列

  • 输⼊:HMM模型λ = (A, B, Π),观测序列O = (o1, o2, ...oT)
  • 输出:观测序列概率P(Oλ)
    • 初始化时刻T的各个隐藏状态后向概率:

    • 递推时刻T−1,T−2,...1时刻的后向概率:

    • 计算最终结果:

维特比算法——解码隐藏状态序列

在本篇我们会讨论维特⽐算法解码隐藏状态序列,即给定模型和观测序列,求给定观测序列条件下,最可能出现的对应的隐藏状态序列。

HMM模型的解码问题最常⽤的算法是维特⽐算法,当然也有其他的算法可以求解这个问题。

同时维特⽐算法是⼀个通⽤的求序列最短路径的动态规划算法,也可以⽤于很多其他问题。

1 HMM最可能隐藏状态序列求解概述

HMM模型的解码问题即:

  • 给定模型λ = (A, B, Π)和观测序列O = o1, o2, ...oT ,求给定观测序列O条件下,最可能出现的对应的状态序列 ,即P(I O)的最⼤化。

⼀个可能的近似解法是求出观测序列O在每个时刻t最可能的隐藏状态 然后得到⼀个近似的隐藏状态序列。要这样近似求解不难,利⽤前向后向算法评估观察序列概率的定义:

  • 在给定模型λ和观测序列O时,在时刻t处于状态qi 的概率是,这个概率可以通过HMM的前向算法与后向算法计算。这样我们有:

近似算法很简单,但是却不能保证预测的状态序列整体是最可能的状态序列,因为预测的状态序列中某些相邻的隐藏状态可能存在转移概率为0的情况。

维特⽐算法可以将HMM的状态序列作为⼀个整体来考虑,避免近似算法的问题,下⾯我们来看看维特⽐算法进⾏HMM解码的⽅法。

2 维特⽐算法概述

维特⽐算法是⼀个通⽤的解码算法,是基于动态规划的求序列最短路径的⽅法。

既然是动态规划算法,那么就需要找到合适的局部状态,以及局部状态的递推公式。在HMM中,维特⽐算法定义了两个局部状态⽤于递推。

1) 第⼀个局部状态是在时刻t隐藏状态为i 所有可能的状态转移路径i1,i2, ...it中的概率最⼤值。

记为δt(i ):

δt(i )的定义可以得到δ 的递推表达式:

2) 第⼆个局部状态由第⼀个局部状态递推得到。

我们定义在时刻t隐藏状态为i的所有单个状态转移路径(i1,i2, ...,it−1,i )中概率最⼤的转移路径中第t-1个节点的隐藏状态为ψt(i )

其递推表达式可以表示为:

有了这两个局部状态,我们就可以从时刻0⼀直递推到时刻T,然后利⽤ψt(i )记录的前⼀个最可能的状态节点回溯,直到找到最优的隐藏状态序列。

3 维特⽐算法流程总结

现在我们来总结下维特⽐算法的流程:

  • 输⼊:HMM模型λ = (A, B, Π),观测序列O = (o1, o2, ...oT)
  • 输出:最有可能的隐藏状态序列

流程如下:

  • 1)初始化局部状态:

  • 2) 进⾏动态规划递推时刻t = 2, 3, ...T 时刻的局部状态:

  • 3) 计算时刻T最⼤的δT(i ),即为最可能隐藏状态序列出现的概率。计算时刻T最⼤的ψt(i ),即为时刻T最可能的隐藏状态。

  • 4) 利⽤局部状态ψt(i)开始回溯。对于t = T − 1, T − 2, ..., 1:

最终得到最有可能的隐藏状态序列

4 HMM维特比算法求解实例

下⾯我们仍然⽤盒⼦与球的例⼦来看看HMM维特⽐算法求解。 我们的观察集合是:

我们的状态集合是:

⽽观察序列和状态序列的⻓度为3.

初始状态分布为:

状态转移概率分布矩阵为:

观测状态概率矩阵为:

球的颜⾊的观测序列:

按照我们前⾯的维特⽐算法,⾸先需要得到三个隐藏状态在时刻1时对应的各⾃两个局部状态,此时观测状态为1:

现在开始递推三个隐藏状态在时刻2时对应的各⾃两个局部状态,此时观测状态为2:

继续递推三个隐藏状态在时刻3时对应的各⾃两个局部状态,此时观测状态为1:

此时已经到最后的时刻,我们开始准备回溯。此时最⼤概率为δ3(3),从⽽得到

由于ψ3(3) = 3,所以, ⽽⼜由于ψ2(3) = 3,所以。从⽽得到最终的最可能的隐藏状态序列为:(3,3,3)。

鲍姆-韦尔奇算法简介

模型参数学习问题 —— 鲍姆-韦尔奇(Baum-Welch)算法(状态未知) 

  • 即给定观测序列O = {o1, o2, ...oT },估计模型λ = (A, B, Π)的参数,使该模型下观测序列的条件概率P(Oλ)最⼤。
  • 它的解法最常⽤的是鲍姆-⻙尔奇算法,其实就是基于EM算法的求解,只不过鲍姆-⻙尔奇算法出现的时代,EM算法还没有被抽象出来,所以被叫为鲍姆-⻙尔奇算法。

2 鲍姆-⻙尔奇算法原理

鲍姆-⻙尔奇算法原理既然使⽤的就是EM算法的原理,

  • 那么我们需要在E步求出联合分布P(O,I|λ)基于条件概率的期望,其中λ为当前的模型参数。
  • 然后在M步最⼤化这个期望,得到更新的模型参数λ

接着不停的进⾏EM迭代,直到模型参数的值收敛为⽌。

⾸先来看看E步,当前模型参数为λ, 联合分布P(O, Iλ)基于条件概率的期望表达式为:

在M步,我们极⼤化上式,然后得到更新后的模型参数如下:

过不断的E步和M步的迭代,直到收敛

HMM模型API介绍

1 API的安装:

官⽹链接:https://hmmlearn.readthedocs.io/en/latest/

pip install hmmlearn

2 hmmlearn介绍

hmmlearn实现了三种HMM模型类,按照观测状态是连续状态还是离散状态,可以分为两类。

GaussianHMM和GMMHMM是连续观测状态的HMM模型,⽽MultinomialHMM是离散观测状态的模型,也是我们在HMM原理系列篇⾥⾯使⽤的模型。

在这⾥主要介绍我们前⾯⼀直讲的关于离散状态的MultinomialHMM模型。

  1. ​旧版本行为 (v0.2.0 之前):​

    • MultinomialHMM 实际上实现的是 ​​CategoricalHMM​​(单项分布),即:
      • 观测值是一个​​离散类别​​(如:红/白)
      • emissionprob_ 是一个形状为 (n_states, n_categories) 的矩阵,表示每个状态下观测类别的概率分布
  2. ​新版本行为 (v0.2.0 之后):​

    • MultinomialHMM 遵循​​标准的多项分布定义​​(维基百科),即:
      • 观测值是一个​​计数值向量​​(如:掷骰子100次后每个点数出现的次数)
      • emissionprob_ 是一个形状为 (n_states, n_features) 的矩阵,表示每个状态下​​多个独立试验结果​​的概率分布
    • 你的代码需要改为:
      • 使用 CategoricalHMM 处理 ​​离散类别​​ 数据
      • 仅当观测数据是 ​​计数向量​​ 时才使用 MultinomialHMM

注​​:新版 CategoricalHMM 的参数名与旧版 MultinomialHMM 完全兼容,你的代码无需其他修改。

对于MultinomialHMM(CategoricalHMM)的模型,使⽤⽐较简单,⾥⾯有⼏个常⽤的参数:

  • "startprob_"参数对应我们的隐藏状态初始分布Π,
  • "transmat_"对应我们的状态转移矩阵A,
  • "emissionprob_"对应我们的观测状态概率矩阵B。

3 MultinomialHMM实例

下⾯我们⽤我们在前⾯讲的关于球的那个例⼦使⽤MultinomialHMM跑⼀遍。

import numpy as np
from hmmlearn import hmm
# 设定 隐藏状态的集合
states = ["box1", "box2", "box3"]
n_states = len(states)
# 设定 观察状态的集合
observations = ["red", "white"]
n_observations = len(observations)
# 设定 初始状态分布
start_probability = np.array([0.2, 0.4, 0.4])
# 设定 状态转移概率分布矩阵
transition_probability = np.array([
    [0.5, 0.2, 0.3], 
    [0.3, 0.5, 0.2], 
    [0.2, 0.3, 0.5]])
# 设定 观测状态概率矩阵
emission_probability = np.array([
    [0.5, 0.5], 
    [0.4, 0.6], 
    [0.7, 0.3]])
# 设定模型参数
# 使用 CategoricalHMM 替代 MultinomialHMM
model=hmm.CategoricalHMM(
# model=hmm.MultinomialHMM(
                         n_components=n_states,
                         n_features=n_observations,  # 明确指定特征数量
                         init_params="",  # 禁用所有自动初始化
                         n_iter=0       # 不进行迭代训练
                         )
model.startprob_=start_probability#初始状态分布
model.transmat_=transition_probability#状态转移概率分布矩阵
model.emissionprob_=emission_probability#观测状态概率矩阵

现在我们来跑⼀跑HMM问题三维特⽐算法的解码过程,使⽤和之前⼀样的观测序列来解码,代码如下:

seen=np.array([[0],[1],[0]]).T# 设定观测序列
# 关键:必须先调用 fit() 才能使用模型
# 即使不改变参数,也需要用观测数据"拟合"一次
dummy_data = np.array([[0]]) 
model.fit(dummy_data)  # 完成模型初始化
box=model.predict(seen)
box#array([2, 2, 2], dtype=int64)注意,这里返回的是下标,其实对应结果是["box3", "box3", "box3"]

我们再来看看求HMM问题⼀的观测序列的概率的问题,代码如下:

# 求观测序列的概率
print(model.score(seen))#-2.038545309915233

 我们前面的案例中:最终我们求出观测序列:O=红,⽩,红的概率为:0.13022,为什么上面打印的结果是-2.038545309915233?
 要注意的是score函数返回的是以⾃然对数为底的对数概率值,我们在HMM问题⼀中⼿动计算的结果是未取对数的原始概率是0.13022。对⽐⼀下:

import math
math.exp(-2.038545309915233)
# ln0.13022≈−2.0385
# 输出结果是:0.13021800000000003 

 

posted @ 2025-06-16 21:07  指尖下的世界  阅读(53)  评论(0)    收藏  举报