一文搞懂HMM(隐马尔可夫模型)

一文搞懂HMM(隐马尔可夫模型)

什么是熵(Entropy)

简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度。熵越大,系统越无序,意味着系统结构和运动的不确定和无规则;反之,,熵越小,系统越有序,意味着具有确定和有规则的运动状态。熵的中文意思是热量被温度除的商。负熵是物质系统有序化,组织化,复杂化状态的一种度量。

熵最早来原于物理学. 德国物理学家鲁道夫·克劳修斯首次提出熵的概念,用来表示任何一种能量在空间中分布的均匀程度,能量分布得越均匀,熵就越大。

  1. 一滴墨水滴在清水中,部成了一杯淡蓝色溶液
  2. 热水晾在空气中,热量会传到空气中,最后使得温度一致

更多的一些生活中的例子:

  1. 熵力的一个例子是耳机线,我们将耳机线整理好放进口袋,下次再拿出来已经乱了。让耳机线乱掉的看不见的“力”就是熵力,耳机线喜欢变成更混乱。
  2. 熵力另一个具体的例子是弹性力。一根弹簧的力,就是熵力。 胡克定律其实也是一种熵力的表现。
  3. 万有引力也是熵力的一种(热烈讨论的话题)。
  4. 浑水澄清[1]

image

于是从微观看,熵就表现了这个系统所处状态的不确定性程度。香农,描述一个信息系统的时候就借用了熵的概念,这里熵表示的是这个信息系统的平均信息量(平均不确定程度)

最大熵模型

我们在投资时常常讲不要把所有的鸡蛋放在一个篮子里,这样可以降低风险。在信息处理中,这个原理同样适用。在数学上,这个原理称为最大熵原理(the maximum entropy principle)。

让我们看一个拼音转汉字的简单的例子。假如输入的拼音是"wang-xiao-bo",利用语言模型,根据有限的上下文(比如前两个词),我们能给出两个最常见的名字“王小波”和“王晓波 ”。至于要唯一确定是哪个名字就难了,即使利用较长的上下文也做不到。当然,我们知道如果通篇文章是介绍文学的,作家王小波的可能性就较大;而在讨论两岸关系时,台湾学者王晓波的可能性会较大。在上面的例子中,我们只需要综合两类不同的信息,即主题信息和上下文信息。虽然有不少凑合的办法,比如:分成成千上万种的不同的主题单独处理,或者对每种信息的作用加权平均等等,但都不能准确而圆满地解决问题,这样好比以前我们谈到的行星运动模型中的小圆套大圆打补丁的方法。在很多应用中,我们需要综合几十甚至上百种不同的信息,这种小圆套大圆的方法显然行不通。

数学上最漂亮的办法是最大熵(maximum entropy)模型,它相当于行星运动的椭圆模型。“最大熵”这个名词听起来很深奥,但是它的原理很简单,我们每天都在用。说白了,就是要保留全部的不确定性,将风险降到最小。

回到我们刚才谈到的拼音转汉字的例子,我们已知两种信息,第一,根据语言模型,wangxiao-bo可以被转换成王晓波和王小波;第二,根据主题,王小波是作家,《黄金时代》的作者等等,而王晓波是台湾研究两岸关系的学者。因此,我们就可以建立一个最大熵模型,同时满足这两种信息。现在的问题是,这样一个模型是否存在。匈牙利著名数学家、信息论最高奖香农奖得主希萨(Csiszar)证明,对任何一组不自相矛盾的信息,这个最大熵模型不仅存在,而且是唯一的。而且它们都有同一个非常简单的形式 -- 指数函数。下面公式是根据上下文(前两个词)和主题预测下一个词的最大熵模型,其中 w3 是要预测的词(王晓波或者王小波)w1 和 w2 是它的前两个字(比如说它们分别是“出版”,和“”),也就是其上下文的一个大致估计,subject 表示主题。

640_wx_fmt=png&tp=webp&wxfrom=5.webp

我们看到,在上面的公式中,有几个参数 lambda 和 Z ,他们需要通过观测数据训练出来。最大熵模型在形式上是最漂亮的统计模型,而在实现上是最复杂的模型之一。

我们上次谈到用最大熵模型可以将各种信息综合在一起。我们留下一个问题没有回答,就是如何构造最大熵模型。我们已经所有的最大熵模型都是指数函数的形式,现在只需要确定指数函数的参数就可以了,这个过程称为模型的训练。

最原始的最大熵模型的训练方法是一种称为通用迭代算法 GIS(generalized iterative scaling) 的迭代 算法。GIS 的原理并不复杂,大致可以概括为以下几个步骤: 
1. 假定第零次迭代的初始模型为等概率的均匀分布。 
2. 用第 N 次迭代的模型来估算每种信息特征在训练数据中的分布,如果超过了实际的,就把相应的模型参数变小;否则,将它们便大。 
3. 重复步骤 2 直到收敛。

GIS 最早是由 Darroch 和 Ratcliff 在七十年代提出的。但是,这两人没有能对这种算法的物理含义进行很好地解释。后来是由数学家希萨(Csiszar)解释清楚的,因此,人们在谈到这个算法时,总是同时引用 Darroch 和Ratcliff 以及希萨的两篇论文。GIS 算法每次迭代的时间都很长,需要迭代很多次才能收敛,而且不太稳定,即使在 64 位计算机上都会出现溢出。因此,在实际应用中很少有人真正使用 GIS。大家只是通过它来了解最大熵模型的算法。 
    八十年代,很有天才的孪生兄弟的达拉皮垂(Della Pietra)在 IBM 对 GIS 算法进行了两方面的改进,提出了改进迭代算法 IIS(improved iterative scaling)。这使得最大熵模型的训练时间缩短了一到两个数量级。这样最大熵模型才有可能变得实用。即使如此,在当时也只有 IBM 有条件是用最大熵模型。

由于最大熵模型在数学上十分完美,对科学家们有很大的诱惑力,因此不少研究者试图把自己的问题用一个类似最大熵的近似模型去套。谁知这一近似,最大熵模型就变得不完美了,结果可想而知,比打补丁的凑合的方法也好不了多少。于是,不少热心人又放弃了这种方法。第一个在实际信息处理应用中验证了最大熵模型的优势的,是宾夕法尼亚大学马库斯的另一个高徒原 IBM 现微软的研究员拉纳帕提(Adwait Ratnaparkhi)。拉纳帕提的聪明之处在于他没有对最大熵模型进行近似,而是找到了几个最适合用最大熵模型、而计算量相对不太大的自然语言处理问题,比如词性标注和句法分析。拉纳帕提成功地将上下文信息、词性(名词、动词和形容词等)、句子成分(主谓宾)通过最大熵模型结合起来,做出了当时世界上最好的词性标识系统和句法分析器。拉纳帕提的论文发表后让人们耳目一新。拉纳帕提的词性标注系统,至今仍然是使用单一方法最好的系统。科学家们从拉纳帕提的成就中,又看到了用最大熵模型解决复杂的文字信息处理的希望。

但是,最大熵模型的计算量仍然是个拦路虎。我在学校时花了很长时间考虑如何简化最大熵模型的计算量。终于有一天,我对我的导师说,我发现一种数学变换,可以将大部分最大熵模型的训练时间在 IIS 的基础上减少两个数量级。我在黑板上推导了一个多小时,他没有找出我的推导中的任何破绽,接着他又回去想了两天,然后告诉我我的算法是对的。从此,我们就建造了一些很大的最大熵模型。这些模型比修修补补的凑合的方法好不少。即使在我找到了快速训练算法以后,为了训练一个包含上下文信息,主题信息和语法信息的文法模型(language model),我并行使用了20 台当时最快的 SUN 工作站,仍然计算了三个月。由此可见最大熵模型的复杂的一面。

最大熵模型,可以说是集简与繁于一体,形式简单,实现复杂。值得一提的是,在Google的很多产品中,比如机器翻译,都直接或间接地用到了最大熵模型。 
     讲到这里,读者也许会问,当年最早改进最大熵模型算法的达拉皮垂兄弟这些年难道没有做任何事吗?他们在九十年代初贾里尼克离开 IBM 后,也退出了学术界,而到在金融界大显身手。他们两人和很多 IBM 语音识别的同事一同到了一家当时还不大,但现在是世界上最成功对冲基金(hedge fund)公司----文艺复兴技术公司 (Renaissance Technologies)。我们知道,决定股票涨落的因素可能有几十甚至上百种,而最大熵方法恰恰能找到一个同时满足成千上万种不同条件的模型。达拉皮垂兄弟等科学家在那里,用于最大熵模型和其他一些先进的数学工具对股票预测,获得了巨大的成功。从该基金 1988 年创立至今,它的净回报率高达平均每年 34%。也就是说,如果 1988 年你在该基金投入一块钱,今天你能得到 200 块钱。这个业绩,远远超过股神巴菲特的旗舰公司伯克夏哈撒韦(Berkshire Hathaway)。同期,伯克夏哈撒韦的总回报是 16 倍。 
    值得一提的是,信息处理的很多数学手段,包括隐含马尔可夫模型、子波变换、贝叶斯网络等等,在华尔街多有直接的应用。由此可见,数学模型的作用。

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。

