隐马尔可夫模型

介绍隐马尔可夫模型之前,首先需要明白马尔可夫链。

马尔可夫链

假设随机过程中各个隐马尔可夫 - 图1的概率分布,只与它之前的状态隐马尔可夫 - 图2有关,即隐马尔可夫 - 图3。比如硬性规定今天的气温只跟昨天有关,跟前天或之前的天气无关。这种假设未必适用所有的应用,但是至少对以前很多不好解决的问题给出了近似解。这个假设后来被命名为马尔可夫假设,而符合这个假设的随机过程则称为马尔可夫过程,也称为马尔可夫链。

隐马尔可夫1.jpg

上图中,四个圈表示四个状态,每条边表示一个可能的状态转换,边上的权值为转移概率。例如,状态隐马尔可夫 - 图5到状态隐马尔可夫 - 图6之间只有一条边,且边上的权重为隐马尔可夫 - 图7。这表示从状态隐马尔可夫 - 图8只可能转换到状态隐马尔可夫 - 图9,转移概率为隐马尔可夫 - 图10。从隐马尔可夫 - 图11出发的有两条边:到隐马尔可夫 - 图12和到隐马尔可夫 - 图13。其中权值隐马尔可夫 - 图14表示:如果某个时刻隐马尔可夫 - 图15的状态隐马尔可夫 - 图16隐马尔可夫 - 图17,则下一个时刻的状态隐马尔可夫 - 图18的概率是隐马尔可夫 - 图19。如果用数学符号表示是隐马尔可夫 - 图20。类似的,有隐马尔可夫 - 图21。随机选择一个状态作为初始状态,随后按照上述规则随机选择后续状态。这样运行一段时间隐马尔可夫 - 图22后,就会产生一个状态序列:隐马尔可夫 - 图23

隐马尔可夫模型

隐马尔可夫模型是马尔可夫链的一个扩展:任一时刻隐马尔可夫 - 图24的状态隐马尔可夫 - 图25是不可见的。观察者没法通过观察到一个状态序列隐马尔可夫 - 图26来推测转移概率等参数。但是,隐马尔可夫模型在每个时刻隐马尔可夫 - 图27会输出一个符号隐马尔可夫 - 图28,而且隐马尔可夫 - 图29隐马尔可夫 - 图30相关且仅跟隐马尔可夫 - 图31相关。即,我们观测不到状态变化,只能观测到输出符号。

隐马尔可夫2.png

基于马尔可夫假设和独立输出假设,我们可以计算出某个特定的状态序列隐马尔可夫 - 图33产生输出符号隐马尔可夫 - 图34的概率

隐马尔可夫 - 图35

除了结构信息,想要确定一个隐马尔可夫模型还需要以下三组参数:

1、状态转移概率:模型在各个状态间转换的概率,通常记为矩阵隐马尔可夫 - 图36其中

隐马尔可夫 - 图37

表示在任意时刻隐马尔可夫 - 图38,若状态为隐马尔可夫 - 图39,则下一时刻状态为隐马尔可夫 - 图40的概率

2、输出观测概率:模型根据当前状态获得各个观测值的概率,记矩阵隐马尔可夫 - 图41其中

隐马尔可夫 - 图42

表示任意时刻隐马尔可夫 - 图43,若状态为隐马尔可夫 - 图44,则观测值隐马尔可夫 - 图45被获取的概率

3、初始状态概率:模型在初始时刻各状态出现的概率,记为隐马尔可夫 - 图46其中

隐马尔可夫 - 图47
表示模型的初始状态为隐马尔可夫 - 图48的概率

通过指定状态空间隐马尔可夫 - 图49、观测空间隐马尔可夫 - 图50和上面三组参数,就能确定一个隐马尔可夫模型,通常用其参数隐马尔可夫 - 图51来指代。给定隐马尔可夫模型隐马尔可夫 - 图52,它按如下过程产生观测序列隐马尔可夫 - 图53

  1. 设置隐马尔可夫 - 图54,并根据初始状态概率隐马尔可夫 - 图55选择初始状态隐马尔可夫 - 图56
  2. 根据状态隐马尔可夫 - 图57和输出观测概率隐马尔可夫 - 图58选择观测变量取值隐马尔可夫 - 图59
  3. 根据状态隐马尔可夫 - 图60和状态转移矩阵隐马尔可夫 - 图61转移模型状态,即确定隐马尔可夫 - 图62
  4. 隐马尔可夫 - 图63设置隐马尔可夫 - 图64,并转到第2.步,否则停止

