在上一篇文章机器学习中的隐马尔科夫模型(HMM)详解中,我们已经向大家介绍了HMM的基本概念。本文将通过几个例子来演示HMM可以帮我们做些什么事情。特别地,在这个过程中,我们还将向你介绍HMM中非常重要的前向(Forward)算法以及(基于动态规划思想设计的)维特比(Viterbi)算法。
- 一个引子
- 前向(Forward)算法
- 维特比(Viterbi)算法
- HMM在自然语言处理中的应用举例
欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。
一个引子
回忆一下,我们通常如何定义一个HMM,上篇文章已经告诉我们定义一个HMM模型,需要三个参数,或者说我们可以把一个HMM记作 λ(A,B,π)。其中,矩阵 A 用来表示转移概率 P(qt|qt?1),B 用来表示测量概率 P(yt|qt),最后 π 指示了HMM模型的初始状态。
继续上篇文章中最后的那个讨论,假设现在我们有如下这样一个HMM,而且我们已经得到了连续的三个观测值 y1=up,y2=up,y3=down,能否据此得到相应的隐状态序列呢?
这其实是HMM可以实现的第一种功能。有时我们称之为Computing Likelihood,其实它所要做的就是 Evaluate
P(Y|λ)。因为我们想知道隐藏在观测值背后的隐状态序列,其实就是要看哪个隐状态序列可以使得上面这个观测值的概率最大。而且在上一篇文章的末尾我也得出了针对上述问题的一个递推公式,即
P(y1,y2,y3)=∑q1k∑q2k∑q3kP(y3|q3)×P(q3|q2)×P(y2|q2)×P(q2|q1)×P(y1|q1)×P(q1)
根据已有的HMM参数以及上面这个公式,当隐状态
q1,q2,q3 取不得不同的值时,显然我们可以算出不同的概率,然后其中取值最大的对应序列就是我们想要找的隐状态。具体来说,我们可以列出下面这张表,其中
q1=1,q2=1,q3=2 就是我们最终要找的隐状态序列。
把这种解法泛化,可得下式(注意其中 λ 是已知条件,但是从第二行开始为了书写上的简便,我们将其略去)
P(Y|λ)=∑Q[P(Y,Q|λ)]=∑q1=1k?∑qT=1k[P(y1,?,yT,q1,?,qT|λ)]=∑q1=1k?∑qT=1kP(q1)P(y1|q1)P(q2|q1)?P(qt|qt?1)P(yt|qt)=∑q1=1k?∑qT=1kπ(q1)∏t=1Taqt?1,qtbqt(yt)
我们对最后一行的标记稍作解释。因为
P(q1) 是由初始状态决定的,所以它被记作
π(q1)。矩阵
A 用来表示转移概率
P(qt|qt?1),具体来说,其中第
m 行,第
n 列所给出的值就是
P(qt=n|qt?1=m),所以矩阵中的
P(q2|q1),?,P(qt|qt?1) 就可以记作
∏Tt=1aqt?1,qt ,其中
aqt?1,qt 就是矩阵中第
qt?1 行,第
qt 列的项。类似地,(注意我们现在讨论的观测值服从离散分布),
B 用来表示测量概率
P(yt|qt),所以矩阵
B 中的项
bqt(yt) 就对应概率
P(yt|qt)。
上这种做法确实可以得出我们想要的结果,但是这种做法的计算量过大。你很容易发现,它的复杂度是 O(kT) ,实际应用中需要一种更高效的算法,这就是本文后续要讨论的内容。
前向(Forward)算法
首先针对下图所示的情况,我们定义一个新的记号:
αi(t)=P(y1,y2,?,yt,qt=i | λ)
其注意这里的
α 和
a 是不同的。我们的新记号
αi(t) 给出了当状态
qt=i 时,它与到时刻
t 为止所有的观测值的联合分布的概率。
借助上面这个定义,我们便可以简化原来相当繁杂的运算。不妨来看看
αi(1) 所表示的内容:
αi(1)=P(y1,q1=i)=P(y1|q1=i)?P(q1)=bi(y1)?π(q1)
同理,我们还可以写出
αj(2) 所表示的内容:
αj(2)=P(y1,y2,q2=j)=∑i=1kP(y1,y2,q1=i,q2=j)=∑i=1kP(y2|q2=j)?P(q2=j|q1=i)?P(y1,q1=i)=∑i=1kP(y2|q2=j)?P(q2=j|q1=i)?αi(1)=P(y2|q2=j)∑i=1kP(q2=j|q1=i)?αi(1)=bj(y2)∑i=1kai,j?αi(1)
可见
αi(2) 和
αi(1) 之间产生了递推关系,所以我们可以写出
αj(T) 的表达式:
αj(T)=bj(yT)∑i=1kai,j?αi(T?1)
到此为止,其实我们已经得到了一个相当高效的计算
P(y1,y2,?,yT) 的方法。因为根据定义,我们可以知道
αj(T)=(y1,y2,?,yT,qt=j) 。而我们最终要求的问题就可以通过下式得到:
P(y1,y2,?,yT)=∑j=1kαj(T)
而且现在问题的复杂度已经降为了
O(K2T)。
维特比(Viterbi)算法
我们已经知道,前向算法的目的在于求 P(y1,y2,?,yt),之所以在求解公式前面会出现很多的求和,这是因为,当给定一个观测序列(例如UP,UP,DOWN)时,最终的概率值其实是所有可能的情况的概率加总。或者说,针对“UP,UP,DOWN”这里例子而言,前向算法求出的其实是本文开头给出的那个表中所有行的概率之和。而这个表中的概率一共有 KT 行(这个计算量太大),如果采用前向算法,我们就可以大大简化这个计算量。
但现在我们要回到最开始抛出的那个问题,如果给定一个观测序列,例如“UP,UP,DOWN”,那最可能的隐状态序列应该是什么?注意这个问题的答案不再整张概率表,而其实是要求其中(概率值最大的)一行。当然,我们的困难可能在于如果不把整张表列出来,那又如何知道哪一行的概率值最大呢?其实根据前向算法已经给了我们启示。
对于任何一个包含有隐变量的模型来说,例如HMM,当我们有一组观测值时,确定相应的最有可能之隐变量的方法通常又称为 decoding。
HMM中用来decoding的算法就是所谓的维特比算法。它是一种基于动态规划思想设计的算法,最初用于数字通信链路中的卷积码decoding。它的提出者 Andrew Viterbi 被称为是现代CDMA技术之父,他同时还是高通公司的联合创始人和IEEE院士。
经由最可能的状态序列 q0,q1,?,qt?1 后进入状态 qt=j 时,前面这些状态序列与到 t 时刻为止所有观测值的联合分布之概率,我们记为
vj(t)=maxq0,q1,?,qt?1P(q1,q2,?,qt?1,y1,y2,?,yt,qt=j | λ)
注意,我们表示“最可能的状态序列”的方法就是在之前所有的状态序列里找到使上述概率却得最大的那个状态序列,这也同当前我们所面对的问题相一致。
vj(t)=maxq1,?,qt?1P(q1,q2,?,qt?1,y1,y2,?,yt,qt=j)=maxq1,?,qt?1P(q1,q2,?,qt?1,y1,y2,?,yt?1)?P(yt | qt=j)?P(qt=j | qt?1)=maxq1,?,qt?1P(q1,q2,?,qt?1,y1,y2,?,yt?1)?bj(yt)?aqt?1, j=bj(yt)maxikvi(t?1)?ai, j
于是我们同样得到了一个递归的公式(注意这个递归公式的base case由初始状态给定)。这也就是维特比算法的核心原理。此外,由于我们最终要确定最大可能的隐状态序列,所以记 ψj(t) 是在 t?1 时刻的一个状态,且从该状态转换到状态 j 的概率最大,即
ψj(t)=bj(yt)argmaxikvi(t?1)?ai, j
接下来,我们回到开篇给出的那个例子来演示一下维特比算法的执行过程。首先,我们根据已知条件
π 来初始化在
t=1 时刻的概率,则有
vj=1(t=1)=0.5×0.7=0.35,
vj=2(t=1)=0.2×0.1=0.35,
vj=3(t=1)=0.3×0.3=0.09,如下图中最左边一列所示。接下来,当
t=2 时,要求确定
vj=1(t=2) 的值时,对于
i=1,2,3,我们必须考虑三个值,即
vi(1)ai,1 , 其中第一个最大,所以根据算法执行流程,我们得到
vj=1(t=2)=0.147 。也就是下图中红色实线所标示的转移路径,其他两条在后续的步骤中不会再参与计算我们将其用虚线标出。而且,我们还可以得到
ψ1(2)=1,这表明当
t=2 时,转入状态
j=1 前的的状态是
j=1 。
同理,当要确定
vj=2(t=2) 的值时,对于
i=1,2,3,我们必须考虑三个值,即
vi(1)ai,2 , 于是得到
vj=2(t=2)=0.007 。要确定
vj=3(t=2) 的值时,对于
i=1,2,3,我们必须考虑三个值,即
vi(1)ai,3 , 于是得到
vj=3(t=2)=0.021 , 我们同样用红色实线在下图中标出。而且,还有
ψ2(2)=1,
ψ3(2)=1 。
在接下来的步骤里,我们要确定
vj=1(t=3),
vj=2(t=3),
vj=3(t=3),然后在所有的值中,我们会发现
vj=2(t=3)=0.01764最大,如下图所示,用红色实线标出(当
t=2时,由
j=2,3 发出的路径未画出)。
到此为止,因为我们仅有三个观测值,因此可以结束我们的算法执行,从而知道当观测值序列为
y1=up, y2=up, y3=down 时,最可能的隐状态序列为
q1=1, q2=1, q3=2(这个序列由
ψ给 出),且概率为
0.01764。
HMM在自然语言处理中的应用举例
前面给出的例子都比较简单,不免让人产生一种错觉,以为HMM在实践中难当大任。然而,HMM在语音识别和自然语言处理中的用处非常广泛,而且准确率也相当之高(POS Tagging的准确率可以达到96%以上)。
例如我们现在有一个句子 “time flies like an arrow”. 然后我们可以为每个标注词性,则有“time/Noun flies/Verb like/Prep an/Art arrow/Noun/”。显然,当我们单独来看单词 flies,它可能是一个Noun,也可能是一个Verb,但是如果它前面那个词是形容词,那么它显然是名词的概率更高,而如果它前面的那个词是名词,则它是动词的可能性更高。所以我们就可以建立一个HMM模型,来根据观测到的状态序列(及历史)来预测具体某个词到底是什么词性。其中,单词的词性就是HMM中的隐状态,而我们所看到的具体的每个词就是观测状态。对此有兴趣的读者可以参阅文献[4]以了解HMM在NLP中的更多应用细节。
参考文献
[1] Stuart Russell and Peter Norvig. Artificial Intelligence: A Modern Approach. 3rd Edition.
[2] The University of Melbourne “Web Search and Text Analysis” 课程之幻灯片素材
[3] 同时推荐悉尼科大徐亦达博士的机器学习公开课中关于HMM的部分
[4] Daniel Jurafsky & James H. Martin. Speech and Language Processing, 3rd Edition. Chapter 6