###隐马尔可夫模型的定义
隐马尔可夫模型是关于时序的概率模型,描述由一个隐藏的马尔可夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测而产生观测随机序列的过程。
隐马尔可夫链随机生成的状态的序列,称为状态序列(state sequence);每个状态生成一个观测,而由此产生的观测的随机序列,称为观测序列(observation sequence)。序列的每一个位置又可以看作是一个时刻。
设Q是所有可能的状态的集合,V是所有可能的观测的集合。
Q
=
{
q
1
,
q
2
,
.
.
.
q
N
}
,
V
=
{
v
1
,
v
2
,
.
.
.
v
M
}
Q = \{q_1,q_2,...q_N\}, V = \{v_1,v_2,...v_M\}
Q={q1,q2,...qN},V={v1,v2,...vM}
其中, N N N是可能的状态数, M M M是可能的观测数。状态 q q q是不可见的,观测 v v v是可见的。应用到词性标注系统,词就是 v v v,词性就是 q q q。应用到语音识别系统,语音就是 v v v,语素就是 q q q。
I
I
I是长度为
T
T
T的状态序列,
O
O
O是对应的观测序列。
I
=
{
i
1
,
i
2
,
.
.
.
i
T
}
,
O
=
{
o
1
,
o
2
,
.
.
.
o
T
}
I = \{i_1,i_2,...i_T\}, O = \{o_1,o_2,...o_T\}
I={i1,i2,...iT},O={o1,o2,...oT}
这可以理解为给定了一个词(O)+词性(I)的训练集,于是我们手上有了一个可以用隐马尔可夫模型解决的实际问题。
A为状态转移概率矩阵:
A
=
[
a
i
j
]
N
∗
N
A = [a_{ij}]_{N*N}
A=[aij]N∗N
其中,
a
i
j
=
P
(
i
t
+
1
=
q
j
∣
i
t
=
q
i
)
,
i
=
1
,
2...
,
N
;
j
=
1
,
2
,
.
.
.
N
a_{ij}= P(i_t+1 = q_j|i_t = q_i), i = 1,2...,N; j = 1,2,...N
aij=P(it+1=qj∣it=qi),i=1,2...,N;j=1,2,...N
是在时刻
t
t
t处于状态
q
j
q_j
qj的条件下在时刻t+1转移到状态
q
j
q_j
qj的概率。
这实际在表述一个一阶的HMM,所作的假设是每个状态只跟前一个状态有关。
B是观测概率矩阵:
B
=
[
b
j
(
k
)
]
N
∗
N
B = [b_j(k)]_{N*N}
B=[bj(k)]N∗N
其中,
b
j
(
k
)
=
P
(
o
t
=
v
k
∣
i
t
=
q
j
)
,
k
=
1
,
2...
,
M
;
j
=
1
,
2
,
.
.
.
N
b_j(k)= P(o_t = v_k|i_t = q_j), k = 1,2...,M; j = 1,2,...N
bj(k)=P(ot=vk∣it=qj),k=1,2...,M;j=1,2,...N 是在时刻
t
t
t处于状态
q
j
q_j
qj的条件下生成观测
v
k
v_k
vk的概率,也就是所谓的“发射概率”。
这实际上在作另一个假设,观测是由当前时刻的状态决定的,跟其他因素无关,这有点像Moore自动机。
π
\pi
π是初始状态概率向量:
π
=
(
π
i
)
\pi = (\pi_i)
π=(πi)
其中,
π
i
=
P
(
i
1
=
q
i
)
,
i
=
1
,
2
,
.
.
.
N
\pi_i= P(i_1 = q_i), i= 1,2,...N
πi=P(i1=qi),i=1,2,...N 是时刻t=1处于状态
q
j
q_j
qj的概率。
隐马尔可夫模型由初始状态概率向量
π
\pi
π、状态转移概率矩阵
A
A
A和观测概率矩阵
B
B
B决定。
π
\pi
π和
A
A
A决定状态序列,
B
B
B决定观测序列。因此,隐马尔可夫模型
λ
\lambda
λ可以用三元符号表示,即
λ
=
(
A
,
B
,
π
)
\lambda = (A,B,\pi)
λ=(A,B,π)
A
,
B
,
π
A,B,\pi
A,B,π称为隐马尔可夫模型的三要素。
状态转移概率矩阵 A A A与初始状态概率向量 π π π确定了隐藏的马尔可夫链,生成不可观测的状态序列。观测概率矩阵B确定了如何从状态生成观测,与状态序列综合确定了如何产生观测序列。
从定义可知,隐马尔可夫模型作了两个基本假设:
(1)齐次马尔可夫性假设,即假设隐藏的马尔可夫链在任意时刻t的状态只依赖于其前一时刻的状态,与其他时刻的状态及观测无关。
P
(
i
t
∣
i
t
−
1
,
o
t
−
1
,
.
.
.
i
1
,
o
1
)
=
P
(
i
t
∣
i
t
−
1
)
,
t
=
1
,
2
,
.
.
.
T
P(i_t|i_t-1,o_t-1,...i_1,o_1 ) = P(i_t|i_t-1), t = 1,2,...T
P(it∣it−1,ot−1,...i1,o1)=P(it∣it−1),t=1,2,...T
从上式左右两边的复杂程度来看,齐次马尔可夫性假设简化了许多计算。
(2)观测独立性假设,即假设任意时刻的观测只依赖于该时刻的马尔可夫链的状态,与其他观测及状态无关。
P
(
o
t
∣
i
T
,
o
T
,
i
T
−
1
,
o
T
−
1
,
.
.
.
i
t
,
o
t
,
.
.
.
i
1
,
o
1
)
=
P
(
i
t
∣
o
t
)
P(o_t|i_T,o_T,i_T-1,o_T-1,...i_t,o_t,...i_1,o_1 ) = P(i_t|o_t)
P(ot∣iT,oT,iT−1,oT−1,...it,ot,...i1,o1)=P(it∣ot)
隐马尔可夫模型有3类基本问题:
(1)概率计算
给定模型
λ
=
(
A
,
B
,
π
)
\lambda = (A,B,\pi)
λ=(A,B,π) 和观测序列
O
=
(
o
1
,
o
2
,
.
.
.
o
T
)
O = (o_1,o_2,...o_T)
O=(o1,o2,...oT),计算在观测序列O出现的概率
P
=
(
O
∣
λ
)
P = (O|\lambda)
P=(O∣λ)。
(2)学习问题
己知观测序列
O
=
(
o
1
,
o
2
,
.
.
.
o
T
)
O = (o_1,o_2,...o_T)
O=(o1,o2,...oT),估计模型参数
λ
=
(
A
,
B
,
π
)
\lambda = (A,B,\pi)
λ=(A,B,π),使得在该模型下观测序列概率
P
=
(
O
∣
λ
)
P = (O|\lambda)
P=(O∣λ)最大。即用极大似然估计的方法估计参数。
(3)预测问题
也称为解码问题(decoding)。已知模型
λ
=
(
A
,
B
,
π
)
\lambda = (A,B,\pi)
λ=(A,B,π)和观测序列
O
=
(
o
1
,
o
2
,
.
.
.
o
T
)
O = (o_1,o_2,...o_T)
O=(o1,o2,...oT),求对给定观测序列条件概率
P
=
(
O
∣
λ
)
P = (O|\lambda)
P=(O∣λ)最大的状态序列
I
=
(
i
1
,
i
2
,
.
.
.
i
T
)
I = (i_1,i_2,...i_T)
I=(i1,i2,...iT)。即给定观测序列,求最有可能的对应的状态序列。
概率计算方法
给定模型 λ = ( A , B , π ) \lambda = (A,B,\pi) λ=(A,B,π) 和观测序列 O = ( o 1 , o 2 , . . . o T ) O = (o_1,o_2,...o_T) O=(o1,o2,...oT),,求 P = ( O ∣ λ ) P = (O|\lambda) P=(O∣λ)
直接计算法
直接计算法的思路是枚举所有长度 T T T的状态序列,然后计算该状态序列与观测序列的联合概率,对所有的枚举项求和即可。在状态种类为N的情况下,一共有 N T N^T NT种排列,每种排列计算联合概率的计算量为 T T T,总的复杂度为 O ( T ∗ N T ) O(T*N^T) O(T∗NT)。
直接计算法只是一种理论方法,可以用来解释整个计算过程,而不会被用于计算。因为只需做简单的改进,就能很大程度上地减少运算量。这些改进,只是用到了合并同类项的思想。直接计算法在状态种类为N的情况下,一共有 N T N^T NT种排列。这 N T N^T NT种排列并不都需要从0开始计算,而是可以利用已经计算的结果,减少运算量。这就有了前向算法和后向算法。
假设长度为3的序列,一共有2种状态,分别为A,B。序列AAA和AAB,用直接计算法,这里需要4次乘法。而如果利用AA这个已有状态的结果,再分别计算AAA和AAB,则只有3次乘法。这就是前向和后向算法的基础。
前向算法
给定隐马尔可夫模型
λ
\lambda
λ,定义到时刻
t
t
t为止的观测序列为
o
1
,
o
2
.
.
.
o
t
o_1,o_2...o_t
o1,o2...ot,且状态为
q
t
q_t
qt的概率为前向概率,记作
α
t
(
i
)
=
P
(
o
1
,
o
2
.
.
.
,
o
t
,
i
t
=
q
t
∣
λ
)
\alpha_t(i) = P(o_1,o_2...,o_t, i_t = q_t | \lambda)
αt(i)=P(o1,o2...,ot,it=qt∣λ)
(1) 初始状态,
t
=
0
t = 0
t=0时刻
α
1
(
i
)
=
π
i
b
i
(
o
1
)
,
i
=
1
,
2
,
.
.
.
N
\alpha_1(i) = \pi_ib_i(o_1), i = 1,2,...N
α1(i)=πibi(o1),i=1,2,...N
初始状态有N种可能,所以这个概率有N个。
前向概率的定义限定了两个条件,一是到当前为止的观测序列,另一个是当前的状态。所以初值的计算也有两项,一项是初始状态概率,另一项是发射到当前观测的概率。
(2)
t
=
2
,
3
,
.
.
.
T
−
1
t = 2,3,... T-1
t=2,3,...T−1时刻
α
t
+
1
(
i
)
=
[
∑
j
=
1
N
α
t
(
j
)
a
j
i
]
∗
b
i
(
o
t
+
1
)
,
i
=
1
,
2
,
.
.
.
N
\alpha_{t+1}(i) = [\sum_{j=1}^N \alpha_t(j) a_{ji}] *b_i(o_{t+1}), i = 1,2,...N
αt+1(i)=[j=1∑Nαt(j)aji]∗bi(ot+1),i=1,2,...N
整个计算过程分两部分,第一部分是到当前状态转移概率,第二部分是到观测序列的发射概率。
α t ( j ) \alpha_t(j) αt(j)表示t时刻的概率,一共有 N N N项。 j j j表示t时刻的状态,而 i i i表示 t + 1 t+1 t+1时刻的状态,所以 j = 1 , 2 , . . . N j=1,2,...N j=1,2,...N, i = 1 , 2 , . . . N i=1,2,...N i=1,2,...N。那么从状态 j j j到状态 i i i,需要计算 N 2 N^2 N2次。如果这个状态序列有 T T T时刻,则复杂度为 O ( T N 2 ) O(TN^2) O(TN2),远小于直接计算法的 O ( T N T ) O(TN^T) O(TNT)。
(3)最终状态
t
=
T
t =T
t=T时刻
p
(
O
∣
λ
)
=
∑
i
=
1
N
α
T
(
i
)
p(O|\lambda) = \sum_{i=1}^N\alpha_T(i)
p(O∣λ)=i=1∑NαT(i)
从
t
=
T
−
1
t = T-1
t=T−1 到
t
=
T
t = T
t=T,一共有
N
N
N种状态可以到达目标状态,需要求和
参考代码如下。 N N N表示状态数, T T T是时间数, A A A是转移矩阵, B B B是发射矩阵, F F F对应 α \alpha α。
def _forward(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
F = np.zeros((N,T))
F[:,0] = self.pi * self.B[:, obs_seq[0]]
for t in range(1, T):
for n in range(N):
F[n,t] = np.dot(F[:,t-1], (self.A[:,n])) * self.B[n, obs_seq[t]]
return F
后向算法
给定隐马尔可夫模型
λ
\lambda
λ,定义时刻
t
t
t的状态为
q
t
q_t
qt,且从时刻
t
+
1
t+1
t+1到时刻
T
T
T为止的观测序列为
o
t
+
1
,
o
t
+
2
.
.
.
o
T
o_{t+1},o_{t+2}...o_T
ot+1,ot+2...oT的概率为后向概率,记作
β
t
(
i
)
=
P
(
o
t
+
1
,
o
t
+
2
.
.
.
,
o
T
∣
i
t
=
q
t
,
λ
)
\beta_t(i) = P(o_{t+1},o_{t+2}...,o_T | i_t = q_t , \lambda)
βt(i)=P(ot+1,ot+2...,oT∣it=qt,λ)
(1) 初始状态,
t
t
t =
T
T
T时刻
β
1
(
i
)
=
1
,
i
=
1
,
2
,
.
.
.
N
\beta_1(i) = 1, i = 1,2,...N
β1(i)=1,i=1,2,...N
因为从
t
=
T
+
1
t = T+1
t=T+1时刻到
t
=
T
t = T
t=T 时刻的概率并不存在,默认为1.
(2)
t
=
T
−
1
,
T
−
2...2
,
1
t = T-1, T-2... 2,1
t=T−1,T−2...2,1 时刻
β
t
(
i
)
=
∑
j
=
1
N
β
t
+
1
(
j
)
∗
b
j
(
O
t
+
1
)
∗
a
j
i
,
i
=
1
,
2
,
.
.
.
N
\beta_t(i) = \sum_{j=1} ^N \beta_{t+1}(j) * b_j(O_{t+1}) * a_{ji}, i = 1,2,...N
βt(i)=j=1∑Nβt+1(j)∗bj(Ot+1)∗aji,i=1,2,...N
(3) 最终状态,
t
=
0
t = 0
t=0 时刻
p
(
O
∣
λ
)
=
∑
i
=
1
N
β
1
(
i
)
∗
b
i
(
O
1
)
∗
a
j
i
p(O|\lambda) = \sum_{i = 1}^N \beta_1(i) * b_i(O_1) * a_{ji}
p(O∣λ)=i=1∑Nβ1(i)∗bi(O1)∗aji
在
t
t
t= 1时间点上有
N
N
N种后向概率都能输出从
1
1
1到
T
T
T的观测序列,乘以对应的初始概率,再乘以输出
O
1
O1
O1的概率后,求和得到最终结果
参考代码如下。 N N N表示状态数, T T T是时间数, A A A是转移矩阵, B B B是发射矩阵, X X X对应 β \beta β。注意这里求和方式与前向方法的区别。前向算法里面发射概率是当前层的下标 i i i,后向算法里发射概率是后一层的下标 j j j。前向算法求和符号不包括发射概率,而后项算法的求和概率包括了发射概率。
def _backward(self, obs_seq):
N = self.A.shape[0]
T = len(obs_seq)
X = np.zeros((N,T))
X[:,-1:] = 1
for t in reversed(range(T-1)):
for n in range(N):
X[n,t] = np.sum(X[:,t+1] * self.A[n,:] * self.B[:, obs_seq[t+1]])
return X