image

假设我们开始掷骰子,我们先从三个骰子里挑一个,挑到每一个骰子的概率都是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中说到的马尔可夫链其实是指隐含状态链,因为隐含状态(骰子)之间存在转换概率(transition probability)。在我们这个例子里,D6的下一个状态是D4,D6,D8的概率都是1/3。D4,D8的下一个状态是D4,D6,D8的转换概率也都一样是1/3。这样设定是为了最开始容易说清楚,但是我们其实是可以随意设定转换概率的。比如,我们可以这样定义,D6后面不能接D4,D6后面是D6的概率是0.9,是D8的概率是0.1。这样就是一个新的HMM。

同样的,尽管可见状态之间没有转换概率,但是隐含状态和可见状态之间有一个概率叫做输出概率(emission probability)。就我们的例子来说,六面骰(D6)产生1的输出概率是1/6。产生2,3,4,5,6的概率也都是1/6。我们同样可以对输出概率进行其他定义。比如,我有一个被赌场动过手脚的六面骰子,掷出来是1的概率更大,是1/2,掷出来是2,3,4,5,6的概率是1/10。

image

image

其实对于HMM来说,如果提前知道所有隐含状态之间的转换概率和所有隐含状态到所有可见状态之间的输出概率,做模拟是相当容易的。但是应用HMM模型时候呢,往往是缺失了一部分信息的,有时候你知道骰子有几种,每种骰子是什么,但是不知道掷出来的骰子序列;有时候你只是看到了很多次掷骰子的结果,剩下的什么都不知道。如果应用算法去估计这些缺失的信息,就成了一个很重要的问题。这些算法我会在下面详细讲。

××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× 
      如果你只想看一个简单易懂的例子,就不需要往下看了。 
     ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× 
    说两句废话,答主认为呢,要了解一个算法,要做到以下两点:会其意,知其形。答主回答的,其实主要是第一点。但是这一点呢,恰恰是最重要,而且很多书上不会讲的。正如你在追一个姑娘,姑娘对你说“你什么都没做错!”你要是只看姑娘的表达形式呢,认为自己什么都没做错,显然就理解错了。你要理会姑娘的意思,“你赶紧给我道歉!”这样当你看到对应的表达形式呢,赶紧认错,跪地求饶就对了。数学也是一样,你要是不理解意思,光看公式,往往一头雾水。不过呢,数学的表达顶多也就是晦涩了点,姑娘的表达呢,有的时候就完全和本意相反。所以答主一直认为理解姑娘比理解数学难多了。

回到正题,和HMM模型相关的算法主要分为三类,分别解决三种问题: 
      1)知道骰子有几种(隐含状态数量),每种骰子是什么(转换概率),根据掷骰子掷出的结果(可见状态链),我想知道每次掷出来的都是哪种骰子(隐含状态链)。 
      这个问题呢,在语音识别领域呢,叫做解码问题。这个问题其实有两种解法,会给出两个不同的答案。每个答案都对,只不过这些答案的意义不一样。第一种解法求最大似然状态路径,说通俗点呢,就是我求一串骰子序列,这串骰子序列产生观测结果的概率最大。第二种解法呢,就不是求一组骰子序列了,而是求每次掷出的骰子分别是某种骰子的概率。比如说我看到结果后,我可以求得第一次掷骰子是D4的概率是0.5,D6的概率是0.3,D8的概率是0.2.第一种解法我会在下面说到,但是第二种解法我就不写在这里了,如果大家有兴趣,我们另开一个问题继续写吧。

2)还是知道骰子有几种(隐含状态数量),每种骰子是什么(转换概率),根据掷骰子掷出的结果(可见状态链),我想知道掷出这个结果的概率。 
      看似这个问题意义不大,因为你掷出来的结果很多时候都对应了一个比较大的概率。问这个问题的目的呢,其实是检测观察到的结果和已知的模型是否吻合。如果很多次结果都对应了比较小的概率,那么就说明我们已知的模型很有可能是错的,有人偷偷把我们的骰子給换了。

3)知道骰子有几种(隐含状态数量),不知道每种骰子是什么(转换概率),观测到很多次掷骰子的结果(可见状态链),我想反推出每种骰子是什么(转换概率)。 
      这个问题很重要,因为这是最常见的情况。很多时候我们只有可见结果,不知道HMM模型里的参数,我们需要从可见结果估计出这些参数,这是建模的一个必要步骤。

问题阐述完了,下面就开始说解法。(0号问题在上面没有提,只是作为解决上述问题的一个辅助) 
      0.一个简单问题 
其实这个问题实用价值不高。由于对下面较难的问题有帮助,所以先在这里提一下。 
知道骰子有几种,每种骰子是什么,每次掷的都是什么骰子,根据掷骰子掷出的结果,求产生这个结果的概率。

image

解法无非就是概率相乘: 


1.看见不可见的,破解骰子序列 
      这里我说的是第一种解法,解最大似然路径问题。 
      举例来说,我知道我有三个骰子,六面骰,四面骰,八面骰。我也知道我掷了十次的结果(1 6 3 5 2 7 3 5 2 4),我不知道每次用了那种骰子,我想知道最有可能的骰子序列。

其实最简单而暴力的方法就是穷举所有可能的骰子序列,然后依照第零个问题的解法把每个序列对应的概率算出来。然后我们从里面把对应最大概率的序列挑出来就行了。如果马尔可夫链不长,当然可行。如果长的话,穷举的数量太大,就很难完成了。 
      另外一种很有名的算法叫做Viterbi algorithm. 要理解这个算法,我们先看几个简单的列子。 
      首先,如果我们只掷一次骰子:

image

看到结果为1.对应的最大概率骰子序列就是D4,因为D4产生1的概率是1/4,高于1/6和1/8. 
      把这个情况拓展,我们掷两次骰子:

image

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


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

image

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


      同上,我们可以计算第三个骰子是D6或D8时的最大概率。我们发现,第三个骰子取到D4的概率最大。而使这个概率最大时,第二个骰子为D6,第一个骰子为D4。所以最大概率骰子序列就是D4 D6 D4。

写到这里,大家应该看出点规律了。既然掷骰子一二三次可以算,掷多少次都可以以此类推。我们发现,我们要求最大概率骰子序列时要做这么几件事情。首先,不管序列多长,要从序列长度为1算起,算序列长度为1时取到每个骰子的最大概率。然后,逐渐增加长度,每增加一次长度,重新算一遍在这个长度下最后一个位置取到每个骰子的最大概率。因为上一个长度下的取到每个骰子的最大概率都算过了,重新计算的话其实不难。当我们算到最后一位时,就知道最后一位是哪个骰子的概率最大了。然后,我们要把对应这个最大概率的序列从后往前推出来。 
2.谁动了我的骰子? 
      比如说你怀疑自己的六面骰被赌场动过手脚了,有可能被换成另一种六面骰,这种六面骰掷出来是1的概率更大,是1/2,掷出来是2,3,4,5,6的概率是1/10。你怎么办么?答案很简单,算一算正常的三个骰子掷出一段序列的概率,再算一算不正常的六面骰和另外两个正常骰子掷出这段序列的概率。如果前者比后者小,你就要小心了。 
      比如说掷骰子的结果是: 
image

要算用正常的三个骰子掷出这个结果的概率,其实就是将所有可能情况的概率进行加和计算。同样,简单而暴力的方法就是把穷举所有的骰子序列,还是计算每个骰子序列对应的概率,但是这回,我们不挑最大值了,而是把所有算出来的概率相加,得到的总概率就是我们要求的结果。这个方法依然不能应用于太长的骰子序列(马尔可夫链)。 
      我们会应用一个和前一个问题类似的解法,只不过前一个问题关心的是概率最大值,这个问题关心的是概率之和。解决这个问题的算法叫做前向算法(forward algorithm)。 
首先,如果我们只掷一次骰子:

image

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

image

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

image

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

image

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

image

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

image

同样的,我们一步一步的算,有多长算多长,再长的马尔可夫链总能算出来的。用同样的方法,也可以算出不正常的六面骰和另外两个正常骰子掷出这段序列的概率,然后我们比较一下这两个概率大小,就能知道你的骰子是不是被人换了。

Viterbi algorithm

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

任何一个HMM都可以通过下列五元组来描述:

:param obs:观测序列
:param states:隐状态
:param start_p:初始概率(隐状态)
:param trans_p:转移概率(隐状态)
:param emit_p: 发射概率 (隐状态表现为显状态的概率)

6cbb8645gw1egs40a3bpmj208n09574o

伪码如下:

复制代码
states = ('Rainy', 'Sunny')
 
observations = ('walk', 'shop', 'clean')
 
start_probability = {'Rainy': 0.6, 'Sunny': 0.4}
 
transition_probability = {
    'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},
    'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},
    }
 
emission_probability = {
    'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},
    'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},
}
复制代码

求解最可能的天气

