作者:哈工大SCIR硕士生 乐远

隐马尔可夫模型(HMM)是可用于标注问题的统计学习模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型。

说到隐马尔可夫模型(HMM),我们先来了解下马尔可夫模型(Markov模型),Markov模型是一种统计模型,广泛地应用在语音识别,词性自动标注,音字转换,概率文法等各个自然语言处理的应用领域。

一. 马尔可夫模型(Markov模型)


隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据

是随机变量序列,其中每个随机变量的取值在有限集

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_02

,称为状态空间。Markov特征是

  • 有限历史假设

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_03

  • 时间不变性

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_04

如果

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_05

具有这些特征,那么这个随机变量序列称为一个马尔可夫过程(链)。Markov的形式化表示:一个马尔可夫模型是一个三元组

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_06

,其中

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_07

 是状态的集合,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_08

是初始状态的概率,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_09

是状态间的转移概率。具体例子用图形表示如下,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_10

相应的

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_11

分别是,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_12

隐马尔可夫模型与马尔可夫模型不同的是各个状态(或者状态转移弧)都有一个输出,但是状态是不可见的。

最简单的情形:不同的状态只能有不同的输出,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_13

增加一点灵活性:不同的状态,可以输出相同的输出,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_14

再增加一点灵活性:输出在状态转移中进行,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_15

最大的灵活性:在状态转移中以特定的概率分布输出,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_16

这就得到了我们要讲的隐马尔可夫模型。

二. 隐马尔可夫模型(HMM)

1.HMM的形式化定义

HMM是一个五元组

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_17

,其中

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_18

是状态的集合,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_19

是输出字符的集合,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_20

是初始状态的概率,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_21

是状态转移的概率,  

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_22

是状态转移时输出字符的概率。

一个HMM的例子用图形表示如下,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_23

2. 隐马尔可夫模型的三个基本问题

  • 评估问题:给定一个模型
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_24

  • ,如何高效地计算某一输出字符序列的概率
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_25

  • 解码问题:给定一个输出字符序列
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_26

  • ,和一个模型
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_27

  • ,如何确定产生这一序列概率最大的状态序列
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_28

  • 学习问题:给定一个输出字符的序列
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_29

  • ,如何调整模型的参数使得产生这一序列的概率最大?

3. 评估问题的解法

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_30

已知

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_31


隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_32

,计算

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_33

?我们先来化简一下

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_34


隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_35

  • 方案一:直接计算法

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_36

穷举所有可能的

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_37

的情况,求和得到

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_38

,但是时间复杂度太高,为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_39


  • 方案二:前向算法(Forward algorithm)

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_40

使用动态规划使得算法更高效,定义一个前向变量表示到时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_41

部分观测序列为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_42

且状态为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_43

的概率为向前概率,记为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_44

,即

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_45

则可以递推得到,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_46

前向过程算法如下,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_47

一个简单的前向过程例子如下,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_48

  • 方案三:向后算法(backward algorithm)

同样的道理,我们定义在时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_49

状态为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_50

的条件下,从

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_51


隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_52

的部分观测序列为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_53

的概率为后向概率,记作

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_54

,即

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_55

直接采用递推即可得到后向算法。

后向算法过程如下,

  • 1. 初始化

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_56

  • 2. 推导

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_57

  • 3. 总和

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_58

4. 解码问题的解法

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_59

给定一个输出字符序列

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_60

,和一个模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_61

,如何确定产生这一序列概率最大的状态序列?

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_62

我们定义

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_63

表示为在

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_64

时刻到达状态

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_65

,输出字符

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_66

时,输出前面

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_67

个字符的最可能路径的概率,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_68

则有

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_69

这样我们就得到了维特比算法(Viterbi Algorithm),算法过程如下:

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_70

一个简单的viterbi算法举例如下,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_71

5.  学习问题解法

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_72

给定一个输出字符的序列

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_73

,如何调整模型的参数使得产生这一序列的概率最大?

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_74