其中隐马尔可夫 - 图65隐马尔可夫 - 图66分别为第隐马尔可夫 - 图67时刻的状态和观测值

举例如下:假设有4个盒子,每个盒子里都装有红白两种颜色的球

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

按照下面的方法抽球,产生一个球的颜色的观测序列:

开始,从4个盒子里以等概率随机选取1个盒子,从这个盒子里随机抽出1个球,记录颜色后,放回;然后,从当前盒子随机转移到下一个盒子,规则是:如果当前是盒子1,那么下一个盒子一定是盒子2,如果当前是盒子2或3,那么分别以概率0.4,0.6转移到左边或右边的盒子,如果当前是盒子4,那么各以0.5的概率停留在盒子4或转移到盒子3;确定转移的盒子后,再从这个盒子里随机抽取1个球,记录颜色,放回;如此下去,重复5次,得到一个球的颜色的观测序列:

隐马尔可夫 - 图68

在这个过程中,观察者只能观测到球颜色的序列,观测不到球从哪个盒子取出,即观测不到盒子的序列。

在这个例子中有两个随机序列,一个是盒子的序列(状态序列),一个是球的颜色的观测序列(观测序列)。前者是隐藏的,只有后者是可观测的。这是一个隐马尔可夫模型的例子,根据所给条件,可以明确状态集合、观测集合、序列长度及模型的三要素

状态集合:隐马尔可夫 - 图69

观测集合:隐马尔可夫 - 图70

状态序列和观测序列长度:隐马尔可夫 - 图71

初始状态概率分布为:隐马尔可夫 - 图72

状态转移概率分布为:隐马尔可夫 - 图73

观测概率分布为:隐马尔可夫 - 图74

隐马尔可夫模型的训练

围绕着隐马尔可夫模型有三个基本问题:

  1. 给定一个模型,如何计算某个特定的输出序列的概率
  2. 给定一个模型和某个特定的输出序列,如何找到最能产生这个输出序列的状态序列
  3. 给定足够量的观测数据,如何估计隐马尔可夫模型的参数

三大问题

给定模型,计算特定的输出序列的概率

使用前向与后向(Forward-Backward)算法。现实任务中,许多任务需要根据以往的观测序列来推测当前时刻最有可能的观测值,这显然可转化为这个计算特定输出序列的概率的问题。

前向算法

给定隐马尔可夫模型隐马尔可夫 - 图75,定义到时刻隐马尔可夫 - 图76部分观测序列为隐马尔可夫 - 图77且状态为隐马尔可夫 - 图78的概率为前向概率,记作:隐马尔可夫 - 图79可以递推地求得前向概率隐马尔可夫 - 图80及观测序列概率隐马尔可夫 - 图81

输入:隐马尔可夫模型隐马尔可夫 - 图82,观测序列隐马尔可夫 - 图83
输出:观测序列概率隐马尔可夫 - 图84
(1)初值:隐马尔可夫 - 图85

(2)递推:对隐马尔可夫 - 图86
隐马尔可夫 - 图87

(3)终止:隐马尔可夫 - 图88

递推部分就是上个状态转移到当前状态的所有可能乘上当前状态出现对应观测的概率;终止部分即把所有可能出现这种观测的可能加起来,即隐马尔可夫 - 图89

举例如下

考虑盒子和球模型隐马尔可夫 - 图90,状态集合隐马尔可夫 - 图91,观测集合隐马尔可夫 - 图92

隐马尔可夫 - 图93隐马尔可夫 - 图94隐马尔可夫 - 图95

隐马尔可夫 - 图96隐马尔可夫 - 图97,用前向算法计算隐马尔可夫 - 图98

(1)初值:
隐马尔可夫 - 图99
隐马尔可夫 - 图100
隐马尔可夫 - 图101

(2)迭代:
隐马尔可夫 - 图102
隐马尔可夫 - 图103
隐马尔可夫 - 图104
隐马尔可夫 - 图105
隐马尔可夫 - 图106
隐马尔可夫 - 图107

(3)终止:
隐马尔可夫 - 图108

后向算法