求解最可能的隐状态序列是HMM的三个典型问题之一,通常用维特比算法解决。维特比算法就是求解HMM上的最短路径(-log(prob),也即是最大概率)的算法。

稍微用中文讲讲思路,很明显,第一天天晴还是下雨可以算出来:

  1. 定义V[时间][今天天气] = 概率,注意今天天气指的是,前几天的天气都确定下来了(概率最大)今天天气是X的概率,这里的概率就是一个累乘的概率了。

  2.     因为第一天我的朋友去散步了,所以第一天下雨的概率V[第一天][下雨] = 初始概率[下雨] * 发射概率[下雨][散步] = 0.6 * 0.1 = 0.06,同理可得V[第一天][天晴] = 0.24 。从直觉上来看,因为第一天朋友出门了,她一般喜欢在天晴的时候散步,所以第一天天晴的概率比较大,数字与直觉统一了。

  3. 从第二天开始,对于每种天气Y,都有前一天天气是X的概率 * X转移到Y的概率 * Y天气下朋友进行这天这种活动的概率。因为前一天天气X有两种可能,所以Y的概率有两个,选取其中较大一个作为V[第二天][天气Y]的概率,同时将今天的天气加入到结果序列中

  4. 比较V[最后一天][下雨]和[最后一天][天晴]的概率,找出较大的哪一个对应的序列,就是最终结果。

算法的代码可以在github上看到,地址为:

https://github.com/hankcs/Viterbi

运行完成后根据Viterbi得到结果:

Sunny Rainy Rainy

Viterbi被广泛应用到分词,词性标注等应用场景。


转载:http://www.cnblogs.com/skyme/p/4651331.html





第二篇

假设我们已经有一个特定的隐马尔科夫模型 λ 和一个可观察状态序列集。我们也许想知道在所有可能的隐藏状态序列下,给定的可观察状态序列的概率。当给定如下一个隐藏状态序列:

  那么在 HMM 和这个隐藏状态序列的条件下,可观察状态序列的概率为:

  而隐藏状态序列在 HMM 条件下的概率为:

  因此,隐藏状态序列和可观察状态序列的联合概率为:

  那么所有可能的隐藏状态序列上,可观察状态序列的概率为:

  例如,我们也许有一个海藻的“Summer”模型和一个“Winter”模型,因为海藻在夏天和冬天的状态应该是不同的,我们希望根据一个可观察状态(海藻的潮湿与否)序列来判断现在是夏天还是冬天。

  我们可以使用前向算法来计算在某个特定的 HMM 下一个可观察状态序列的概率,然后据此找到最可能的模型。

  这种类型的应用通常出现在语音设别中,通常我们会使用很多 HMM,每一个针对一个特别的单词。一个可观察状态的序列是从一个可以听到的单词向前得到的,然后这个单词就可以通过找到满足这个可观察状态序列的最大概率的 HMM 来识别。

  下面介绍一下前向算法 (Forward Algorithm)

  如何计算一个可观察序列的概率?

  1. 穷举搜索

  给定一个 HMM,我们想计算出某个可观察序列的概率。考虑天气的例子,我们知道一个描述天气和海藻状态的 HMM,而且我们还有一个海藻状态的序列。假设这个状态中的某三天是(dry,damp,soggy),在这三天中的每一天,天气都可能是晴朗,多云或者下雨,我们可以用下图来描述观察序列和隐藏序列:

  在这个图中的每一列表示天气的状态可能,并且每个状态都指向相邻的列的每个状态,每个状态转换在状态转移矩阵中都有一个概率。每一列的下面是当天的可观察的海藻的状态,在每种状态下出现这种可观察状态的概率是由混淆矩阵给出的。

  一个可能的计算可观察概率的方法是找到每一个可能的隐藏状态的序列,这里有3= 27种,这个时候的可观察序列的概率就是 Pr(dry, damp, soggy | HMM)=Pr(dry, damp, soggy | sunny, sunny, sunny) + . . . . + Pr(dry, damp, soggy | rainy, rainy, rainy)。

  很显然,这种计算的效率非常低,尤其是当模型中的状态非常多或者序列很长的时候。事实上,我们可以利用概率不随时间变化这个假设来降低时间的开销。

  2. 使用递归来降低复杂度

  我们可以考虑给定 HMM 的情况下,递归的计算一个可观察序列的概率。我们可以首先定义一个部分概率,表示达到某个中间状态的概率。接下来我们将看到这些部分概率是如何 在time=1 和 time = n (n > 1) 的时候计算的。

  假设一个T时间段的可观察序列是:

  1) 部分概率

  下面这张图表示了一个观察序列(dry,damp,soggy)的一阶转移

  我们可以通过计算到达某个状态的所有路径的概率和来计算到达某个中间状态的概率。比如说,t=2时刻,cloudy的概率用三条路径的概率之和来表示:

  我们用 αt(j) 来表示在 t 时刻是状态 j 的概率,αt(j)=Pr(观察状态 | 隐藏状态 j ) x Pr(t 时刻到达状态 j 的所有路径)。

  最后一个观察状态的部分概率就表示了整个序列最后达到某个状态的所有可能的路径的概率和,比如说在这个例子中,最后一列的部分状态是通过下列路径计算得到的:

  因为最后一列的部分概率是所有可能的路径的概率和,所以就是这个观察序列在给定 HMM 下的概率了。

  2) 计算 t=1时候的部分概率

  当 t=1 的时候,没有路径到某个状态,所以这里是初始概率,Pr(状态 j | t=0) = π(状态 j ),这样我们就可以计算 t=1 时候的部分概率为:

  因为在初始的时候,状态 j 的概率不仅和这个状态本身相关,还和观察状态有关,所以这里用到了混淆矩阵的值,k1 表示第一个观察状态,bjk1 表示隐藏状态是 j,但是观察成 k1 的概率。

  3) 计算 t>1 时候的部分概率

  还是看计算部分概率的公式是:αt(j) = Pr(观察状态 | 隐藏状态 j) x Pr(t 时刻到达状态 j 的所有路径)。 这个公式的左边是从混淆矩阵中已知的,我只需要计算右边部分,很显然右边是所有路径的和:

  需要计算的路径数是和观察序列的长度的平方相关的,但是 t 时刻的部分概率已经计算过了之前的所有路径,所以在 t+1 时刻只需要根据 t 时刻的概率来计算就可以了:

  这里简单解释下,bjk(t+1) 就是在 t+1 时刻的第 j 个隐藏状态被认为是当前的观察状态的概率,后面一部分是所有t时刻的隐藏状态到 t+1 时候的隐藏状态j的转移的概率的和。这样我们每一步的计算都可以利用上一步的结果,节省了很多时间。

  4) 公式推导

 

  5) 降低计算复杂度

  我们可以比较穷举和递归算法的复杂度。假设有一个 HMM,其中有 n 个隐藏状态,我们有一个长度为 T 的观察序列。

  穷举算法的需要计算所有可能的隐藏序列:

  需要计算:

  很显然穷举算法的时间开销是和 T 指数相关的,即 NT,而如果采用递归算法,由于我们每一步都可以利用上一步的结果,所以是和 T 线性相关的,即复杂度是 N2T。

  这里我们的目的是在某个给定的 HMM 下,计算出某个可观察序列的概率。我们通过先计算部分概率的方式递归的计算整个序列的所有路径的概率,大大节省了时间。在 t=1 的时候,使用了初始概率和混淆矩阵的概率,而在t时刻的概率则可以利用 t-1 时刻的结果。

  这样我们就可以用递归的方式来计算所有可能的路径的概率和,最后,所有的部分概率的计算公式为

  使用天气的例子,计算 t=2 时刻的 cloudy 状态的概率方法如图:

  我们使用前向算法在给定的一个 HMM 下计算某个可观察序列的概率。前向算法主要采用的是递归的思想,利用之前的计算结果。有了这个算法,我们就可以在一堆 HMM 中,找到一个最满足当前的可观察序列的模型(前向算法计算出来的概率最大)。

  (二) 根据可观察状态的序列找到一个最可能的隐藏状态序列

  和上面一个问题相似的并且更有趣的是根据可观察序列找到隐藏序列。在很多情况下,我们对隐藏状态更有兴趣,因为其包含了一些不能被直接观察到的有价值的信息。比如说在海藻和天气的例子中,一个隐居的人只能看到海藻的状态,但是他想知道天气的状态。这时候我们就可以使用 Viterbi 算法来根据可观察序列得到最优可能的隐藏状态的序列,当然前提是已经有一个 HMM

  另一个广泛使用 Viterbi 算法的领域是自然语言处理中的词性标注。句子中的单词是可以观察到的,词性是隐藏的状态。通过根据语句的上下文找到一句话中的单词序列的最有可能的隐藏状态序列,我们就可以得到一个单词的词性(可能性最大)。这样我们就可以用这种信息来完成其他一些工作。

  下面介绍一下维特比算法 (Viterbi Algorithm)

  一.如何找到可能性最大的隐藏状态序列?

  通常我们都有一个特定的 HMM,然后根据一个可观察状态序列去找到最可能生成这个可观察状态序列的隐藏状态序列。

  1. 穷举搜索

  我们可以在下图中看到每个隐藏状态和可观察状态的关系。

  通过计算所有可能的隐藏序列的概率,我们可以找到一个可能性最大的隐藏序列,这个可能性最大的隐藏序列最大化了 Pr(观察序列 | 隐藏状态集)。比如说,对于上图中的可观察序列 (dry damp soggy),最可能的隐藏序列就是下面这些概率中最大的:

  Pr(dry, damp, soggy | sunny, sunny, sunny), ……,Pr(dry, damp, soggy | rainy, rainy, rainy)

  这个方法是可行的,但是计算代价很高。和前向算法一样,我们可以利用转移概率在时间上的不变性来降低计算的复杂度。

  2. 使用递归降低复杂度

  在给定了一个可观察序列和HMM的情况下,我们可以考虑递归的来寻找最可能的隐藏序列。我们可以先定义一个部分概率 δ,即到达某个中间状态的概率。接下来我们将讨论如何计算 t=1 和 t=n (n>1) 的部分概率。

  注意这里的部分概率和前向算法中的部分概率是不一样的,这里的部分概率表示的是在t时刻最可能到达某个状态的一条路径的概率,而不是所有概率之和

  1) 部分概率和部分最优路径

  考虑下面这个图以及可观察序列 (dry, damp, soggy) 的一阶转移

  对于每一个中间状态和终止状态 (t=3) 都有一个最可能的路径。比如说,在 t=3 时刻的三个状态都有一个如下的最可能的路径:

  我们可以称这些路径为部分最优路径。这些部分最优路径都有一个概率,也就是部分概率 δ。和前向算法中的部分概率不一样,这里的概率只是一个最可能路径的概率,而不是所有路径的概率和。

  我们可以用 δ(i, t) 来表示在t时刻,到状态i的所有可能的序列(路径)中概率最大的序列的概率,部分最优路径就是达到这个最大概率的路径,对于每一个时刻的每一个状态都有这样一个概率和部分最优路径。

  最后,我们通过计算 t=T 时刻的每一个状态的最大概率和部分最优路径,选择其中概率最大的状态和它的部分最优路径来得到全局的最优路径。

  2) 计算 t=1 时刻的部分概率

  当 t=1 时刻的时候,到达某个状态最大可能的路径还不存在,但是我们可以直接使用在 t=1 时刻某个状态的概率和这个状态到可观察序列 k的转移概率:

  3) 计算 t>1 时刻的部分概率

  接下来我们可以根据 t-1 时刻的部分概率来求 t 时刻的部分概率

  我们可以计算所有到状态 X 的路径的概率,找到其中最可能的路径,也就是局部最优路径。注意到这里,到达X的路径必然会经过 t-1 时刻的 A、B 和 C,所以我们可以利用之前的结果。达到X的最可能的路径就是下面三个之一:

  (状态序列),. . .,A,X (状态序列),. . .,B,X (状态序列),. . .,C,X

  我们需要做的就是找到以 AX、BX 和 CX 结尾的路径中概率最大的那个。

  根据一阶马尔科夫的假设,一个状态的发生之和之前的一个状态有关系,所以X在某个序列的最后发生的概率只依赖于其之前的一个状态:

Pr (到达A的最优路径) . Pr (X | A) . Pr (观察状态 | X)

  有个了这个公式,我们就可以利用t-1时刻的结果和状态转移矩阵和混淆矩阵的数据:

  将上面这个表达式推广一下,就可以得到 t 时刻可观察状态为 k的第 i 个状态的最大部分概率的计算公式:

  其中 aji 表示从状态 j 转移到状态 i 的概率,bikt 表示状态i被观察成 kt 的概率。

  4) 后向指针

  考虑下图

  在每一个中间状态和结束状态都有一个部分最优概率 δ(i, t)。但是我们的目的是找到最可能的隐藏状态序列,所以我们需要一个方法去记住部分最优路径的每一个节点。

  考虑到要计算 t 时刻的部分概率,我们只需要知道 t-1 时刻的部分概率,所以我们只需要记录那个导致了 t 时刻最大部分概率的的状态,也就是说,在任意时刻,系统都必须处在一个能在下一时刻产生最大部分概率的状态。如下图所示:

  我们可以利用一个后向指针 φ 来记录导致某个状态最大局部概率的前一个状态,即

  这里 argmax 表示能最大化后面公式的j值,同样可以发现这个公式和 t-1 时刻的部分概率和转移概率有关,因为后向指针只是为了找到“我从哪里来”,这个问题和可观察状态没有关系,所以这里不需要再乘上混淆矩阵因子。全局的行为如下图所示:

  5) 优点

  使用 viterbi 算法对一个可观察状态进行解码有两个重要的优点:

  a) 通过使用递归来减少复杂度,这点和之前的前向算法是一样的

  b) 可以根据可观察序列找到最优的隐藏序列,这个的计算公式是:

其中 

  这里就是一个从左往右翻译的过程,通过前面的翻译结果得到后面的结果,起始点是初始向量 π。

  3. 补充

  但在序列某个地方有噪声干扰的时候,某些方法可能会和正确答案相差的较远。但是 Viterbi 算法会查看整个序列来决定最可能的终止状态,然后通过后向指针来找到之前的状态,这对忽略孤立的噪声非常有用。

  Viterbi 算法提供了一个根据可观察序列计算隐藏序列的很高效的方法,它利用递归来降低计算复杂度,并且使用之前全部的序列来做判断,可以很好的容忍噪声。

  在计算的过程中,这个算法计算每一个时刻每一个状态的部分概率,并且使用一个后向指针来记录达到当前状态的最大可能的上一个状态。最后,最可能的终止状态就是隐藏序列的最后一个状态,然后通过后向指针来查找整个序列的全部状态。

  (三) 根据观察到的序列集来找到一个最有可能的 HMM。 

  在很多实际的情况下,HMM 不能被直接的判断,这就变成了一个学习问题,因为对于给定的可观察状态序列 O 来说,没有任何一种方法可以精确地找到一组最优的 HMM 参数 λ 使 P(O | λ) 最大,于是人们寻求使其局部最优的解决办法,而前向后向算法(也称为Baum-Welch算法)就成了 HMM学习问题的一个近似的解决方法。

  前向后向算法首先对于 HMM 的参数进行一个初始的估计,但这个很可能是一个错误的猜测,然后通过对于给定的数据评估这些参数的的有效性并减少它们所引起的错误来更新 HMM 参数,使得和给定的训练数据的误差变小,这其实是机器学习中的梯度下降的思想。

  对于网格中的每一个状态,前向后向算法既计算到达此状态的“前向”概率,又计算生成此模型最终状态的“后向”概率,这些概率都可以通过前面的介绍利用递归进行高效计算。可以通过利用近似的 HMM 模型参数来提高这些中间概率从而进行调整,而这些调整又形成了前向后向算法迭代的基础。

  另外,前向后向算法是 EM 算法的一个特例,它避免了 EM 算法的暴力计算,而采用动态规划思想来解决问题,Jelinek 在其书《Statistical Methods for Speech Recognition》中对前向后向算法与 EM 算法的关系进行了详细描述,有兴趣的读者可以参考这本书。

  类似于上面讲到的前向算法,我们也可以定义后向变量 βt(i) 来计算给定当前隐藏状态 i 时,部分观察序列 ot+1,ot+2,…,oT的概率,即:

  与前向算法类似,我们也可以通过迭代算法有效计算 βt(i),计算公式如下:

  其中

  进一步我们可以发现

  因此

  下面开始介绍前向后向算法

  首先我们需要定义两个辅助变量,这两个变量可以用前文介绍过的前向变量和后向变量进行定义。

  第一个变量定义为 t 时状态 i 和 t+1 时状态 j 的概率,即

  该变量在网格中所代表的关系如下图所示:

  

  该等式等价于

  利用前向变量和后向变量,上式可以表示为

  第二个变量定义为后验概率,也就是在给定观察状态序列和 HMM 的情况下,t 时状态 i 的概率,即

  利用前向变量和后向变量,上式可以表示为

  因此,下式为在任意时刻状态 i 的期望,也就是从状态 i 转移到观察状态 o 的期望

  同样,下式也就是从状态 i 转移到状态 j 的期望

  我们可以发现定义的这两个变量之间的关系为

  下面介绍前向后向算法的参数学习过程,在学习的过程中,不断更新 HMM 的参数,从而使得 P(O | λ) 最大。我们假设初始的 HMM 参数为  λ={ π, A, B },首先计算前向变量 α 和后向变量 β,再根据刚刚介绍的公式计算期望 ξ 和 ζ,最后,根据下面的3个重估计公式更新 HMM 参数。

  如果我们定义当前的 HMM 模型为 λ={ π,A,B },那么可以利用该模型计算上面三个式子的右端;我们再定义重新估计的 HMM 模型为,那么上面三个式子的左端就是重估的 HMM 模型参数。Baum 及他的同事在70年代证明了,因此如果我们迭代地计算上面三个式子,由此不断地重新估计 HMM 的参数,那么在多次迭代后可以得到 HMM 模型的一个最大似然估计。不过需要注意的是,前向后向算法所得的这个最大似然估计是一个局部最优解。

  参考资料:

  1. http://blog.csdn.net/eaglex/article/details/6376826

  2. http://en.wikipedia.org/wiki/Markov_chain

  3. http://en.wikipedia.org/wiki/Hidden_Markov_model

  4. Lawrence R. Rabiner, A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition. Proceedings of the IEEE, 77 (2), p. 257–286, February 1989.

  5. L. R. Rabiner and B. H. Juang, “An introduction to HMMs,” IEEE ASSP Mag., vol. 3, no. 1, pp. 4-16, 1986.

  6. http://jedlik.phy.bme.hu/~gerjanos/HMM/node2.html

  7. http://www.cs.brown.edu/research/ai/dynamics/tutorial/Documents/HiddenMarkovModels.html

  8. 隐马尔可夫模型简介,刘群


