目录
- 一、马尔可夫模型
-
- 1. 马尔可夫性
- 2. 马尔可夫链
- 3. 马尔可夫链案例
- 二、隐马尔可夫模型HMM
-
- 1. named entity recognition(命名实体识别)问题概述
- 2. 什么是隐马尔可夫模型 a . k . a . H M M ? a.k.a.HMM? a.k.a.HMM?
- 3. HMM模型的参数
- 4. 用HMM解决序列标注问题, HMM的学习算法
- 三、维特比算法(Viterbi Algorithm)(HMM的预测算法)
- 四、代码实现
一、马尔可夫模型
1. 马尔可夫性
设 { X ( t ) , t ∈ T } \{X(t), t ∈ T\} {X(t),t∈T}是一个随机过程,E为其状态空间,若对于任意的 t 1 < t 2 < . . . < t n < t t_1t1<t2<...<tn<t,任意的 x 1 , x 2 , . . . , x n , x ∈ E x_1,x_2,...,x_n,x∈E x1,x2,...,xn,x∈E,随机变量 X ( t ) X(t) X(t)在已知变量 X ( t 1 ) = x 1 , . . . , X ( t n ) = x n X(t_1)=x_1,...,X(t_n)=x_n X(t1)=x1,...,X(tn)=xn之下的条件分布函数只与 X ( t n ) = x n X(t_n)=x_n X(tn)=xn有关,而与 X ( t 1 ) = x 1 , . . . , X ( t n − 1 ) = x n − 1 X(t_1)=x_1,...,X(t_{n-1})=x_{n-1} X(t1)=x1,...,X(tn−1)=xn−1无关,即条件分布函数满足下列等式,此性质称为马尔可夫性;如果随机过程满足马尔可夫性,则该过程称为马尔可夫过程。
连续变量: p ( x ( t ) ≤ x ∣ X ( t 1 ) = x 1 , . . . , X ( t n ) = x n ) = p ( X ( t ) ≤ x ∣ X ( t n ) = x n ) p(x(t)\le x|X(t_1)=x_1,...,X(t_n)=x_n)=p(X(t)\le x|X(t_n)=x_n) p(x(t)≤x∣X(t1)=x1,...,X(tn)=xn)=p(X(t)≤x∣X(tn)=xn)
离散变量: p ( x n + 1 ≤ x ∣ X 1 = x 1 , . . . , X n = x n ) = p ( X n + 1 = x ∣ X n = x n ) p(x_{n+1}\le x|X_1=x_1,...,X_n=x_n)=p(X_{n+1}= x|X_n=x_n) p(xn+1≤x∣X1=x1,...,Xn=xn)=p(Xn+1=x∣Xn=xn)
2. 马尔可夫链
- 马尔可夫链是指具有马尔可夫性质的随机过程。在过程中,在给定当前信息的情况下,过去的信息状态对于预测将来状态是无关的。
- 马尔可夫链在马尔可夫链的每一步,系统根据概率分布,可以从一个状态变成另外一个状态,也可以保持当前状态不变。状态的改变叫做转移,状态改变的相关概率叫做转移概率。
- 马尔可夫链中的三元素是:状态空间 S S S、转移概率矩阵 P P P、初始概率分布 π π π。
3. 马尔可夫链案例
设将天气状态分为晴、阴、雨三种状态,假定某天的天气状态只和上一天的天气状态有关,状态使用1(晴)、2(阴)、3(雨)表示,转移概率矩阵 P P P如下:
今/明 |
晴 |
阴 |
雨 |
晴 |
0.75 |
0.125 |
0.125 |
阴 |
0.5 |
0.25 |
0.25 |
雨 |
0.25 |
0.5 |
0.25 |
- 第n+1天天气状态为j的概率为:
π ( X n + 1 = j ) = ∑ i = 1 k π ( X n = i ) ⋅ P ( X n + 1 ∣ X n = j ) ⇒ π n + 1 = π n ⋅ P \pi(X_{n+1}=j)=\sum^k_{i=1}\pi(X_n=i)·P(X_{n+1}|X_n=j) \Rightarrow \pi^{n+1}=\pi^n·P π(Xn+1=j)=∑i=1kπ(Xn=i)⋅P(Xn+1∣Xn=j)⇒πn+1=πn⋅P
- 因此,矩阵P即为条件概率转移矩阵。
矩阵P的第 i i i行元素表示,在上一个状态为i的时候的分布概率,即每行元素的和必须为1。
初始概率: π = [ 0.5 , 0.3 , 0.2 ] π=[0.5,0.3,0.2] π=[0.5,0.3,0.2]
转移概率矩阵: P = [ 0.75 0.125 0.125 0.5 0.25 0.25 0.25 0.5 0.25 ] P=\left[ \begin{matrix} 0.75&0.125&0.125 \\ 0.5&0.25&0.25 \\ 0.25&0.5&0.25 \end{matrix} \right] P=⎣⎡0.750.50.250.1250.250.50.1250.250.25⎦⎤
第n天 |
晴 |
阴 |
雨 |
0 |
0.5 |
0.3 |
0.2 |
1 |
0.575 |
0.2375 |
0.1875 |
2 |
0.5969 |
0.225 |
0.1781 |
3 |
0.6047 |
0.2199 |
0.1754 |
4 |
0.6073 |
0.2183 |
0.1744 |
5 |
0.6082 |
0.2177 |
0.1741 |
6 |
0.6085 |
0.2175 |
0.174 |
7 |
0.6086 |
0.2174 |
0.1739 |
8 |
0.6087 |
0.2174 |
0.1739 |
9 |
0.6087 |
0.2174 |
0.1739 |
10 |
0.6087 |
0.2174 |
0.1739 |
11 |
0.6087 |
0.2174 |
0.1739 |
当初始概率: π = [ 0.1 , 0.6 , 0.3 ] π=[0.1,0.6,0.3] π=[0.1,0.6,0.3]
第n天 |
晴 |
阴 |
雨 |
0 |
0.1 |
0.6 |
0.3 |
1 |
0.45 |
0.3125 |
0.2375 |
2 |
0.5531 |
0.2531 |
0.1937 |
3 |
0.5898 |
0.2293 |
0.1809 |
4 |
0.6022 |
0.2215 |
0.1763 |
5 |
0.6065 |
0.2188 |
0.1747 |
6 |
0.6079 |
0.2179 |
0.1742 |
7 |
0.6084 |
0.2176 |
0.174 |
8 |
0.608 |
6 0.2174 |
0.1739 |
9 |
0.6087 |
0.2174 |
0.1739 |
10 |
0.6087 |
0.2174 |
0.1739 |
11 |
0.6087 |
0.2174 |
0.1739 |
可以发现,无论初始概率设置为多少(不为0),经过很多次迭代,第n天晴、阴、雨的概率会趋于一个稳定的相同数值。
二、隐马尔可夫模型HMM
自然语言处理中的序列标注问题, 目前比较主流的技术是语言模型(如LSTM, BERT)+CRF(条件随机场), 要了解CRF(条件随机场), 需要首先了解隐马尔可夫模型(Hidden Markov Model), HMM是一种概率图模型, 只要理解了HMM模型和维特比解码算法(viterbi algorothm), 理解条件随机场就比较简单了。
1. named entity recognition(命名实体识别)问题概述
命名实体识别(英语:Named Entity Recognition,简称NER), 是指识别文本中具有特定意义的实体,主要包括人名、地名、机构名、专有名词等等, 并把需要识别的词在文本序列中标注出来。
例如有一段文本: 上海市成立自由贸易试验区.
要在上面文本中识别一些区域和地点, 那么需要识别出来内容有:
上海市(地点), 自由贸易试验区(地点).
在使用的NER数据集中, 一共有7个标签:
- “B-ORG”: 组织或公司(organization)
- “I-ORG”: 组织或公司
- “B-PER”: 人名(person)
- “I-PER”: 人名
- “O”: 其他非实体(other)
- “B-LOC”: 地名(location)
- “I-LOC”: 地名
文本中以每个字为单位, 每个字必须分别对应上面的任一标签。
但为什么上面标签除了"O"(其他)之外都是一个实体类型对应两个标签呢?
请小伙伴们仔细看标签前面有分为"B"和"I"的不同, "B"表示begin, 实体开头的那个字使用"B"对应的标签来标注, 在实体中间或结尾的部分, 用"I"来标注。
比如说"自贸区"对应的标注是: 自(B-LOC)贸(I-LOC)区(I-LOC), 这三个字都对应一个"地名"的标签, 但是第一个字属于实体开头的字, 所以使用"B"开头的标签, 后面两个字的标签都是"I"开头。
注意, "B"后面是不可以跟其他类型的"I"的, 例如: 自(B-PER)贸(I-LOC)区(I-LOC) 就是属于错误的标注, 因为实体开头"B"标注成了人名, 即使实体中间标注成了地名, 这个实体的标注方法也是非法的。
上面的原因就是要从语言模型(例如BERT, LSTM)后面再加上概率图模型, 例如条件随机场, 用来约束模型的输出, 防止出现不合规的标注输出。
2. 什么是隐马尔可夫模型 a . k . a . H M M ? a.k.a.HMM? a.k.a.HMM?
HMM模型是概率图模型的一种, 属于生成模型, 笼统的说, 上面说的"BIO"的实体标签, 就是一个不可观测的隐状态, 而HMM模型描述的就是由这些隐状态序列(实体标记)生成可观测状态(可读文本)的过程。
在本文的问题当中, 隐状态序列是实体标记序列, 而可观测序列是可读的原始语料文本序列。
例如:
隐藏状态序列: B − L O C ∣ I − L O C ∣ I − L O C B-LOC | I-LOC | I-LOC B−LOC∣I−LOC∣I−LOC
观测状态序列: 自 贸 区 自 \quad \quad \quad \quad 贸 \quad \quad \quad \quad 区 自贸区
设的可观测状态序列是由所有汉字组成的集合, 用 V O b s e v a t i o n V_{Obsevation} VObsevation来表示:
V o b s . = { v 1 , v 2 , . . . , v M } V_{obs.}=\{v_1, v_2, ... , v_M \} Vobs.={v1,v2,...,vM}
上式中, v v v表示字典中单个字, 假设已知的字数为 M M M。
设所有可能的隐藏状态集合为 Q h i d d e n Q_{hidden} Qhidden, 一共有 N N N种隐藏状态, 例如现在的命名实体识别数据里面只有7种标签:
Q h i d d e n = { q 1 , q 2 , . . . , q N } Q_{hidden} = \{ q_1, q_2, ... , q_N\} Qhidden={q1,q2,...,qN}
设有观测到的一串自然语言序列文本 O O O, 一共有 T T T个字, 又有这段观测到的文本所对应的实体标记, 也就是隐状态 I I I:
I = { i 1 , i 2 , . . . , i T } ( 隐 状 态 ) O = { o 1 , o 2 , . . . , o T } ( 观 测 ) I=\{i_1, i_2, ... , i_T \}(隐状态) \quad O=\{o_1, o_2, ... , o_T \}(观测) I={i1,i2,...,iT}(隐状态)O={o1,o2,...,oT}(观测)
注意上式中,常称 t t t为时刻, 如上式中一共有 T T T个时刻( T T T个汉字)。
HMM模型有两个基本假设(非常重要):
- 第 t t t个隐状态(实体标签)只跟前一时刻的 t − 1 t-1 t−1隐状态(实体标签)有关, 与除此之外的其他隐状态(如 t − 2 , t + 3 t-2,\ t+3 t−2, t+3)无关。
例如上图中: 蓝色的部分指的是 i t i_t it只与 i t − 1 i_{t-1} it−1有关, 而与蓝色区域之外的所有内容都无关, 而 P ( i t ∣ i t − 1 ) P(i_{t}|i_{t-1}) P(it∣it−1)指的是隐状态 i i i从 t − 1 t-1 t−1时刻转向 t t t时刻的概率, 具体转换方式下面会细讲。
- 观测独立的假设, 上面说过, HMM模型中是由隐状态序列(实体标记)生成可观测状态(可读文本)的过程,
观测独立假设是指在任意时刻观测 o t o_t ot只依赖于当前时刻的隐状态 i t i_t it, 与其他时刻的隐状态无关。
例如上图中: 粉红色的部分指的是 i t + 1 i_{t+1} it+1只与 o t + 1 o_{t+1} ot+1有关, 跟粉红色区域之外的所有内容都无关。
3. HMM模型的参数
- HMM的转移概率(transition probabilities):
上面提到了 P ( i t ∣ i t − 1 ) P(i_{t}|i_{t-1}) P(it∣it−1)指的是隐状态 i i i从 t − 1 t-1 t−1时刻转向 t t t时刻的概率, 比如现在实体标签一共有 7 7 7种, 也就是 N = 7 N=7 N=7(注意 N N N是所有可能的实体标签种类的集合), 也就是 Q h i d d e n = { q 0 , q 1 , . . . , q 6 } Q_{hidden} = \{ q_0, q_1, ... , q_6\} Qhidden={q0,q1,...,q6}(注意实体标签编号从 0 0 0算起), 假设在 t − 1 t-1 t−1时刻任何一种实体标签都可以在 t t t时刻转换为任何一种其他类型的实体标签, 则总共可能的转换的路径一共有 N 2 N^2 N2种, 所以可以做一个 N ∗ N N*N N∗N的矩阵来表示所有可能的隐状态转移概率。
上图就是转移概率矩阵, 也就是 t r a n s i t i o n m a t r i x transition \ matrix transition matrix, 设这个矩阵为 A A A矩阵, 则 A i j A_{ij} Aij表示矩阵中第i行第j列:
A i j = P ( i t + 1 = q j ∣ i t = q i ) q i ∈ Q h i d d e n A_{ij}=P(i_{t+1}= q_j | i_{t} = q_i) \quad q_i \in Q_{hidden} Aij=P(it+1=qj∣it=qi)qi∈Qhidden
上式表示指的是在 t t t时刻实体标签为 q i q_i qi, 而在 t + 1 t+1 t+1时刻实体标签转换到 q j q_j qj的概率。
- HMM的发射概率(emission probabilities):
之前提到了任意时刻观测 o t o_t ot只依赖于当前时刻的隐状态 i t i_t it, 也就是 P ( o t ∣ i t ) P(o_t | i_t) P(ot∣it), 也叫做发射概率, 指的是隐状态生成观测结果的过程。
设字典里有 M M M个字, V o b s . = { v 0 , v 1 , . . . , v M − 1 } V_{obs.}=\{v_0, v_1, ... , v_{M-1} \} Vobs.={v0,v1,...,vM−1}(注意这里下标从0算起, 所以最后的下标是 M − 1 M-1 M−1, 一共有 M M M种观测), 则每种实体标签(隐状态)可以生成 M M M种不同的汉字(也就是观测), 这一过程可以用一个发射概率矩阵来表示, 他的维度是 N ∗ M N*M N∗M。
上图就是发射概率矩阵, 也就是 e m i s s i o n m a t r i x emission \ matrix emission matrix, 设这个矩阵为 B B B矩阵, 则 B j k B_{jk} Bjk表示矩阵中第 j j j行第 k k k列:
B j k = P ( o t = v k ∣ i t = q j ) q i ∈ Q h i d d e n v k ∈ V o b s . = { v 0 , v 1 , . . . , v M − 1 } B_{jk}=P(o_{t}= v_k | i_{t} = q_j) \quad q_i \in Q_{hidden} \quad v_k \in V_{obs.}=\{v_0, v_1, ... , v_{M-1} \} Bjk=P(ot=vk∣it=qj)qi∈Qhiddenvk∈Vobs.={v0,v1,...,vM−1}
上式表示指的是在 t t t时刻由实体标签(隐状态) q j q_j qj生成汉字(观测结果) v k v_k vk的概率。
- HMM的初始隐状态概率: 又称为 i n i t i a l p r o b a b i l i t i e s initial \ probabilities initial probabilities, 通常用 π \pi π来表示, 注意这里可不是圆周率:
π = P ( i 1 = q i ) q i ∈ Q h i d d e n = { q 0 , q 1 , . . . , q N − 1 } \pi=P(i_1=q_i) \quad q_i \in Q_{hidden} = \{ q_0, q_1, ... , q_{N-1}\} π=P(i1=qi)qi∈Qhidden={q0,q1,...,qN−1}
上式指的是自然语言序列中第一个字 o 1 o_1 o1的实体标记是 q i q_i qi的概率, 也就是初始隐状态概率。
4. 用HMM解决序列标注问题, HMM的学习算法
现在已经了解了HMM的三大参数 A , B , π A, \ B, \ \pi A, B, π, 假设已经通过建模学习, 学到了这些参数(学习算法见笔记二), 得到了模型的概率, 怎么使用这些参数来解决序列标注问题呢?
设目前在时刻 t t t, 有当前时刻的观测到的一个汉字 o t = v k o_t=v_k ot=vk(指的第 t t t时刻观测到 v k v_k vk), 假设还知道在 t − 1 t-1 t−1时刻(前一时刻)对应的实体标记类型 i t − 1 = q ^ i t − 1 i_{t-1} = \hat{q}^{t-1}_i it−1=q^it−1(指的 t − 1 t-1 t−1时刻标记为 q ^ i t − 1 \hat{q}^{t-1}_i q^it−1)。要做的仅仅是列举所有 i t i_{t} it可能的实体标记 q ^ j t \hat{q}^{t}_{j} q^jt, 并求可以使下式输出值最大的那个实体类型 q j t q^{t}_{j} qjt(也就是隐状态类型):
q ^ j t = a r g m a x q ^ j t ∈ Q h i d d e n P ( i t = q ^ j t ∣ i t − 1 = q ^ i t − 1 ) P ( o t = v k ∣ i t = q ^ j t ) \hat{q}_j^{t} = argmax_{\hat{q}_j^{t} \in Q_{hidden}} P(i_t = \hat{q}_j^{t} | i_{t-1} = \hat{q}^{t-1}_i) P(o_t=v_k| i_t = \hat{q}_j^{t}) q^jt=argmaxq^jt∈QhiddenP(it=q^jt∣it−1=q^it−1)P(ot=vk∣it=q^jt)
将所有 t t t时刻当前可取的实体标签带入下式中, 找出一个可以使下式取值最大的那个实体标签作为当前字的标注:
P ( 当 前 可 取 实 体 标 签 ∣ 上 一 时 刻 实 体 标 签 ) P ( 测 到 的 汉 字 ∣ 当 前 可 取 实 体 标 签 ) P(当前可取实体标签|上一时刻实体标签)P(测到的汉字|当前可取实体标签) P(当前可取实体标签∣上一时刻实体标签)P(测到的汉字∣当前可取实体标签)
注意: 这里只讲到了怎样求第 t t t时刻的最优标注, 但是在每一时刻进行这样的计算, 并不一定能保证最后能得出全局最优序列路径, 例如在第 t t t时刻最优实体标签是 q j q_j qj, 但到了下一步, 由于从 q j q_j qj转移到其他某些实体标签的转移概率比较低, 而降低了经过 q j q_j qj的路径的整体概率, 所以到了下一时刻最优路径就有可能在第 t t t时刻不经过 q j q_j qj了, 所以每一步的局部最优并不一定可以达成全局最优, 所以之后会用到维特比算法来找到全局最优的标注序列, 这个后面会有详细讲解。
生成模型与判别模型:
对于生成模型与判别模型, 因为篇幅问题, 暂不做讲述, 网上有很多资料。
这里稍稍回顾一下, 假设 x x x为数据点, y y y为数据标记, 比如说逻辑回归属于典型的判别模型, 要计算 P ( y ∣ x ) P(y|x) P(y∣x)并形成一条分类边界, 而在HMM中, 计算的是 P ( x ∣ y ) P(x|y) P(x∣y), 而且要计算出所有 y y y可取的类型, 并比较一下所有 P ( x ∣ y = y i ) P(x|y=y_{i}) P(x∣y=yi)的结果, 并取可以使 P ( x ∣ y ) P(x|y) P(x∣y)最大的那个, 而得到预测结果.
HMM参数学习(监督学习):
今天要用HMM解决的是序列标注问题, 所以解决的是监督学习的问题。也就是说现在有一些文本和与之对应的标注数据, 要训练一个HMM来拟合这些数据, 以便之后用这个模型进行数据标注任务, 最简单的方式是直接用极大似然估计来估计参数:
- 初始隐状态概率 π \pi π的参数估计:
π ^ q i = c o u n t ( q i 1 ) c o u n t ( o 1 ) \hat{\pi}_{q_i}=\frac{count(q^{1}_{i})}{count(o_1)} π^qi=count(o1)count(qi1)
上式指的是, 计算在第 1 1 1时刻, 也就是文本中第一个字, q i 1 q^{1}_{i} qi1出现的次数占总第一个字 o 1 o_1 o1观测次数的比例, q i 1 q^{1}_{i} qi1上标1指的是第1时刻, 下标 i i i指的是第 i i i种标签(隐状态), c o u n t count count是的是记录次数。
- 转移概率矩阵 A A A的参数估计:
之前提到过 t r a n s i t i o n m a t r i x transition \ matrix transition matrix里面 A i j A_{ij} Aij(矩阵的第i行第j列)指的是在 t t t时刻实体标签为 q i q_i qi, 而在 t + 1 t+1 t+1时刻实体标签转换到 q j q_j qj的概率, 则转移概率矩阵的参数估计相当与一个二元模型 b i g r a m bigram bigram, 也就是把所有的标注序列中每相邻的两个实体标签分成一组, 统计他们出现的概率:
A ^ i j = P ( i t + 1 = q j ∣ i t = q i ) = c o u n t ( q i 后 面 出 现 q j 的 次 数 ) c o u n t ( q i 的 次 数 ) \hat{A}_{ij}=P(i_{t+1}= q_j | i_{t} = q_i)=\frac{count(q_i后面出现q_j的次数)}{count(q_i的次数)} A^ij=P(it+1=qj∣it=qi)=count(qi的次数)count(qi后面出现qj的次数)
- 发射概率矩阵 B B B的参数估计:
提到过 e m i s s i o n m a t r i x emission \ matrix emission matrix中的 B j k B_{jk} Bjk(矩阵第j行第k列)指的是在 t t t时刻由实体标签(隐状态) q j q_j qj生成汉字(观测结果) v k v_k vk的概率。
B ^ j k = P ( o t = v k ∣ i t = q j ) = c o u n t ( q j 与 v k 同 时 出 现 的 次 数 ) c o u n t ( q j 出 现 的 次 数 ) \hat{B}_{jk}=P(o_{t}= v_k | i_{t} = q_j)=\frac{count(q_j与v_k同时出现的次数)}{count(q_j出现的次数)} B^jk=P(ot=vk∣it=qj)=count(qj出现的次数)count(qj与vk同时出现的次数)
到此为止, 就可以遍历所有语料, 根据上面的方式得到模型的参数 A , B , π A, \ B, \ \pi A, B, π的估计。
注意, 通过上面的计算过程, 可以得出HMM的参数 ( A , B , π ) (A, B, \pi) (A,B,π)有以下特性:
∑ i π q i = 1 \sum_{i}\pi_{q_i} = 1 i∑πqi=1
∑ j A i j = ∑ j P ( i t + 1 = q j ∣ i t = q i ) = 1 \sum_{j}A_{ij} = \sum_{j}P(i_{t+1}= q_j | i_{t} = q_i) = 1 j∑Aij=j∑P(it+1=qj∣it=qi)=1
∑ k B j k = ∑ k P ( o t = v k ∣ i t = q j ) = 1 \sum_{k}B_{jk} = \sum_{k}P(o_{t}= v_k | i_{t} = q_j) =1 k∑Bjk=k∑P(ot=vk∣it=qj)=1
三、维特比算法(Viterbi Algorithm)(HMM的预测算法)
维特比算法 v i t e r b i a l g o r i t h m viterbi \ algorithm viterbi algorithm使用了动态规划算法来解决类似HMM和CRF的预测问题, 用维特比算法可以找到概率最大路径, 也就是最优路径, 在今天要解决的序列标注问题中, 就要通过维特比算法, 来找到文本所对应的最优的实体标注序列。
如果用一句话来概括维特比算法, 那就是:
在每一时刻, 计算当前时刻落在每种隐状态的最大概率, 并记录这个最大概率是从前一时刻哪一个隐状态转移过来的, 最后再从结尾回溯最大概率, 也就是最有可能的最优路径。 这话对于没有学过维特比算法的同学是无法理解的, 但是我觉得今天学完维特比算法之后再来看这句话, 可以加深记忆。
这里为了学习维特比方便, 所以转换一下标签:
- A i , j t − 1 , t A_{i, j}^{t-1, t} Ai,jt−1,t, 是转移概率矩阵 A A A中的第 i i i行第 j j j列(下标), 指的是在 t − 1 t-1 t−1时刻实体标签为 q i q_i qi, 而在 t t t时刻实体标签转换到 q j q_j qj的概率。
- B j k B_{jk} Bjk是发射矩阵的第j行第k列, 指的是在第 t t t时刻, 由隐状态 q j q_j qj生成观测 v k v_k vk的概率。
- 有了上面两点, 则 q ^ j = A i j B j k \hat{q}_j = A_{ij}B_{jk} q^j=AijBjk表示在 t t t时刻的隐状态 q j q_j qj得到的观测结果 v k v_k vk的概率估计。
在这里直接以实例的方式来说明维特比算法的计算过程(注意在这里下标从 0 0 0开始算起):
- 假设现在有所有可能的观测结果的集合 V o b s . = { v 0 , v 1 } V_{obs.}=\{v_0, v_1\} Vobs.={v0,v1};
- 所有可能的隐状态的集合 Q h i d d e n = { q 0 , q 1 , q 2 } Q_{hidden}=\{q_0, q_1, q_2\} Qhidden={q0,q1,q2};
- 已经观测到的观测结果序列 O = ( o 1 = v 0 , o 2 = v 1 , o 3 = v 0 ) O=(o_1=v_0, \ o_2=v_1, \ o_3 = v_0) O=(o1=v0, o2=v1, o3=v0);
- 然后假设通过HMM建模并学习, 得到了模型所估计的参数 ( A , B , π ) (A, B, \pi) (A,B,π), 注意下面的 A , B A, B A,B矩阵按行求和为 1 1 1;
- 要求出对应当前观测结果 O O O的最有可能的隐状态序列 I = ( i 0 , i 1 , i 2 ) I=(i_0, i_1, i_2) I=(i0,i1,i2)。
现在要初始化两个暂存表格, 来暂存在每一时刻的计算结果, 稍后会说明怎么使用这两个表, 下面看到T1表格和T2表格, 他们的规格都是 n u m _ h i d d e n _ s t a t e s ∗ s e q u e n c e _ l e n g t h num\_hidden\_states * sequence\_length num_hidden_states∗sequence_length, 这两个表格在每一时刻 t t t都由 3 3 3个方块组成, 3 3 3是所有可能隐状态的个数, 即 ∣ Q h i d d e n ∣ = 3 |Q_{hidden}|=3 ∣Qhidden∣=3, 注意这里表格内填充的颜色无意义, 只有好看的作用。
计算过程:
- 首先有初始隐状态概率矩阵 π \pi π, 和第1时刻的观测结果 o 1 = v 0 o_1=v_0 o1=v0, 则在第一时刻, 由隐状态生成观测结果的概率计算可以写成 q j t = 1 = π j B j k q_j^{t=1} = \pi_{j}B_{jk} qjt=1=πjBjk。
现在说明 T 1 , T 2 T1, T2 T1,T2表格的用途: 如果 T 1 , T 2 T1, T2 T1,T2表格是 i ∗ j i*j i∗j的矩阵, 则矩阵中第 j j j列指的是第 j j j时刻, 第 i i i行指的是第 i i i种隐状态, T 1 [ i , j ] T1[i, \ j] T1[i, j]指的是在第 j j j时刻, 落到隐状态 i i i的最大可能的概率是多少(不要着急, 到了下一个时刻就会明白最大是什么意思), 而 T 2 [ i , j ] T2[i, \ j] T2[i, j]记录的是这个最大可能的概率是从第 j − 1 j-1 j−1时刻(上一时刻)的哪一种隐状态 i i i转移过来的, 也就是说记录的是最大可能的概率的转移路径。
现在将第一时刻的计算结果填入 T 1 , T 2 T1, T2 T1,T2表格, 注意在第 0 0 0时刻的隐状态是由初始隐状态概率矩阵提供的, 而不是从上一时刻的隐状态转移过来的, 所以直接在 T 2 T2 T2表格上记为 N A N ( n o t a n u m b e r ) NAN(not \ a \ number) NAN(not a number)
- 现在来到第 1 1 1时刻(时刻下标从 0 0 0起算), 首先先计算 T 1 [ i = 0 , j = 1 ] T1[i=0, j=1] T1[i=0,j=1](也就是第 j = 1 j=1 j=1时刻, 落到隐状态 i = q 0 i=q_0 i=q0上的最大可能的概率是多少), 可以看出, 从上一时刻到当前时刻, 要想让当前时刻的隐状态为 i 1 = q 0 i_1=q_0 i1=q0, 则有3条路径可走, 分别是: ( i 0 = q 0 , i 1 = q 0 ) , ( i 0 = q 1 , i 1 = q 0 ) , ( i 0 = q 2 , i 1 = q 0 ) (i_0=q_0, i_1=q_0), \ (i_0=q_1, i_1=q_0), \ (i_0=q_2, i_1=q_0) (i0=q0,i1=q0), (i0=q1,i1=q0), (i0=q2,i1=q0),
在 T 1 [ i = 0 , j = 1 ] T1[i=0, j=1] T1[i=0,j=1]的位置就是要算出, 这三条路径哪一条是最有可能的路径, 也就是取概率最大的一条, 这样的话, 计算公式为:
T 1 [ 0 , 1 ] = max i ( P ( i 1 = q 0 ∣ i 0 = q i ) P ( o 1 = v 1 ∣ i 1 = q 0 ) ) = T 1 [ q i , t i m e _ s t e p = 0 ] ∗ A t − 1 = q i , t = q 0 ∗ B i 1 = q 0 , o 1 = v 1 T1[0, 1]=\max_{i} (P(i_1 = q_0 | i_0 = q_i) P(o_1=v_1| i_1 = q_0)) = T1[q_i, time\_step=0] * A_{t-1=q_i, \ t=q_0} * B_{i_1 = q_0, o_1=v_1} T1[0,1]=imax(P(i1=q0∣i0=qi)P(o1=v1∣i1=q0))=T1[qi,time_step=0]∗At−1=qi, t=q0∗Bi1=q0,o1=v1
上式最右边 T 1 [ q i , t i m e _ s t e p = 0 ] T1[q_i, time\_step=0] T1[qi,time_step=0]也就是 T 1 [ : , 0 ] T1[:, \ 0] T1[:, 0]的意思是在 t − 1 t-1 t−1时刻(也就是上一时刻), 每个隐状态对应的概率, 是长度为 3 3 3的向量;
A t − 1 = q i , t = q 0 A_{t-1=q_i, \ t=q_0} At−1=qi, t=q0是 A A A矩阵的第 i i i行第 0 0 0列, 指的是在 t − 1 t-1 t−1时刻隐状态为 q i q_i qi, 而在 t t t时刻隐状态为 q 0 q_0 q0的概率, 一共有三种可能的路径, 所以也是长度为 3 3 3的向量;
B i 1 = q 0 , o 1 = v 1 B_{i_1 = q_0, o_1=v_1} Bi1=q0,o1=v1是 B B B矩阵的第 0 0 0行第 1 1 1列, 指的是隐状态 q 0 q_0 q0生成观测 v 1 v_1 v1的概率, 是一个数值。
通过查表计算, 算出:
T 1 [ 0 , 1 ] = m a x { 0.10 ∗ 0.5 ∗ 0.5 , 0.16 ∗ 0.3 ∗ 0.5 , 0.28 ∗ 0.2 ∗ 0.5 } = 0.028 T1[0,1]=max\{0.10 * 0.5 * 0.5, \ 0.16 * 0.3* 0.5, \ 0.28*0.2* 0.5\}=0.028 T1[0,1]=max{0.10∗0.5∗0.5, 0.16∗0.3∗0.5, 0.28∗0.2∗0.5}=0.028
之前说过, 还要知道目前计算出来的这个最大可能的概率前一时刻的哪一种隐状态 i i i转移过来的, 也就是要在 T 2 [ 0 , 1 ] T2[0,1] T2[0,1]记录转移路径, 计算公式为:
T 2 [ 0 , 1 ] = a r g m a x { 0.10 ∗ 0.5 ∗ 0.5 , 0.16 ∗ 0.3 ∗ 0.5 , 0.28 ∗ 0.2 ∗ 0.5 } = 2 T2[0,1]=argmax\{0.10 * 0.5 * 0.5, \ 0.16 * 0.3* 0.5, \ 0.28*0.2* 0.5\}=2 T2[0,1]=argmax{0.10∗0.5∗0.5, 0.16∗0.3∗0.5, 0.28∗0.2∗0.5}=2
把计算结果填到表里, 注意在下图中, 红色的线表示最大的转移路径, 是从前一时刻的 q 2 q_2 q2转移过来的。
- 接下来用同样的方式, 把表填完, 下面开始说明维特比算法是怎样通过这些暂存的概率和路径找到最优路径的:
最优路径有以下特性: 假设有一条最优路径在 t t t时刻通过一个隐状态 i t i_t it, 那么这一路径从 i t i_t it到最优路径的终点 i T i_T iT相对于在这段距离里所有可能出现的路径里, 也必须是最优的. 否则从 i t i_t it到 i T i_T iT就会有更优的一条路径, 如果把他和从 i 1 i_1 i1到 i t i_t it的路径(最优路径 i t i_t it之前的部分)连起来, 等于又有一条更优路径, 这是矛盾的。
利用这一特性, 只要按上面的步骤计算直到得出最后一步达到的最大概率的隐状态, 再确认最大概率是从前一步哪一个隐状态转移过来的, 然后从 T 2 T2 T2表格里面递推回溯直到第一时刻(也就是 N A N NAN NAN的地方), 就可以找出最优路径了。
回溯的计算:
- 首先算出最后一步达到最大路径的隐状态, 也就是在 T 1 T1 T1表格的第 3 3 3列求 a r g m a x argmax argmax:
i 2 = a r g m a x T 1 [ : , t i m e _ s t e p = 2 ] = 2 i_2 = argmax \ T1[:, \ time\_step = 2] = 2 i2=argmax T1[:, time_step=2]=2
- 之后通过 T 2 T2 T2表格向前追溯一步, 当前最大概率是从前一步哪个隐状态转移过来的:
i 1 = T 2 [ i 2 = 2 , t i m e _ s t e p = 2 ] = 2 i_1 = T2[i_2 = 2, \ time\_step = 2] = 2 i1=T2[i2=2, time_step=2]=2
- 到达了倒数第一步, 追溯最优路径是从哪个起始隐状态转移过来的:
i 0 = T 2 [ i 1 = 2 , t i m e _ s t e p = 1 ] = 2 i_0 = T2[i_1 = 2, \ time\_step = 1] = 2 i0=T2[i1=2, time_step=1]=2
- 至此得出了最有可能的隐状态序列:
I = ( q 2 , q 2 , q 2 ) I=(q_2, \ q_2, \ q_2) I=(q2, q2, q2)
结论:
- 时间复杂度: 假设有 N N N种隐状态, 在每个时刻之间, 一共可能的路径一共有 N 2 N^2 N2种, 假设有 T T T个时刻, 则维特比算法的时间复杂度为 O ( T N 2 ) O(TN^2) O(TN2)。
- 在实际的预测计算当中, 为了防止计算结果下溢, 通常将乘法变为取对数之后的加法。
- 具体范例代码见视频讲解。
四、代码实现
下面代码部分为维特比算法中正向递推算法的矩阵化算法, 即从t-1时刻到t时刻求出需要填入T1和T2表暂存的算法,这里计算的是上例从第0时刻到第1时刻的计算过程。
输入:
import numpy as np
A = np.array([
[.5, .2, .3],
[.3, .5, .2],
[.2, .3, .5]
])
B = b = np.array([
[.5,.5],
[.4,.6],
[.7,.3]
])
pi = np.array([
[.2],
[.4],
[.4]
])
print("transitions: A")
print(A)
print("emissions: B")
print(B)
print("pi:")
print(pi)
输出:
transitions: A
[[0.5 0.2 0.3]
[0.3 0.5 0.2]
[0.2 0.3 0.5]]
emissions: B
[[0.5 0.5]
[0.4 0.6]
[0.7 0.3]]
pi:
[[0.2]
[0.4]
[0.4]]
输入:
T1_prev = np.array([0.1, 0.16, 0.28])
T1_prev = np.expand_dims(T1_prev, axis=-1)
print(T1_prev)
print(T1_prev.shape)
输出:
[[0.1 ]
[0.16]
[0.28]]
(3, 1)
输入:
p_Obs_State = B[:, 1]
p_Obs_State = np.expand_dims(p_Obs_State, axis=0)
print(p_Obs_State)
print(p_Obs_State.shape)
输出:
[[0.5 0.6 0.3]]
(1, 3)
输入:
T1_prev * p_Obs_State * A
输出:
array([[0.025 , 0.012 , 0.009 ],
[0.024 , 0.048 , 0.0096],
[0.028 , 0.0504, 0.042 ]])
输入:
np.max(T1_prev * p_Obs_State * A, axis=0)
输出:
array([0.028 , 0.0504, 0.042 ])
输入:
np.argmax(T1_prev * p_Obs_State * A, axis=0)
输出:
array([2, 2, 2])
参考资料:
- 中文命名实体识别标注数据: https://github.com/SophonPlus/ChineseNlpCorpus
- 统计学习方法 (第2版) 李航 著 193页 第十章 隐马尔可夫模型
- wikipedia Viterbi algorithm https://en.wikipedia.org/wiki/Viterbi_algorithm
- wikipedia Hidden Markov model https://en.wikipedia.org/wiki/Hidden_Markov_model