给定隐马尔可夫模型隐马尔可夫 - 图109,定义在时刻隐马尔可夫 - 图110状态为隐马尔可夫 - 图111的条件下,从隐马尔可夫 - 图112隐马尔可夫 - 图113的部分观测序列为隐马尔可夫 - 图114的概率为后向概率,记作:隐马尔可夫 - 图115可以用递推地方法求得后向概率隐马尔可夫 - 图116及观测序列概率隐马尔可夫 - 图117

输入:隐马尔可夫模型隐马尔可夫 - 图118,观测序列隐马尔可夫 - 图119
输出:观测序列概率隐马尔可夫 - 图120

(1)隐马尔可夫 - 图121

(2)对隐马尔可夫 - 图122
隐马尔可夫 - 图123

(3)隐马尔可夫 - 图124

给定模型和特定的输出序列,找到最能产生这个输出序列的状态序列

使用维特比(Viterbi Algorithm)算法。在语音识别等任务中,观测值为语音信号,隐藏状态为文字,目标就是根据观测信号来推断最有可能的状态序列(即对应的文字)。

维特比算法是一种动态规划方法,核心思想是:如果最终的最优路径经过某个隐马尔可夫 - 图125,那么从初始节点到隐马尔可夫 - 图126点的路径必然也是一个最优路径,因为每一个节点隐马尔可夫 - 图127只会影响前后两个隐马尔可夫 - 图128隐马尔可夫 - 图129

维特比算法实际上是用动态规划解隐马尔可夫模型预测问题,即用动态规划求概率最大路径。这时一条路径对应着一个状态序列。根据动态规划原理,最优路径具有这样的特性:如果最优路径在时刻隐马尔可夫 - 图130通过结点隐马尔可夫 - 图131,那么这一路径从结点隐马尔可夫 - 图132到终点隐马尔可夫 - 图133的部分路径,对于从隐马尔可夫 - 图134隐马尔可夫 - 图135的所有可能的部分路径来说,必须是最优的。因为假如不是这样,那么从隐马尔可夫 - 图136隐马尔可夫 - 图137就有另一条更好的部分路径存在,如果把它和从隐马尔可夫 - 图138隐马尔可夫 - 图139的部分路径连接起来,就会形成一条比原来的路径更优的路径,这是矛盾的。依据这一原理,我们只需从时刻隐马尔可夫 - 图140开始,递推地计算在时刻隐马尔可夫 - 图141状态为隐马尔可夫 - 图142的各条部分路径的最大概率,直至得到时刻隐马尔可夫 - 图143状态为隐马尔可夫 - 图144的各条路径的最大概率。

输入:模型隐马尔可夫 - 图145和观测隐马尔可夫 - 图146
输出:最优路径隐马尔可夫 - 图147
(1)初始化:
隐马尔可夫 - 图148

(2)递推:对隐马尔可夫 - 图149
隐马尔可夫 - 图150
隐马尔可夫 - 图151

(3)终止:
隐马尔可夫 - 图152

(4)最优路径回溯:对隐马尔可夫 - 图153
隐马尔可夫 - 图154

举例如下

考虑盒子和球模型隐马尔可夫 - 图155,状态集合隐马尔可夫 - 图156,观测集合隐马尔可夫 - 图157

隐马尔可夫 - 图158隐马尔可夫 - 图159隐马尔可夫 - 图160

已知观测序列隐马尔可夫 - 图161,求最优状态序列,即最优路径隐马尔可夫 - 图162

(1)初始化。在隐马尔可夫 - 图163时,对每一个状态隐马尔可夫 - 图164,求状态隐马尔可夫 - 图165观测隐马尔可夫 - 图166为红的概率,记此概率为隐马尔可夫 - 图167,则

隐马尔可夫 - 图168

代入实际数据

隐马尔可夫 - 图169

隐马尔可夫 - 图170

(2)在隐马尔可夫 - 图171时,对每个状态隐马尔可夫 - 图172,求在隐马尔可夫 - 图173时状态为隐马尔可夫 - 图174观测为红并在隐马尔可夫 - 图175时状态为隐马尔可夫 - 图176观测隐马尔可夫 - 图177为白的路径的最大概率,记此最大概率为隐马尔可夫 - 图178,则

隐马尔可夫 - 图179

同时,对每个状态隐马尔可夫 - 图180,记录概率最大路径的前一个状态隐马尔可夫 - 图181