转载:

假设我们已经有一个特定的隐马尔科夫模型 λ 和一个可观察状态序列集。我们也许想知道在所有可能的隐藏状态序列下,给定的可观察状态序列的概率。当给定如下一个隐藏状态序列:

  那么在 HMM 和这个隐藏状态序列的条件下,可观察状态序列的概率为:

  而隐藏状态序列在 HMM 条件下的概率为:

  因此,隐藏状态序列和可观察状态序列的联合概率为:

  那么所有可能的隐藏状态序列上,可观察状态序列的概率为:

  例如,我们也许有一个海藻的“Summer”模型和一个“Winter”模型,因为海藻在夏天和冬天的状态应该是不同的,我们希望根据一个可观察状态(海藻的潮湿与否)序列来判断现在是夏天还是冬天。

  我们可以使用前向算法来计算在某个特定的 HMM 下一个可观察状态序列的概率,然后据此找到最可能的模型。

  这种类型的应用通常出现在语音设别中,通常我们会使用很多 HMM,每一个针对一个特别的单词。一个可观察状态的序列是从一个可以听到的单词向前得到的,然后这个单词就可以通过找到满足这个可观察状态序列的最大概率的 HMM 来识别。

  下面介绍一下前向算法 (Forward Algorithm)

  如何计算一个可观察序列的概率?

  1. 穷举搜索

  给定一个 HMM,我们想计算出某个可观察序列的概率。考虑天气的例子,我们知道一个描述天气和海藻状态的 HMM,而且我们还有一个海藻状态的序列。假设这个状态中的某三天是(dry,damp,soggy),在这三天中的每一天,天气都可能是晴朗,多云或者下雨,我们可以用下图来描述观察序列和隐藏序列:

  在这个图中的每一列表示天气的状态可能,并且每个状态都指向相邻的列的每个状态,每个状态转换在状态转移矩阵中都有一个概率。每一列的下面是当天的可观察的海藻的状态,在每种状态下出现这种可观察状态的概率是由混淆矩阵给出的。

  一个可能的计算可观察概率的方法是找到每一个可能的隐藏状态的序列,这里有3= 27种,这个时候的可观察序列的概率就是 Pr(dry, damp, soggy | HMM)=Pr(dry, damp, soggy | sunny, sunny, sunny) + . . . . + Pr(dry, damp, soggy | rainy, rainy, rainy)。

  很显然,这种计算的效率非常低,尤其是当模型中的状态非常多或者序列很长的时候。事实上,我们可以利用概率不随时间变化这个假设来降低时间的开销。

  2. 使用递归来降低复杂度

  我们可以考虑给定 HMM 的情况下,递归的计算一个可观察序列的概率。我们可以首先定义一个部分概率,表示达到某个中间状态的概率。接下来我们将看到这些部分概率是如何 在time=1 和 time = n (n > 1) 的时候计算的。

  假设一个T时间段的可观察序列是:

  1) 部分概率

  下面这张图表示了一个观察序列(dry,damp,soggy)的一阶转移

  我们可以通过计算到达某个状态的所有路径的概率和来计算到达某个中间状态的概率。比如说,t=2时刻,cloudy的概率用三条路径的概率之和来表示:

  我们用 αt(j) 来表示在 t 时刻是状态 j 的概率,αt(j)=Pr(观察状态 | 隐藏状态 j ) x Pr(t 时刻到达状态 j 的所有路径)。

  最后一个观察状态的部分概率就表示了整个序列最后达到某个状态的所有可能的路径的概率和,比如说在这个例子中,最后一列的部分状态是通过下列路径计算得到的:

  因为最后一列的部分概率是所有可能的路径的概率和,所以就是这个观察序列在给定 HMM 下的概率了。

  2) 计算 t=1时候的部分概率

  当 t=1 的时候,没有路径到某个状态,所以这里是初始概率,Pr(状态 j | t=0) = π(状态 j ),这样我们就可以计算 t=1 时候的部分概率为:

  因为在初始的时候,状态 j 的概率不仅和这个状态本身相关,还和观察状态有关,所以这里用到了混淆矩阵的值,k1 表示第一个观察状态,bjk1 表示隐藏状态是 j,但是观察成 k1 的概率。

  3) 计算 t>1 时候的部分概率

  还是看计算部分概率的公式是:αt(j) = Pr(观察状态 | 隐藏状态 j) x Pr(t 时刻到达状态 j 的所有路径)。 这个公式的左边是从混淆矩阵中已知的,我只需要计算右边部分,很显然右边是所有路径的和:

  需要计算的路径数是和观察序列的长度的平方相关的,但是 t 时刻的部分概率已经计算过了之前的所有路径,所以在 t+1 时刻只需要根据 t 时刻的概率来计算就可以了:

  这里简单解释下,bjk(t+1) 就是在 t+1 时刻的第 j 个隐藏状态被认为是当前的观察状态的概率,后面一部分是所有t时刻的隐藏状态到 t+1 时候的隐藏状态j的转移的概率的和。这样我们每一步的计算都可以利用上一步的结果,节省了很多时间。

  4) 公式推导

 

  5) 降低计算复杂度

  我们可以比较穷举和递归算法的复杂度。假设有一个 HMM,其中有 n 个隐藏状态,我们有一个长度为 T 的观察序列。

  穷举算法的需要计算所有可能的隐藏序列:

  需要计算:

  很显然穷举算法的时间开销是和 T 指数相关的,即 NT,而如果采用递归算法,由于我们每一步都可以利用上一步的结果,所以是和 T 线性相关的,即复杂度是 N2T。

  这里我们的目的是在某个给定的 HMM 下,计算出某个可观察序列的概率。我们通过先计算部分概率的方式递归的计算整个序列的所有路径的概率,大大节省了时间。在 t=1 的时候,使用了初始概率和混淆矩阵的概率,而在t时刻的概率则可以利用 t-1 时刻的结果。

  这样我们就可以用递归的方式来计算所有可能的路径的概率和,最后,所有的部分概率的计算公式为

  使用天气的例子,计算 t=2 时刻的 cloudy 状态的概率方法如图:

  我们使用前向算法在给定的一个 HMM 下计算某个可观察序列的概率。前向算法主要采用的是递归的思想,利用之前的计算结果。有了这个算法,我们就可以在一堆 HMM 中,找到一个最满足当前的可观察序列的模型(前向算法计算出来的概率最大)。

  (二) 根据可观察状态的序列找到一个最可能的隐藏状态序列

  和上面一个问题相似的并且更有趣的是根据可观察序列找到隐藏序列。在很多情况下,我们对隐藏状态更有兴趣,因为其包含了一些不能被直接观察到的有价值的信息。比如说在海藻和天气的例子中,一个隐居的人只能看到海藻的状态,但是他想知道天气的状态。这时候我们就可以使用 Viterbi 算法来根据可观察序列得到最优可能的隐藏状态的序列,当然前提是已经有一个 HMM

  另一个广泛使用 Viterbi 算法的领域是自然语言处理中的词性标注。句子中的单词是可以观察到的,词性是隐藏的状态。通过根据语句的上下文找到一句话中的单词序列的最有可能的隐藏状态序列,我们就可以得到一个单词的词性(可能性最大)。这样我们就可以用这种信息来完成其他一些工作。

  下面介绍一下维特比算法 (Viterbi Algorithm)

  一.如何找到可能性最大的隐藏状态序列?

  通常我们都有一个特定的 HMM,然后根据一个可观察状态序列去找到最可能生成这个可观察状态序列的隐藏状态序列。

  1. 穷举搜索

  我们可以在下图中看到每个隐藏状态和可观察状态的关系。

  通过计算所有可能的隐藏序列的概率,我们可以找到一个可能性最大的隐藏序列,这个可能性最大的隐藏序列最大化了 Pr(观察序列 | 隐藏状态集)。比如说,对于上图中的可观察序列 (dry damp soggy),最可能的隐藏序列就是下面这些概率中最大的:

  Pr(dry, damp, soggy | sunny, sunny, sunny), ……,Pr(dry, damp, soggy | rainy, rainy, rainy)

  这个方法是可行的,但是计算代价很高。和前向算法一样,我们可以利用转移概率在时间上的不变性来降低计算的复杂度。

  2. 使用递归降低复杂度

  在给定了一个可观察序列和HMM的情况下,我们可以考虑递归的来寻找最可能的隐藏序列。我们可以先定义一个部分概率 δ,即到达某个中间状态的概率。接下来我们将讨论如何计算 t=1 和 t=n (n>1) 的部分概率。

  注意这里的部分概率和前向算法中的部分概率是不一样的,这里的部分概率表示的是在t时刻最可能到达某个状态的一条路径的概率,而不是所有概率之和

  1) 部分概率和部分最优路径

  考虑下面这个图以及可观察序列 (dry, damp, soggy) 的一阶转移

  对于每一个中间状态和终止状态 (t=3) 都有一个最可能的路径。比如说,在 t=3 时刻的三个状态都有一个如下的最可能的路径:

  我们可以称这些路径为部分最优路径。这些部分最优路径都有一个概率,也就是部分概率 δ。和前向算法中的部分概率不一样,这里的概率只是一个最可能路径的概率,而不是所有路径的概率和。

  我们可以用 δ(i, t) 来表示在t时刻,到状态i的所有可能的序列(路径)中概率最大的序列的概率,部分最优路径就是达到这个最大概率的路径,对于每一个时刻的每一个状态都有这样一个概率和部分最优路径。

  最后,我们通过计算 t=T 时刻的每一个状态的最大概率和部分最优路径,选择其中概率最大的状态和它的部分最优路径来得到全局的最优路径。

  2) 计算 t=1 时刻的部分概率

  当 t=1 时刻的时候,到达某个状态最大可能的路径还不存在,但是我们可以直接使用在 t=1 时刻某个状态的概率和这个状态到可观察序列 k的转移概率:

  3) 计算 t>1 时刻的部分概率

  接下来我们可以根据 t-1 时刻的部分概率来求 t 时刻的部分概率

  我们可以计算所有到状态 X 的路径的概率,找到其中最可能的路径,也就是局部最优路径。注意到这里,到达X的路径必然会经过 t-1 时刻的 A、B 和 C,所以我们可以利用之前的结果。达到X的最可能的路径就是下面三个之一:

  (状态序列),. . .,A,X (状态序列),. . .,B,X (状态序列),. . .,C,X

  我们需要做的就是找到以 AX、BX 和 CX 结尾的路径中概率最大的那个。

  根据一阶马尔科夫的假设,一个状态的发生之和之前的一个状态有关系,所以X在某个序列的最后发生的概率只依赖于其之前的一个状态:

Pr (到达A的最优路径) . Pr (X | A) . Pr (观察状态 | X)

  有个了这个公式,我们就可以利用t-1时刻的结果和状态转移矩阵和混淆矩阵的数据:

  将上面这个表达式推广一下,就可以得到 t 时刻可观察状态为 k的第 i 个状态的最大部分概率的计算公式:

  其中 aji 表示从状态 j 转移到状态 i 的概率,bikt 表示状态i被观察成 kt 的概率。

  4) 后向指针

  考虑下图

  在每一个中间状态和结束状态都有一个部分最优概率 δ(i, t)。但是我们的目的是找到最可能的隐藏状态序列,所以我们需要一个方法去记住部分最优路径的每一个节点。

  考虑到要计算 t 时刻的部分概率,我们只需要知道 t-1 时刻的部分概率,所以我们只需要记录那个导致了 t 时刻最大部分概率的的状态,也就是说,在任意时刻,系统都必须处在一个能在下一时刻产生最大部分概率的状态。如下图所示:

  我们可以利用一个后向指针 φ 来记录导致某个状态最大局部概率的前一个状态,即

  这里 argmax 表示能最大化后面公式的j值,同样可以发现这个公式和 t-1 时刻的部分概率和转移概率有关,因为后向指针只是为了找到“我从哪里来”,这个问题和可观察状态没有关系,所以这里不需要再乘上混淆矩阵因子。全局的行为如下图所示:

  5) 优点

  使用 viterbi 算法对一个可观察状态进行解码有两个重要的优点:

  a) 通过使用递归来减少复杂度,这点和之前的前向算法是一样的

  b) 可以根据可观察序列找到最优的隐藏序列,这个的计算公式是:

其中 

  这里就是一个从左往右翻译的过程,通过前面的翻译结果得到后面的结果,起始点是初始向量 π。

  3. 补充

  但在序列某个地方有噪声干扰的时候,某些方法可能会和正确答案相差的较远。但是 Viterbi 算法会查看整个序列来决定最可能的终止状态,然后通过后向指针来找到之前的状态,这对忽略孤立的噪声非常有用。

  Viterbi 算法提供了一个根据可观察序列计算隐藏序列的很高效的方法,它利用递归来降低计算复杂度,并且使用之前全部的序列来做判断,可以很好的容忍噪声。

  在计算的过程中,这个算法计算每一个时刻每一个状态的部分概率,并且使用一个后向指针来记录达到当前状态的最大可能的上一个状态。最后,最可能的终止状态就是隐藏序列的最后一个状态,然后通过后向指针来查找整个序列的全部状态。

  (三) 根据观察到的序列集来找到一个最有可能的 HMM。 

  在很多实际的情况下,HMM 不能被直接的判断,这就变成了一个学习问题,因为对于给定的可观察状态序列 O 来说,没有任何一种方法可以精确地找到一组最优的 HMM 参数 λ 使 P(O | λ) 最大,于是人们寻求使其局部最优的解决办法,而前向后向算法(也称为Baum-Welch算法)就成了 HMM学习问题的一个近似的解决方法。

  前向后向算法首先对于 HMM 的参数进行一个初始的估计,但这个很可能是一个错误的猜测,然后通过对于给定的数据评估这些参数的的有效性并减少它们所引起的错误来更新 HMM 参数,使得和给定的训练数据的误差变小,这其实是机器学习中的梯度下降的思想。

  对于网格中的每一个状态,前向后向算法既计算到达此状态的“前向”概率,又计算生成此模型最终状态的“后向”概率,这些概率都可以通过前面的介绍利用递归进行高效计算。可以通过利用近似的 HMM 模型参数来提高这些中间概率从而进行调整,而这些调整又形成了前向后向算法迭代的基础。

  另外,前向后向算法是 EM 算法的一个特例,它避免了 EM 算法的暴力计算,而采用动态规划思想来解决问题,Jelinek 在其书《Statistical Methods for Speech Recognition》中对前向后向算法与 EM 算法的关系进行了详细描述,有兴趣的读者可以参考这本书。

  类似于上面讲到的前向算法,我们也可以定义后向变量 βt(i) 来计算给定当前隐藏状态 i 时,部分观察序列 ot+1,ot+2,…,oT的概率,即:

  与前向算法类似,我们也可以通过迭代算法有效计算 βt(i),计算公式如下:

  其中

  进一步我们可以发现

  因此

  下面开始介绍前向后向算法

  首先我们需要定义两个辅助变量,这两个变量可以用前文介绍过的前向变量和后向变量进行定义。

  第一个变量定义为 t 时状态 i 和 t+1 时状态 j 的概率,即

  该变量在网格中所代表的关系如下图所示:

  

  该等式等价于

  利用前向变量和后向变量,上式可以表示为

  第二个变量定义为后验概率,也就是在给定观察状态序列和 HMM 的情况下,t 时状态 i 的概率,即

  利用前向变量和后向变量,上式可以表示为

  因此,下式为在任意时刻状态 i 的期望,也就是从状态 i 转移到观察状态 o 的期望

  同样,下式也就是从状态 i 转移到状态 j 的期望

  我们可以发现定义的这两个变量之间的关系为

  下面介绍前向后向算法的参数学习过程,在学习的过程中,不断更新 HMM 的参数,从而使得 P(O | λ) 最大。我们假设初始的 HMM 参数为  λ={ π, A, B },首先计算前向变量 α 和后向变量 β,再根据刚刚介绍的公式计算期望 ξ 和 ζ,最后,根据下面的3个重估计公式更新 HMM 参数。

  如果我们定义当前的 HMM 模型为 λ={ π,A,B },那么可以利用该模型计算上面三个式子的右端;我们再定义重新估计的 HMM 模型为,那么上面三个式子的左端就是重估的 HMM 模型参数。Baum 及他的同事在70年代证明了,因此如果我们迭代地计算上面三个式子,由此不断地重新估计 HMM 的参数,那么在多次迭代后可以得到 HMM 模型的一个最大似然估计。不过需要注意的是,前向后向算法所得的这个最大似然估计是一个局部最优解。

  参考资料:

  1. http://blog.csdn.net/eaglex/article/details/6376826

  2. http://en.wikipedia.org/wiki/Markov_chain

  3. http://en.wikipedia.org/wiki/Hidden_Markov_model

  4. Lawrence R. Rabiner, A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition. Proceedings of the IEEE, 77 (2), p. 257–286, February 1989.

  5. L. R. Rabiner and B. H. Juang, “An introduction to HMMs,” IEEE ASSP Mag., vol. 3, no. 1, pp. 4-16, 1986.

  6. http://jedlik.phy.bme.hu/~gerjanos/HMM/node2.html

  7. http://www.cs.brown.edu/research/ai/dynamics/tutorial/Documents/HiddenMarkovModels.html

  8. 隐马尔可夫模型简介,刘群