隐马尔可夫模型的学习,根据训练数据是包括观测数据和对应的状态序列还是只有观测序列,可以分为有监督学习和无监督学习,其中无监督的学习即是利用EM算法思想的Baum-Welch算法。

  • 方案一:有监督学习

假设训练数据包含

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_75

个长度相同的观测序列和对应的状态序列

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_76

,那么可以利用极大似然估计法来估计隐马尔可夫模型的参数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_77

,具体估计方法如下:

  • 1. 转移概率
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_78

  • 的估计

设样本中时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_79

处于状态

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_80

时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_81

处于状态

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_82

的频数为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_83

,那么状态转移概率

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_84

的估计是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_85

  • 2. 观测概率
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_86

  • 的估计

设样本中状态为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_87

并观测为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_88

的频数是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_89

,那么状态为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_90

观测为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_91

的概率

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_92

的估计是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_93

  • 3. 初始状态概率
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_94

  • 的估计
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_95

  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_96

  • 个样本中初始状态为
  • 隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_97

  • 的概率

由于监督学习的方法需要使用训练数据,而人工标注的代价往往很高,有时会采用非监督学习的方法。

  • 方案二:无监督学习——Baum-Welch算法

假设给定的训练数据只包含

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_98

个长度为

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_99

的观测序列而没有对应的状态序列

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_100

,目标是学习隐马尔可夫模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_101

的参数。我们将观测序列数据看做观测数据

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_102

,状态序列数据看做不可观测数据

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_103

,那么隐马尔可夫模型事实上是一个包含隐变量的概率模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_104

它的参数学习可以由EM算法实现。

(算法推导过程)

(1) 确定完全数据的对数似然函数 所有观测数据写成

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_105

,所有的隐数据写成

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_106

,完全数据是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_107

。完全数据的对数似然函数是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_108

(2) EM算法的E步:求

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_109

函数的

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_110

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_111

其中

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_112

是隐马尔可夫模型参数的当前估计值,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_113

是要极大化的隐马尔可夫模型参数。因为,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_114

所以

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_115

函数可以拆分写成

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_116

式中求和都是对所有训练数据的序列总长度

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_117

进行的。

(3) EM算法的M步:极大化

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_118

函数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_119

,求模型参数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_120

由于要极大化的参数在

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_121

函数式子中单独的出现在三个项中,所以只需要对各项分别极大化。第一项可以写成,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_122

注意到

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_123

满足

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_124

,利用拉格朗日乘子法,写出拉格朗日函数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_125

对其求导数并令结果为0,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_126

得到

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_127

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_128

求和得到

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_129

,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_130

再代入上式子得到,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_131

第二项可以写成

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_132

类似于第一项,利用具有约束条件

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_133

的拉格朗日乘子法恶意求出

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_134

第三项可以写成,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_135

同样利用拉格朗日乘子法,约束条件是

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_136

,注意只有在

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_137

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_138

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_139

的偏导数才不为0,以

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_140

表示,得到,

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_141

-----

为了简便,我们使用一下式子简化, 给定模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_142

和观测

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_143

,在时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_144

处于状态

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_145

的概率记

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_146

有如下公式:

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_147

给定模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_148

和观测

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_149

,在时刻

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_150

处于状态

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_151

的概率记 :

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_152

有如下推倒:

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_153

我们结合上文以及EM算法可以推导如下公式

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_154

Baum-Welch算法过程:

输入:观测数据

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_155

;输出:隐马尔可夫模型参数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_156

。1. 初始化。对

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_157

,选取

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_状态转移_158

得到模型

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_初始状态_159

2. 递推。对

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_160

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_隐马尔可夫模型 python 代码_161

3. 终止。得到模型参数

隐马尔可夫模型 python 代码 隐马尔可夫模型的应用_数据_162


参考资料

[1]公式参考李航《统计学习方法》

[2]图片选自哈尔滨工业大学关毅教授《自然语言处理》课程PPT

本期责任编辑:丁    效

本期编辑:刘元兴