隐马尔可夫 - 图182

计算:
隐马尔可夫 - 图183
隐马尔可夫 - 图184
隐马尔可夫 - 图185

同样,在隐马尔可夫 - 图186时,
隐马尔可夫 - 图187
隐马尔可夫 - 图188
隐马尔可夫 - 图189
隐马尔可夫 - 图190

隐马尔可夫3.png

(3)以隐马尔可夫 - 图192表示最优路径的概率,则

隐马尔可夫 - 图193

最优路径的终点是隐马尔可夫 - 图194

隐马尔可夫 - 图195

(4)由最优路径的终点隐马尔可夫 - 图196,逆向找到隐马尔可夫 - 图197隐马尔可夫 - 图198

隐马尔可夫 - 图199时,隐马尔可夫 - 图200
隐马尔可夫 - 图201时,隐马尔可夫 - 图202

于是求得最优路径,即最优状态序列隐马尔可夫 - 图203

给定足够量的观测数据,估计隐马尔可夫模型的参数

使用鲍姆-韦尔奇(Baum-Welch)算法,也就是EM算法。在大多数现实应用中,人工指定模型参数已变得越来越不可行,如何根据训练样本学得最优的模型参数,正好就是本问题。

在利用隐马尔可夫模型解决实际问题中,需要先知道每个状态隐马尔可夫 - 图204产生相应输出符号隐马尔可夫 - 图205的概率隐马尔可夫 - 图206,也称为生成概率;和转移概率,即从前一个状态隐马尔可夫 - 图207进入当前状态隐马尔可夫 - 图208的概率隐马尔可夫 - 图209。这些概率被称为马尔可夫模型的参数,而计算或者估计这些参数的过程称为模型的训练。

我们从条件概率的定义出发,知道:

隐马尔可夫 - 图210

隐马尔可夫 - 图211

对于上面第一个概率公式(生成概率),状态输出概率,如果有足够多人工标记的数据,知道经过状态隐马尔可夫 - 图212有多少次隐马尔可夫 - 图213,每经过这个状态时,分别产生的输出隐马尔可夫 - 图214是什么,而且分别有多少次隐马尔可夫 - 图215就可以算出(比如语音识别中,符号即每个词对应声波;中英翻译中,中文字为状态,英文字为输出符号)。上述第二个概率公式(转移概率),与前文提到的训练统计语言模型的条件概率完全相同,因此可以依照统计语言模型的训练方法,即数一下出现前一个词后出现这个词的次数(同上文例子,出现“联想”这个词后,出现“公司”的概率是多少,即数一下“联想”的次数,数一下“联想公司”的次数)

隐马尔可夫 - 图216
隐马尔可夫 - 图217

然而,像语音识别等这种应用大量人工标注不现实,所以这个方法只适用于一部分应用。因此,训练隐马尔可夫模型更实用的方法是仅仅通过大量观测到的信号隐马尔可夫 - 图218就能推算模型参数的隐马尔可夫 - 图219隐马尔可夫 - 图220的方法,主要是使用鲍姆-韦尔奇算法。

两个不同的隐马尔可夫模型可以产生同样的输出信号,因此,仅仅通过观察到的输出信号来倒推它的隐马尔可夫模型可能会得到多个合适的模型,但总会有一个模型隐马尔可夫 - 图221比其他的隐马尔可夫 - 图222更有可能产生观测到的输出,其中隐马尔可夫 - 图223是隐马尔科夫模型的参数(可理解为最大似然)。鲍姆-韦尔奇算法就是来寻找这个最可能的模型隐马尔可夫 - 图224

鲍姆-韦尔奇算法思想:

鲍姆-韦尔奇算法使用的就是EM算法原理。首先找到一组能够产生输出序列隐马尔可夫 - 图225的模型参数(显然它们是一定存在的,因为转移概率隐马尔可夫 - 图226和输出概率隐马尔可夫 - 图227为均匀分布时,模型可以产生任何输出,当然包括我们观测到的输出隐马尔可夫 - 图228)现在,有了这样一个初始模型隐马尔可夫 - 图229,根据上文提到的隐马尔可夫 - 图230隐马尔可夫 - 图231公式计算出一组新的模型参数隐马尔可夫 - 图232,为一次迭代,可以证明隐马尔可夫 - 图233。经过不断迭代隐马尔可夫 - 图234轮,直到模型的质量不再有显著提高,得到的隐马尔可夫 - 图235即我们所求参数。