http://blog.csdn.net/likelet/article/details/7056068

假设我们已经有一个特定的隐马尔科夫模型 λ 和一个可观察状态序列集。我们也许想知道在所有可能的隐藏状态序列下,给定的可观察状态序列的概率。当给定如下一个隐藏状态序列:

  那么在 HMM 和这个隐藏状态序列的条件下,可观察状态序列的概率为:

  而隐藏状态序列在 HMM 条件下的概率为:

  因此,隐藏状态序列和可观察状态序列的联合概率为:

  那么所有可能的隐藏状态序列上,可观察状态序列的概率为:

  例如,我们也许有一个海藻的“Summer”模型和一个“Winter”模型,因为海藻在夏天和冬天的状态应该是不同的,我们希望根据一个可观察状态(海藻的潮湿与否)序列来判断现在是夏天还是冬天。

  我们可以使用前向算法来计算在某个特定的 HMM 下一个可观察状态序列的概率,然后据此找到最可能的模型。

  这种类型的应用通常出现在语音设别中,通常我们会使用很多 HMM,每一个针对一个特别的单词。一个可观察状态的序列是从一个可以听到的单词向前得到的,然后这个单词就可以通过找到满足这个可观察状态序列的最大概率的 HMM 来识别。

  下面介绍一下前向算法 (Forward Algorithm)

  如何计算一个可观察序列的概率?

  1. 穷举搜索

  给定一个 HMM,我们想计算出某个可观察序列的概率。考虑天气的例子,我们知道一个描述天气和海藻状态的 HMM,而且我们还有一个海藻状态的序列。假设这个状态中的某三天是(dry,damp,soggy),在这三天中的每一天,天气都可能是晴朗,多云或者下雨,我们可以用下图来描述观察序列和隐藏序列:

  在这个图中的每一列表示天气的状态可能,并且每个状态都指向相邻的列的每个状态,每个状态转换在状态转移矩阵中都有一个概率。每一列的下面是当天的可观察的海藻的状态,在每种状态下出现这种可观察状态的概率是由混淆矩阵给出的。

  一个可能的计算可观察概率的方法是找到每一个可能的隐藏状态的序列,这里有3= 27种,这个时候的可观察序列的概率就是 Pr(dry, damp, soggy | HMM)=Pr(dry, damp, soggy | sunny, sunny, sunny) + . . . . + Pr(dry, damp, soggy | rainy, rainy, rainy)。

  很显然,这种计算的效率非常低,尤其是当模型中的状态非常多或者序列很长的时候。事实上,我们可以利用概率不随时间变化这个假设来降低时间的开销。

  2. 使用递归来降低复杂度

  我们可以考虑给定 HMM 的情况下,递归的计算一个可观察序列的概率。我们可以首先定义一个部分概率,表示达到某个中间状态的概率。接下来我们将看到这些部分概率是如何 在time=1 和 time = n (n > 1) 的时候计算的。

  假设一个T时间段的可观察序列是:

  1) 部分概率

  下面这张图表示了一个观察序列(dry,damp,soggy)的一阶转移

  我们可以通过计算到达某个状态的所有路径的概率和来计算到达某个中间状态的概率。比如说,t=2时刻,cloudy的概率用三条路径的概率之和来表示:

  我们用 αt(j) 来表示在 t 时刻是状态 j 的概率,αt(j)=Pr(观察状态 | 隐藏状态 j ) x Pr(t 时刻到达状态 j 的所有路径)。

  最后一个观察状态的部分概率就表示了整个序列最后达到某个状态的所有可能的路径的概率和,比如说在这个例子中,最后一列的部分状态是通过下列路径计算得到的:

  因为最后一列的部分概率是所有可能的路径的概率和,所以就是这个观察序列在给定 HMM 下的概率了。

  2) 计算 t=1时候的部分概率

  当 t=1 的时候,没有路径到某个状态,所以这里是初始概率,Pr(状态 j | t=0) = π(状态 j ),这样我们就可以计算 t=1 时候的部分概率为:

  因为在初始的时候,状态 j 的概率不仅和这个状态本身相关,还和观察状态有关,所以这里用到了混淆矩阵的值,k1 表示第一个观察状态,bjk1 表示隐藏状态是 j,但是观察成 k1 的概率。

  3) 计算 t>1 时候的部分概率

  还是看计算部分概率的公式是:αt(j) = Pr(观察状态 | 隐藏状态 j) x Pr(t 时刻到达状态 j 的所有路径)。 这个公式的左边是从混淆矩阵中已知的,我只需要计算右边部分,很显然右边是所有路径的和:

  需要计算的路径数是和观察序列的长度的平方相关的,但是 t 时刻的部分概率已经计算过了之前的所有路径,所以在 t+1 时刻只需要根据 t 时刻的概率来计算就可以了:

  这里简单解释下,bjk(t+1) 就是在 t+1 时刻的第 j 个隐藏状态被认为是当前的观察状态的概率,后面一部分是所有t时刻的隐藏状态到 t+1 时候的隐藏状态j的转移的概率的和。这样我们每一步的计算都可以利用上一步的结果,节省了很多时间。

  4) 公式推导

 

  5) 降低计算复杂度

  我们可以比较穷举和递归算法的复杂度。假设有一个 HMM,其中有 n 个隐藏状态,我们有一个长度为 T 的观察序列。

  穷举算法的需要计算所有可能的隐藏序列:

  需要计算:

  很显然穷举算法的时间开销是和 T 指数相关的,即 NT,而如果采用递归算法,由于我们每一步都可以利用上一步的结果,所以是和 T 线性相关的,即复杂度是 N2T。

  这里我们的目的是在某个给定的 HMM 下,计算出某个可观察序列的概率。我们通过先计算部分概率的方式递归的计算整个序列的所有路径的概率,大大节省了时间。在 t=1 的时候,使用了初始概率和混淆矩阵的概率,而在t时刻的概率则可以利用 t-1 时刻的结果。

  这样我们就可以用递归的方式来计算所有可能的路径的概率和,最后,所有的部分概率的计算公式为

  使用天气的例子,计算 t=2 时刻的 cloudy 状态的概率方法如图:

  我们使用前向算法在给定的一个 HMM 下计算某个可观察序列的概率。前向算法主要采用的是递归的思想,利用之前的计算结果。有了这个算法,我们就可以在一堆 HMM 中,找到一个最满足当前的可观察序列的模型(前向算法计算出来的概率最大)。

  (二) 根据可观察状态的序列找到一个最可能的隐藏状态序列

  和上面一个问题相似的并且更有趣的是根据可观察序列找到隐藏序列。在很多情况下,我们对隐藏状态更有兴趣,因为其包含了一些不能被直接观察到的有价值的信息。比如说在海藻和天气的例子中,一个隐居的人只能看到海藻的状态,但是他想知道天气的状态。这时候我们就可以使用 Viterbi 算法来根据可观察序列得到最优可能的隐藏状态的序列,当然前提是已经有一个 HMM

  另一个广泛使用 Viterbi 算法的领域是自然语言处理中的词性标注。句子中的单词是可以观察到的,词性是隐藏的状态。通过根据语句的上下文找到一句话中的单词序列的最有可能的隐藏状态序列,我们就可以得到一个单词的词性(可能性最大)。这样我们就可以用这种信息来完成其他一些工作。

  下面介绍一下维特比算法 (Viterbi Algorithm)

  一.如何找到可能性最大的隐藏状态序列?

  通常我们都有一个特定的 HMM,然后根据一个可观察状态序列去找到最可能生成这个可观察状态序列的隐藏状态序列。

  1. 穷举搜索

  我们可以在下图中看到每个隐藏状态和可观察状态的关系。

  通过计算所有可能的隐藏序列的概率,我们可以找到一个可能性最大的隐藏序列,这个可能性最大的隐藏序列最大化了 Pr(观察序列 | 隐藏状态集)。比如说,对于上图中的可观察序列 (dry damp soggy),最可能的隐藏序列就是下面这些概率中最大的:

  Pr(dry, damp, soggy | sunny, sunny, sunny), ……,Pr(dry, damp, soggy | rainy, rainy, rainy)

  这个方法是可行的,但是计算代价很高。和前向算法一样,我们可以利用转移概率在时间上的不变性来降低计算的复杂度。

  2. 使用递归降低复杂度

  在给定了一个可观察序列和HMM的情况下,我们可以考虑递归的来寻找最可能的隐藏序列。我们可以先定义一个部分概率 δ,即到达某个中间状态的概率。接下来我们将讨论如何计算 t=1 和 t=n (n>1) 的部分概率。

  注意这里的部分概率和前向算法中的部分概率是不一样的,这里的部分概率表示的是在t时刻最可能到达某个状态的一条路径的概率,而不是所有概率之和

  1) 部分概率和部分最优路径

  考虑下面这个图以及可观察序列 (dry, damp, soggy) 的一阶转移

  对于每一个中间状态和终止状态 (t=3) 都有一个最可能的路径。比如说,在 t=3 时刻的三个状态都有一个如下的最可能的路径:

  我们可以称这些路径为部分最优路径。这些部分最优路径都有一个概率,也就是部分概率 δ。和前向算法中的部分概率不一样,这里的概率只是一个最可能路径的概率,而不是所有路径的概率和。

  我们可以用 δ(i, t) 来表示在t时刻,到状态i的所有可能的序列(路径)中概率最大的序列的概率,部分最优路径就是达到这个最大概率的路径,对于每一个时刻的每一个状态都有这样一个概率和部分最优路径。

  最后,我们通过计算 t=T 时刻的每一个状态的最大概率和部分最优路径,选择其中概率最大的状态和它的部分最优路径来得到全局的最优路径。

  2) 计算 t=1 时刻的部分概率

  当 t=1 时刻的时候,到达某个状态最大可能的路径还不存在,但是我们可以直接使用在 t=1 时刻某个状态的概率和这个状态到可观察序列 k的转移概率:

  3) 计算 t>1 时刻的部分概率

  接下来我们可以根据 t-1 时刻的部分概率来求 t 时刻的部分概率

  我们可以计算所有到状态 X 的路径的概率,找到其中最可能的路径,也就是局部最优路径。注意到这里,到达X的路径必然会经过 t-1 时刻的 A、B 和 C,所以我们可以利用之前的结果。达到X的最可能的路径就是下面三个之一:

  (状态序列),. . .,A,X (状态序列),. . .,B,X (状态序列),. . .,C,X

  我们需要做的就是找到以 AX、BX 和 CX 结尾的路径中概率最大的那个。

  根据一阶马尔科夫的假设,一个状态的发生之和之前的一个状态有关系,所以X在某个序列的最后发生的概率只依赖于其之前的一个状态:

