HMM基础
隐马尔科夫模型(Hidden Markov model),HMM是很流行的序列模型,广泛应用在语音识别等领域,也可以用在词性标注、实体识别等文本问题中。
时间序列数据
时间序列数据(time series data)可以认为是沿着时间的维度而变化的数据,列如股价、气温、语音、 文本等。时序的数据它的长度是不确定的,比如两个人说同一句话,可能有的人说的比较快,有的人比较慢。 所以我们在将逻辑回归或者SVM应用在这类数据上实际是会损失一些数据的。
非时序数据比如像图片,一个人的特征等,当我们使用它们的时候,它的维度是固定的。
时序类的模型,从传统机器学习角度来说有HMM、CRF,从深度学习角度来说有RNN、LSTM。
HMM模型介绍
上图是一个HMM模型的经典结构,它由上层的隐变量和下层的观测值组成。隐变量之间的传递叫作状态转移,隐变量到观测值之间的传递叫作状态生成,所以它也是生成模型。
可以看到这个模型是有向的、生成的模型。
HMM是一个概率图模型,在\( t=1 \)时刻:
- \( z_1 \)表示一个状态,但是它有多种状态,表示每种状态有着对应的概率
- \( z_1 \) to \( z_2 \),表示状态的转移,由前一种状态转移到下一种状态也有着对应的概率
- \( z_1 \) to \( x_1 \),表示在这种状态下生成了一个值,这个值也有不同的取值(通常可分为连续和离散值),在这种状态下生成了这种值也有着对应的概率。
由以上介绍不难知道HMM模型存在三大主要问题:
- 一是在已知模型参数的条件下,对于任何一个观测值序列,去推出背后状态转移的序列,这种问题也叫inference 或者decoding。比如说假如这个序列是针对语音识别,那么我们可以根据听到的音乐或人的声音来反推出他到底说了哪些单词或者哪些句子。
- 二是给定观测值,我们去预测出或者估算出整个模型的参数。
- 三是计算某一个观测值序列的边缘概率。
应用举例 Part of Speech Tagging(POS)
当我们的问题变成词性标注时,我们关心的是:给定一句话,知道观测值(单词)\( x_1 到 x_n \)到底是什么词性。可以知道在这个例子里\( z_i \)是离散值。
接下来看我们的三大问题:
- 给定我们句子,我们需要去反推出它每个单词的词性。这个问题也叫inference or decoding问题(怎么解决,维特比算法)
- 给定一句话之后,我们怎么去估计模型的参数。
- \( p(x_1x_2...x_n) \)出现的概率是多少
请看对上面第二个问题的详解:
参数\( \theta = (A,B,\pi) \),
A表示的是词性之间的转换的概率(transition probability):
- A是状态转移概率矩阵,也叫作transiton probability。我们要知道状态之间的转移不是随机发生的,而是更有可能转移到其它的状态里。
- \( A_{m\times m} \),m表示词性(状态)的种类个数,每一行表示一个词性(状态),每一行加起来为1。
- 矩阵里每一个点表示从前一个词性(状态)转换到下一个词性(状态)的概率。
B是生成概率(emission probability):
- 在\( z_1 \)状态下我们生成的单词\( w_1 \)是某种词性的概率,它可以表达为一个概率矩阵
- \( B_{m\times v} \),m表示词性的种类个数,v表示词库的大小,每一行表示每一种词性对应词库里每一个单词的概率,每一行加和为1。
- 矩阵里的每一个点表示在某个状态下(在这个例子中是单词词性)看到一个观测值(在这个例子中是单词)的概率是多少。
- 值得注意的是生成的值也可以是连续值,对于连续型的变量我们是不能写成矩阵的形式的,这时应当借用高斯混合(GMM)模型来处理。
\( \pi \)表示句子里第一个单词(观测值)出现某个词性(状态)的概率:
- 可以理解为\( \pi \)是一个初始化数组,即\( \pi = [\pi_1,\pi_2...\pi_i...\pi_m]\),加和为1
在这个模型中,\( x\to \theta \),这个过程叫预测,parameter estimate ;\( x\to z \),这个过程叫infer
基于为维特比算法的预测
解决inference/decoding 问题:给定\( \theta = (A,B,\pi) \),\( x \)序列,反推出\( z \)
tips:一般给定问题的时候,我们都应该能想到一个最笨的方法,再基于这个方法去思考、不断去优化,这是一般的解题过程。
简单的方法:
假设我们的 \( z_i\in \ { a,b,c} \), 所以我们可以写出所有的状态转移序列,再基于以下公式(1)算出似然概率
$$ p(z_1)p(z_2|z_1)p(z_3|z_2)...p(z_{n-1}|z_n)p(x_1|z_1)p(x_2|z_2)...p(x|z_n)\tag{1} $$
我们可以用上式(1)计算出所以状态转移序列的似然概率,但缺点也是很明显的,就是计算的时间复杂度是指数级的,计算量非常大,所以我得考虑其他更高效的方法,如动态规划。
动态规划算法适合那种刚开始是指数级复杂度。但是我通过存储中间的过程,来减轻计算量,这是动态规划的核心。维特比算法就是这样的一种算法。
但其实在这里维特比算法为什么会有效还有另外的一些因素,就是像HMM这样的模型是有限制条件的,限制条件是我们的隐式变量\( z_i \)只会跟前一个隐式变量\(z_{i-1}\)有联系,只有这样我们才能大大减少计算量。假设我们的\( z_i \)如果满足网状图或是完全图,即每一个节点都和其他节点有联系,这时候即使我们使用维特比算法也降不下来计算量。
维特比算法
下面是用维特比计算过程中的一个流程图:
\( 1-m \)表示每个隐变量可取的状态,一共\( m \)种,\( z_1-z_n \)表示隐变量,同时也对应时间\( t \)
现在利用上图考虑我们的问题,给定一个序列\( x_i \),需要去确定最好的\( z_i \), 也就是需要确定上图中红色线标注的这样的一条最好路径。当我们的路径确定了的时候,我们的\( z_i \)也就确定了。
我们来看看这样的一条路径的其概率怎么计算:
$$ \begin{equation}\begin{split} probability &= p(z_1=2)\cdot p(x_1|z_1=2)\cdot p(z_2=1|z_1=2)\cdot \\ &p(x_2|z_2=1)\cdot... \cdot p(z_n=j|z_{n-1}=j+1)\cdot p(x_n|z_n=j) \end{split}\end{equation}\tag{2} $$
其中,
整个概率计算公式其实由这三部分组成,1其实就是参数\( \pi \),2是transition probability, 3是Observeation model,刚好对应参数\( \theta \)。
接下来用递推公式:
定义 \( \delta_k(i) \) := the score of the best path ending at state i at time k
\( \delta_{k+1}(j) \)只与其前一个状态有关,蓝色的虚线表示可能的转移路径,计算方式如下:
$$ \delta_{k+1}(j) = max \left \{ \begin{array}{c} \delta_{k}(1)+log(p(z_{k+1}=j|z_k=1))+log(p(x_{k+1}=j|z_{k+1}=j))\\ \delta_{k}(2)+log(p(z_{k+1}=j|z_k=2))+log(p(x_{k+1}=j|z_{k+1}=j))\\ \ ......\\ \ \delta_{k}(m)+log(p(z_{k+1}=j|z_k=m))+log(p(x_{k+1}=j|z_{k+1}=j))\tag{3} \end{array} \right. $$
递推公式总结为:
$$ \delta_{k+1}(j) = max_i[\delta_{i}(m)+log(p(z_{k+1}=j|z_k=i))+log(p(x_{k+1}=j|z_{k+1}=j))]\tag{4} $$
其中,\( j \in [1,m] ,i \in [1,m], k+1 \in [1,n] \),时间复杂度为\( O(n\cdot m^2) \)
整个过程是从上到下,从左到由计算(填表),其中最后一列是\( [\delta_{n}(1),\delta_{n}(2)...\delta_{n}(m)] \),选出其中最大的数就是我们的最优路径终点,之后回溯便可确定最终的路径。
在计算的过程中,需要一个栈来记录路径上的节点。由此这个算法结束,但其实这样的过程我们得到的是局部最优,并不是全局最优,得到全局最优还需其他算法(如贪心,但是时间开销非常大)。
HMM中的参数估计
Forward/Backward 算法
Forward/Backward算法在估计HMM参数中扮演很重要的角色。换句话说,在估计HMM参数过程中,会用到Forward/Backward算法的结果。
Forward/Backward算法是为了计算\( p(z_k|x) \)
Forward是为了计算\( p(z_k,x_{1:k}) \)
Backward是为了计算\( p(x_{k+1:n } | z_k) \)
通过贝叶斯我们可以改写
$$ p(z_k|x) = \frac {p(z_k,x)} {p(x)} \varpropto p(z_k,x) \tag{5} $$
在这里无论\( z_k \)怎么取值,都有\( p(x) \)这样的一个概率存在,或者说其实在这里\( p(x) \)就相当于一个常数项。
$$ \begin{equation}\begin{split} p(z_k,x) =& p(x_{k+1:n}|z_k,x_{1:k}) \cdot p(z_k,x_{1:k}) \\ =& p(x_{k+1:n}|z_k) \cdot p(z_k,x_{1:k}) \tag{6} \end{split}\end{equation} $$
\( x_{1:k} \)条件独立于\( x_{k+1:n} \)
式(6)的结果正好是上Forward/Backward的结果
Forward algorithm
为了计算\( p(z_k,x_{1:k}) \),可以穷举,也可以用动态规划的的方式求出递推式,当然这种有前后关系的一般都采用动态规划。
所以我们想要求出这样一个递推式:
$$ p(z_k,x_{1:k}) = something \cdot p(z_{k-1},x_{1:k-1}) \tag{7} $$
So,
$$ \begin{equation}\begin{split} p(z_k,x_{1:k}) =& \sum_{z_{k-1}} p(z_{k-1},z_k,x_{1:k})\\ =& \sum_{z_{k-1}} p(z_{k-1},x_{1:k-1}) \cdot p(z_k|z_{k-1},x_{1:k-1}) \cdot p(x_k|z_k,z_{k-1},x_{1:k-1})\\ =& \sum_{z_k-1} p(z_{k-1},x_{1:k-1}) \cdot p(z_k|z_{k-1}) \cdot p(x_k|z_k)\tag{8} \end{split}\end{equation} $$
- \( x_{1:k-1} \)与\( z_k \)条件独立,故可以删去
- \( z_{k-1},x_{1:k-1} \)与\( x_k \)条件独立,故可以删去
到此,我们已经把递推关系写出来了,如果我们把\( p(z_k,x_{1:k}) \)表示为\( \alpha(z_k) \),那么递推公式可以重新表示为:
$$ \alpha_k(z_k) = \sum_{z_{k-1}} \alpha_{k-1}(z_{k-1}) \cdot p(z_k|z_{k-1}) \cdot p(x_k|z_k)\tag{9} $$
$$ \alpha(z_1) = p(z_1,x) = p(z_1)\cdotp(x_1|z_1)=\pi \cdot B \tag{10} $$
Backward algorithm
Backward algorithm 是从后面向前计算的,与Forward algorithm相反。
同样我们想要求出这样一个递推式:
$$ p(x_{k+1:n}|z_k) = something \cdot p(x_{k+2:n}|z_{k+1}) \tag{11} $$
$$ \begin{equation}\begin{split} p(x_{k+1:n}|z_k) =& \sum_{z_{k+1}} p(x_{k+1:n},z_{k+1}|z_k) \\ =& \sum p(x_{k+2:n}|z_{k+1},x_{k+1},z_k) \cdot p(x_{k+1}|z_{k+1},z_k)\cdot p(z_{k+1}|z_k)\\ =& \sum p(x_{k+2:n}|z_{k+1}) \cdot p(x_{k+1}|z_{k+1})\cdot p(z_{k+1}|z_k) \end{split}\end{equation}\tag{12} $$
- \( x_{k+1},z_k \)与\( x_{k+2:n} \)条件独立,故可以删去
- \( z_k \)与 \( x_{k+1} \)条件独立,故可以删去
到此,我们已经把递推关系写出来了,如果我们把\(p(x_{k+1:n}|z_k)\)表示为\( \beta(z_k) \),那么递推公式可以重新表示为:
$$ \beta_k(z_k) = \sum_{z_{k+1}} \beta_k(z_{k+1}) \cdot p(x_{k+1}|z_{k+1})\cdot p(z_{k+1}|z_k)\tag{13} $$
Ok, 到此为止准备工作已就绪,Forward算法,Backward算法即将在正式的参数估计中会用到
Incomplete and Complete Case
在正式进入HMM参数估计之前,首先来看一个更简单的情况,也就是在样本数据中我们既可以观测到x,也可以观测到z的情况。这时候,参数估计变得格外简单,只需要从数据中统计一下就可以了。
- Complete case: x, z 都知道
- Incomplete Case: 仅知道x
Complete Case
Incomplete Case
在complete情况下,参数估计很简单,那么在incomplete情况下又如何估计呢?因为在incomplete情况下我们并没有观测到变量z, 所以不能简单地做统计。所以,怎么做? 答案是:求期望(expectation)
在HMM中,有两类变量,一种是模型本身的参数,另外一种是隐变量z。而且很难同时对这两类参数求估计,所以采用的一种方法是:把其中一组变量看作是常量(constant),从而估计另外一组变量,以此类推。
具体来讲,把模型参数看作是常量,估计变量z; 把z看作是常量,估计模型参数; 把模型参数看作是常量,估计变量z; 把z看作是常量,估计模型参数, 一直循环到收敛为止。
这里我们使用一种算法,EM算法,EM算法用于估计两个未知量,常用于机器学习算法中,例如K近邻。
例如在这个例子中,\( \theta = { \pi,A,B} \),和参数\( z \)。EM算法流程是估计\( z \),估计\( theta \),估计\( z \),估计\( \theta \)...,直到converge。
EM algorithm
$$ \mathop {argmax}_{\theta}[E_{z|x,\theta}ln p(x,z | \theta)]\tag{14} $$
式(14)分为两步骤:
- E-step: 求出\( Z \)的期望
- M-step: 最大化\( ln p(x,z | \theta) \)
一二步骤依次循环,直到收敛
算法流程可以表示为:
while (not converged):
compute z(expectation)
update pi,A,B
HMM的参数求解
估计\( \pi \)
估计B
估计A
小结
HMM的inference过程实际上是对于序列的预测过程,要用到维特比算法
维特比算法实际上是动态规划算法
HMM的参数估计实际上是模型训练过程,需要估计三类不同的参数
HMM的参数估计过程要用到EM算法,而且EM算法的结果依赖于初始化结果。不同的初始化很可能带来不一样的效果
未完待续....
此为个人学习笔记,不得侵权,不得用于其他途径!