马尔可夫随机场

马尔可夫随机场(Markov Random Field)包含两层意思。

马尔可夫性质:它指的是一个随机变量序列按时间先后关系依次排开的时候,第隐马尔可夫 - 图236时刻的分布特性,与隐马尔可夫 - 图237时刻以前的随机变量的取值无关。拿天气来打个比方。如果我们假定天气是马尔可夫的,其意思就是我们假设今天的天气仅仅与昨天的天气存在概率上的关联,而与前天及前天以前的天气没有关系。其它如传染病和谣言的传播规律,就是马尔可夫的。

随机场:当给每一个位置中按照某种分布随机赋予相空间的一个值之后,其全体就叫做随机场。我们不妨拿种地来打个比方。其中有两个概念:位置(site),相空间(phase space)。“位置”好比是一亩亩农田;“相空间”好比是种的各种庄稼。我们可以给不同的地种上不同的庄稼,这就好比给随机场的每个“位置”,赋予相空间里不同的值。所以,俗气点说,随机场就是在哪块地里种什么庄稼的事情。

马尔可夫随机场:马尔科夫随机场是具有马尔科夫特性的随机拿种地打比方,如果任何一块地里种的庄稼的种类仅仅与它邻近的地里种的庄稼的种类有关,与其它地方的庄稼的种类无关,那么这些地里种的庄稼的集合,就是一个马尔可夫随机场。

模型定义

概率图模型是由图表示概率分布。设有联合概率分布隐马尔可夫 - 图238隐马尔可夫 - 图239是一组随机变量。由无向图隐马尔可夫 - 图240表示概率分布隐马尔可夫 - 图241,即在图隐马尔可夫 - 图242中,结点隐马尔可夫 - 图243表示一个随机变量隐马尔可夫 - 图244隐马尔可夫 - 图245;边隐马尔可夫 - 图246表示随机变量之间的概率依赖关系。

给定一个联合概率分布隐马尔可夫 - 图247和表示它的无向图隐马尔可夫 - 图248。首先定义无向图表示的随机变量之间存在的成对马尔可夫性、局部马尔可夫性和全局马尔可夫性。

成对马尔可夫性:设隐马尔可夫 - 图249隐马尔可夫 - 图250是无向图隐马尔可夫 - 图251中任意两个没有边连接的结点,结点隐马尔可夫 - 图252隐马尔可夫 - 图253分别对应随机变量隐马尔可夫 - 图254隐马尔可夫 - 图255。其他所有结点为隐马尔可夫 - 图256,对应的随机变量组是隐马尔可夫 - 图257。成对马尔可夫性是指给定随机变量组隐马尔可夫 - 图258的条件下随机变量隐马尔可夫 - 图259隐马尔可夫 - 图260是条件独立的,即

隐马尔可夫 - 图261

局部马尔可夫性:设隐马尔可夫 - 图262是无向图隐马尔可夫 - 图263中任意一个结点,隐马尔可夫 - 图264是与隐马尔可夫 - 图265有边连接的所有结点,隐马尔可夫 - 图266隐马尔可夫 - 图267隐马尔可夫 - 图268以外的其他所有结点。隐马尔可夫 - 图269表示的随机变量是隐马尔可夫 - 图270隐马尔可夫 - 图271表示的随机变量组是隐马尔可夫 - 图272隐马尔可夫 - 图273表示的随机变量是隐马尔可夫 - 图274。局部马尔可夫性是指在给定随机变量组隐马尔可夫 - 图275的条件下随机变量隐马尔可夫 - 图276隐马尔可夫 - 图277是独立的,即

隐马尔可夫 - 图278

隐马尔可夫4.png

全局马尔可夫性:设结点集合隐马尔可夫 - 图280隐马尔可夫 - 图281是在无向图隐马尔可夫 - 图282中被结点组合隐马尔可夫 - 图283分开的任意结点集合。结点集合隐马尔可夫 - 图284隐马尔可夫 - 图285隐马尔可夫 - 图286所对应的随机变量组分别是隐马尔可夫 - 图287隐马尔可夫 - 图288隐马尔可夫 - 图289。全局马尔可夫性是指给定随机变量组隐马尔可夫 - 图290条件下随机变量隐马尔可夫 - 图291隐马尔可夫 - 图292是条件独立的,即