Pr (到达A的最优路径) . Pr (X | A) . Pr (观察状态 | X)

  有个了这个公式,我们就可以利用t-1时刻的结果和状态转移矩阵和混淆矩阵的数据:

  将上面这个表达式推广一下,就可以得到 t 时刻可观察状态为 k的第 i 个状态的最大部分概率的计算公式:

  其中 aji 表示从状态 j 转移到状态 i 的概率,bikt 表示状态i被观察成 kt 的概率。

  4) 后向指针

  考虑下图

  在每一个中间状态和结束状态都有一个部分最优概率 δ(i, t)。但是我们的目的是找到最可能的隐藏状态序列,所以我们需要一个方法去记住部分最优路径的每一个节点。

  考虑到要计算 t 时刻的部分概率,我们只需要知道 t-1 时刻的部分概率,所以我们只需要记录那个导致了 t 时刻最大部分概率的的状态,也就是说,在任意时刻,系统都必须处在一个能在下一时刻产生最大部分概率的状态。如下图所示:

  我们可以利用一个后向指针 φ 来记录导致某个状态最大局部概率的前一个状态,即

  这里 argmax 表示能最大化后面公式的j值,同样可以发现这个公式和 t-1 时刻的部分概率和转移概率有关,因为后向指针只是为了找到“我从哪里来”,这个问题和可观察状态没有关系,所以这里不需要再乘上混淆矩阵因子。全局的行为如下图所示:

  5) 优点

  使用 viterbi 算法对一个可观察状态进行解码有两个重要的优点:

  a) 通过使用递归来减少复杂度,这点和之前的前向算法是一样的

  b) 可以根据可观察序列找到最优的隐藏序列,这个的计算公式是:

其中 

  这里就是一个从左往右翻译的过程,通过前面的翻译结果得到后面的结果,起始点是初始向量 π。

  3. 补充

  但在序列某个地方有噪声干扰的时候,某些方法可能会和正确答案相差的较远。但是 Viterbi 算法会查看整个序列来决定最可能的终止状态,然后通过后向指针来找到之前的状态,这对忽略孤立的噪声非常有用。

  Viterbi 算法提供了一个根据可观察序列计算隐藏序列的很高效的方法,它利用递归来降低计算复杂度,并且使用之前全部的序列来做判断,可以很好的容忍噪声。

  在计算的过程中,这个算法计算每一个时刻每一个状态的部分概率,并且使用一个后向指针来记录达到当前状态的最大可能的上一个状态。最后,最可能的终止状态就是隐藏序列的最后一个状态,然后通过后向指针来查找整个序列的全部状态。

  (三) 根据观察到的序列集来找到一个最有可能的 HMM。 

  在很多实际的情况下,HMM 不能被直接的判断,这就变成了一个学习问题,因为对于给定的可观察状态序列 O 来说,没有任何一种方法可以精确地找到一组最优的 HMM 参数 λ 使 P(O | λ) 最大,于是人们寻求使其局部最优的解决办法,而前向后向算法(也称为Baum-Welch算法)就成了 HMM学习问题的一个近似的解决方法。

  前向后向算法首先对于 HMM 的参数进行一个初始的估计,但这个很可能是一个错误的猜测,然后通过对于给定的数据评估这些参数的的有效性并减少它们所引起的错误来更新 HMM 参数,使得和给定的训练数据的误差变小,这其实是机器学习中的梯度下降的思想。

  对于网格中的每一个状态,前向后向算法既计算到达此状态的“前向”概率,又计算生成此模型最终状态的“后向”概率,这些概率都可以通过前面的介绍利用递归进行高效计算。可以通过利用近似的 HMM 模型参数来提高这些中间概率从而进行调整,而这些调整又形成了前向后向算法迭代的基础。

  另外,前向后向算法是 EM 算法的一个特例,它避免了 EM 算法的暴力计算,而采用动态规划思想来解决问题,Jelinek 在其书《Statistical Methods for Speech Recognition》中对前向后向算法与 EM 算法的关系进行了详细描述,有兴趣的读者可以参考这本书。

  类似于上面讲到的前向算法,我们也可以定义后向变量 βt(i) 来计算给定当前隐藏状态 i 时,部分观察序列 ot+1,ot+2,…,oT的概率,即:

  与前向算法类似,我们也可以通过迭代算法有效计算 βt(i),计算公式如下:

  其中

  进一步我们可以发现

  因此

  下面开始介绍前向后向算法

  首先我们需要定义两个辅助变量,这两个变量可以用前文介绍过的前向变量和后向变量进行定义。

  第一个变量定义为 t 时状态 i 和 t+1 时状态 j 的概率,即

  该变量在网格中所代表的关系如下图所示:

  

  该等式等价于

  利用前向变量和后向变量,上式可以表示为

  第二个变量定义为后验概率,也就是在给定观察状态序列和 HMM 的情况下,t 时状态 i 的概率,即

  利用前向变量和后向变量,上式可以表示为

  因此,下式为在任意时刻状态 i 的期望,也就是从状态 i 转移到观察状态 o 的期望

  同样,下式也就是从状态 i 转移到状态 j 的期望

  我们可以发现定义的这两个变量之间的关系为

  下面介绍前向后向算法的参数学习过程,在学习的过程中,不断更新 HMM 的参数,从而使得 P(O | λ) 最大。我们假设初始的 HMM 参数为  λ={ π, A, B },首先计算前向变量 α 和后向变量 β,再根据刚刚介绍的公式计算期望 ξ 和 ζ,最后,根据下面的3个重估计公式更新 HMM 参数。

  如果我们定义当前的 HMM 模型为 λ={ π,A,B },那么可以利用该模型计算上面三个式子的右端;我们再定义重新估计的 HMM 模型为,那么上面三个式子的左端就是重估的 HMM 模型参数。Baum 及他的同事在70年代证明了,因此如果我们迭代地计算上面三个式子,由此不断地重新估计 HMM 的参数,那么在多次迭代后可以得到 HMM 模型的一个最大似然估计。不过需要注意的是,前向后向算法所得的这个最大似然估计是一个局部最优解。

  参考资料:

  1. http://blog.csdn.net/eaglex/article/details/6376826

  2. http://en.wikipedia.org/wiki/Markov_chain

  3. http://en.wikipedia.org/wiki/Hidden_Markov_model

  4. Lawrence R. Rabiner, A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition. Proceedings of the IEEE, 77 (2), p. 257–286, February 1989.

  5. L. R. Rabiner and B. H. Juang, “An introduction to HMMs,” IEEE ASSP Mag., vol. 3, no. 1, pp. 4-16, 1986.

  6. http://jedlik.phy.bme.hu/~gerjanos/HMM/node2.html

  7. http://www.cs.brown.edu/research/ai/dynamics/tutorial/Documents/HiddenMarkovModels.html

  8. 隐马尔可夫模型简介,刘群

你可能感兴趣的:(——机器学习——,HMM,机器学习,隐马尔科夫模型)