隐马尔可夫 - 图293

隐马尔可夫5.png

设有联合分布隐马尔可夫 - 图295,由无向图隐马尔可夫 - 图296表示,在图隐马尔可夫 - 图297中,结点表示随机变量,边表示随机变量之间的依赖关系。如果联合概率分布隐马尔可夫 - 图298满足成对、局部或全局马尔可夫性,就称此联合概率分布为概率无向图模型,或马尔可夫随机场。

模型的因子分解

马尔科夫随机场(Markov Random Field, MRF)是典型的马尔可夫网,这是一种著名的无向图模型。图中每个结点表示一个或一组变量,结点之间的边表示两个变量之间的依赖关系。马尔科夫随机场有一组势函数,又称为“因子”,这是定义在变量子集上的非负实函数,主要用于定义概率分布函数。

隐马尔可夫6.png

上图就是一个简单的马尔科夫随机场。对于图中结点的一个子集,若其中任意两结点间都有边连接,则称该结点子集为一个“团”(clique)。若在一个团中加入另外任何一个结点都不再形成团,则称该团为“极大团”;换言之,极大团就是不能被其他团所包含的团。例如上图隐马尔可夫 - 图300隐马尔可夫 - 图301隐马尔可夫 - 图302隐马尔可夫 - 图303隐马尔可夫 - 图304隐马尔可夫 - 图305隐马尔可夫 - 图306隐马尔可夫 - 图307都是团,并且除了隐马尔可夫 - 图308隐马尔可夫 - 图309隐马尔可夫 - 图310之外都是极大团。显然,每个结点至少出现在一个极大团中。

将概率无向图模型的联合概率分布表示为其最大团上的随机变量的函数的乘积形式的操作,称为概率无向图模型的因子分解。给定概率无向图模型,设其无向图为隐马尔可夫 - 图311隐马尔可夫 - 图312隐马尔可夫 - 图313上的最大团,隐马尔可夫 - 图314表示隐马尔可夫 - 图315对应的随机变量。那么概率无向图模型的联合概率分布隐马尔可夫 - 图316可写作图中所有最大团隐马尔可夫 - 图317上的函数隐马尔可夫 - 图318的乘积形式,即

隐马尔可夫 - 图319

其中,隐马尔可夫 - 图320是规范化因子,由下式得出

隐马尔可夫 - 图321

规范化因子保证隐马尔可夫 - 图322构成一个概率分布。函数隐马尔可夫 - 图323称为势函数。这里要求势函数是严格正的,通常定义为指数函数:

隐马尔可夫 - 图324

概率无向图模型的因子分解由Hammersley-Clifford定理来保证

隐马尔可夫 - 图325

隐马尔可夫 - 图326

其中,隐马尔可夫 - 图327是无向图的最大团,隐马尔可夫 - 图328隐马尔可夫 - 图329的结点对应的随机变量,隐马尔可夫 - 图330隐马尔可夫 - 图331上定义的严格正函数,乘积是在无向图所有的最大团上进行的。

Code实现

  1. import numpy as np
  2. class HiddenMarkov:
  3. def forward(self, Q, V, A, B, O, PI): # 使用前向算法
  4. N = len(Q) # 状态序列的大小
  5. M = len(O) # 观测序列的大小
  6. alphas = np.zeros((N, M)) # alpha值
  7. T = M # 有几个时刻,有几个观测序列,就有几个时刻
  8. for t in range(T): # 遍历每一时刻,算出alpha值
  9. indexOfO = V.index(O[t]) # 找出序列对应的索引
  10. for i in range(N):
  11. if t == 0: # 计算初值
  12. alphas[i][t] = PI[t][i] * B[i][indexOfO] # P176(10.15)
  13. print('alpha1(%d)=p%db%db(o1)=%f' % (i, i, i, alphas[i][t]))
  14. else:
  15. alphas[i][t] = np.dot([alpha[t - 1] for alpha in alphas], [a[i] for a in A]) * B[i][
  16. indexOfO] # 对应P176(10.16)
  17. print('alpha%d(%d)=[sigma alpha%d(i)ai%d]b%d(o%d)=%f' % (t, i, t - 1, i, i, t, alphas[i][t]))
  18. # print(alphas)
  19. P = np.sum([alpha[M - 1] for alpha in alphas]) # P176(10.17)
  20. # alpha11 = pi[0][0] * B[0][0] #代表a1(1)
  21. # alpha12 = pi[0][1] * B[1][0] #代表a1(2)
  22. # alpha13 = pi[0][2] * B[2][0] #代表a1(3)
  23. def backward(self, Q, V, A, B, O, PI): # 后向算法
  24. N = len(Q) # 状态序列的大小
  25. M = len(O) # 观测序列的大小
  26. betas = np.ones((N, M)) # beta
  27. for i in range(N):
  28. print('beta%d(%d)=1' % (M, i))
  29. for t in range(M - 2, -1, -1):
  30. indexOfO = V.index(O[t + 1]) # 找出序列对应的索引
  31. for i in range(N):
  32. betas[i][t] = np.dot(np.multiply(A[i], [b[indexOfO] for b in B]), [beta[t + 1] for beta in betas])
  33. realT = t + 1
  34. realI = i + 1
  35. print('beta%d(%d)=[sigma a%djbj(o%d)]beta%d(j)=(' % (realT, realI, realI, realT + 1, realT + 1),
  36. end='')
  37. for j in range(N):
  38. print("%.2f*%.2f*%.2f+" % (A[i][j], B[j][indexOfO], betas[j][t + 1]), end='')
  39. print("0)=%.3f" % betas[i][t])
  40. # print(betas)
  41. indexOfO = V.index(O[0])
  42. P = np.dot(np.multiply(PI, [b[indexOfO] for b in B]), [beta[0] for beta in betas])
  43. print("P(O|lambda)=", end="")
  44. for i in range(N):
  45. print("%.1f*%.1f*%.5f+" % (PI[0][i], B[i][indexOfO], betas[i][0]), end="")
  46. print("0=%f" % P)
  47. def viterbi(self, Q, V, A, B, O, PI):
  48. N = len(Q) # 状态序列的大小
  49. M = len(O) # 观测序列的大小
  50. deltas = np.zeros((N, M))
  51. psis = np.zeros((N, M))
  52. I = np.zeros((1, M))
  53. for t in range(M):
  54. realT = t+1
  55. indexOfO = V.index(O[t]) # 找出序列对应的索引
  56. for i in range(N):
  57. realI = i+1
  58. if t == 0:
  59. deltas[i][t] = PI[0][i] * B[i][indexOfO]
  60. psis[i][t] = 0
  61. print('delta1(%d)=pi%d * b%d(o1)=%.2f * %.2f=%.2f'%(realI, realI, realI, PI[0][i], B[i][indexOfO], deltas[i][t]))
  62. print('psis1(%d)=0' % (realI))
  63. else:
  64. deltas[i][t] = np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])) * B[i][indexOfO]
  65. print('delta%d(%d)=max[delta%d(j)aj%d]b%d(o%d)=%.2f*%.2f=%.5f'%(realT, realI, realT-1, realI, realI, realT, np.max(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])), B[i][indexOfO], deltas[i][t]))
  66. psis[i][t] = np.argmax(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A]))
  67. print('psis%d(%d)=argmax[delta%d(j)aj%d]=%d' % (realT, realI, realT-1, realI, psis[i][t]))
  68. print(deltas)
  69. print(psis)
  70. I[0][M-1] = np.argmax([delta[M-1] for delta in deltas])
  71. print('i%d=argmax[deltaT(i)]=%d' % (M, I[0][M-1]+1))
  72. for t in range(M-2, -1, -1):
  73. I[0][t] = psis[int(I[0][t+1])][t+1]
  74. print('i%d=psis%d(i%d)=%d' % (t+1, t+2, t+2, I[0][t]+1))
  75. print(I)
  76. #测试数据
  77. Q = [1, 2, 3]
  78. V = ['红', '白']
  79. A = [[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]]
  80. B = [[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]]
  81. # O = ['红', '白', '红', '红', '白', '红', '白', '白']
  82. O = ['红', '白', '红', '白']
  83. PI = [[0.2, 0.4, 0.4]]
  84. HMM = HiddenMarkov()
  85. # HMM.forward(Q, V, A, B, O, PI)
  86. # HMM.backward(Q, V, A, B, O, PI)
  87. HMM.viterbi(Q, V, A, B, O, PI)

Source

https://www.zhihu.com/question/35866596/answer/236886066