本文主要讲解NLP 标注模型 涉及到的概率图模型算法. 可用于序列标注问题的概率图模型有 HMM, MEMM, CRF.
首先, 统计机器学习所有的模型的工作流程大部分都遵循
- 训练模型参数, 得到模型
- 预测给定的测试数据.
一. 基础知识
1. 概率图模型
在统计概率图中, 参考宗成庆老师的书, 是这样的体系结构
在概率图模型中,数据(样本)由G=(V,E)建模表示:
- V 表示节点,即随机变量(可以是一个token,或者一个label). 具体地,用 Y = ( y 1 , y 2 , . . y n ) Y=(y_1, y_2,..y_n) Y=(y1,y2,..yn)为随机变量建模,注意Y现在代表了一批随机变量(可以想象成 一个sequence, 里面包含了很多token), P(Y)为这些随机变量的分布;
- E表示边,即依赖关系.具体理解要结合下面的HMM或CRF的图来解释.
1.1 有向图 vs 无向图
从上图可以看到贝叶斯都是有向图,马尔科夫网络是无向.所以贝叶斯网络适合为有单向依赖的数据建模, 马尔科夫网络适合实体间互相依赖的建模. 具体地, 他们的核心差异表现在如何求P=(Y),即怎么表示 Y = ( y 1 , y 2 , . . . y n ) Y = (y_1, y_2,...y_n) Y=(y1,y2,...yn)这个联合概率.
1.1.1. 有向图
对于有向图模型, 这么求联合概率 P ( x 1 , x 2 , . . x n ) = ∏ i = 0 P ( x i ∣ π ( x i ) ) P(x_1, x_2,..x_n) = \prod_{i=0}P(x_i|\pi(x_i)) P(x1,x2,..xn)=∏i=0P(xi∣π(xi))
举例:对于下面的有向图的随机变量的联合概率应该表示为
P
(
x
1
,
x
2
,
.
.
x
n
)
=
P
(
x
1
)
P
(
x
2
∣
x
1
)
P
(
x
3
∣
x
2
)
P
(
x
4
∣
x
2
)
P
(
x
5
∣
x
3
,
x
4
)
P(x_1,x_2,..x_n) = P(x_1)P(x_2|x_1)P(x_3|x_2)P(x_4|x_2)P(x_5|x_3,x_4)
P(x1,x2,..xn)=P(x1)P(x2∣x1)P(x3∣x2)P(x4∣x2)P(x5∣x3,x4)
1.1.2. 无向图
对于无向图, 资料一般指马尔科夫网络.
如果一个图太大, 可以用因式分解将P=(Y)写为若干个联合概率的乘积. 如何分解?
将一个图分为若干个小团, 注意每个团必须是最大团(就是里面任何两个点连在一起),则有:
P
(
Y
)
=
1
Z
(
x
)
∏
c
ψ
c
(
Y
c
)
P(Y) = \frac 1{Z(x)} \prod_c\psi_c(Y_c)
P(Y)=Z(x)1c∏ψc(Yc)
其中,
Z
(
x
)
=
∑
Y
∏
c
ψ
c
(
Y
c
)
Z(x) = \sum_Y\prod_c\psi_c(Y_c)
Z(x)=Y∑c∏ψc(Yc).
归一化是为了让结果作为概率.
所以像上面的无向图:
P
(
Y
)
=
1
Z
(
x
)
(
ψ
1
(
X
1
,
X
2
,
.
.
X
n
)
∗
ψ
2
(
X
2
,
X
3
,
X
4
)
)
P(Y) = \frac 1{Z(x)}(\psi_1(X_1, X_2,..X_n)* \psi_2(X_2, X_3,X_4))
P(Y)=Z(x)1(ψ1(X1,X2,..Xn)∗ψ2(X2,X3,X4))
其中,
ψ
c
(
Y
c
)
\psi_c(Y_c)
ψc(Yc)是一个最大团C上随机变量的联合概率, 一般取指数函数的
ψ
c
(
Y
c
)
=
e
−
E
(
Y
c
)
=
e
∑
k
λ
k
f
k
(
c
,
y
∣
c
,
x
)
\psi_c(Y_c) = e^{-E(Y_c)} = e^{\sum_k\lambda_kf_k(c,y|c,x)}
ψc(Yc)=e−E(Yc)=e∑kλkfk(c,y∣c,x) 叫做势函数. 注意
e
∑
k
λ
k
f
k
(
c
,
y
∣
c
,
x
)
e^{\sum_k\lambda_kf_k(c,y|c,x)}
e∑kλkfk(c,y∣c,x) 可以看到CRF的影子.
那么概率无向图的联合概率分布可以在因子分解下表示为:
P
(
Y
)
=
1
Z
(
x
)
∏
c
ψ
c
(
Y
c
)
=
1
Z
(
x
)
∏
c
e
∑
k
λ
k
f
k
(
c
,
y
∣
c
,
x
)
=
1
Z
(
x
)
e
∑
c
∑
k
λ
k
f
k
(
y
i
,
y
i
−
1
,
x
,
i
)
P(Y) = \frac 1{Z(x)} \prod_c\psi_c(Y_c) =\frac 1{Z(x)} \prod_ce^{\sum_k\lambda_kf_k(c,y|c,x)} = \frac 1{Z(x)} e^{\sum_c\sum_k\lambda_kf_k(y_i,y_{i-1},x,i)}
P(Y)=Z(x)1c∏ψc(Yc)=Z(x)1c∏e∑kλkfk(c,y∣c,x)=Z(x)1e∑c∑kλkfk(yi,yi−1,x,i)
注意,这里的理解还蛮重要的,注意递推过程,这是CRF的开端!
这个由Hammersly-Clifford law保证,具体不展开。
1.2 马尔科夫假设和马尔科夫性
1.2.1. 齐次马尔科夫假设
马尔科夫链
(
x
1
,
x
2
,
.
.
.
x
n
)
(x_1,x_2,...x_n)
(x1,x2,...xn)里面的
x
i
x_i
xi总是受
x
i
−
1
x_{i-1}
xi−1一个元素的影响.(也就是相当于1-gram)
马尔科夫过程,是在一个过程中, 每个状态的转移只依赖与前n个状态,并且只是个n阶模型,最简单的马尔科夫过程是一阶的,即依赖于前一个状态.
1.2.2. 马尔科夫性
马尔科夫性是保证或者判断概率图是否为概率无向图的条件.
三点内容: a, 成对, b,局部, c,全局.
2. 判别式模型vs 生成式模型
在监督学习下,模型可以分为判别式模型与生成式模型。
先问个问题,根据经验,A批模型(神经网络模型、SVM、perceptron、LR、DT……)与B批模型(NB、LDA……),有啥区别不?(这个问题需要一些模型使用经验)应该是这样的:
- A批模型是这么工作的,他们直接将数据的Y(或者label),根据所提供的features,学习,最后画出了一个明显或者比较明显的边界(具体怎么做到的?通过复杂的函数映射,或者决策叠加等等mechanism),这一点线性LR、线性SVM应该很明显吧。
- B批模型是这么工作的,他们先从训练样本数据中,将所有的数据的分布情况摸透,然后最终确定一个分布,来作为我的所有的输入数据的分布,并且他是一个联合分布 P ( X , Y ) P(X,Y) P(X,Y)(注意这里X包含所有的特征 x i x_i xi, Y 包含所有的label). 然后当有新的样本数据时, 通过学习来的模型的联合概率分布 P ( X , Y ) P(X,Y) P(X,Y) 再结合新样本给的X, 通过条件概率就能得到Y P ( Y ∣ X ) = P ( X , Y ) P ( X ) P(Y|X) = \frac {P(X,Y)}{P(X)} P(Y∣X)=P(X)P(X,Y)
2.1 判别式模型
A批模型对应了判别式模型。根据上面的两句话的区别,可以知道判别模型的特征了,所以有句话说:判别模型是直接对P(Y|X)建模,也就是说直接根据X特征来对Y建模训练.
具体地, 我们的训练过程是确定构建P(Y|X)模型里面"复杂映射关系"中的参数, 完了之后再去inference一批新的sample.
所以判别式模型的特征总结如下:
- 对P(Y|X)建模
- 对所有的样本只构建一个模型, 确认总体判别边界
- 观测到输入什么特征,就预测最可能的label
- 判别式的优点是, 对数据量要求没生成式的严格,速度也会快, 小数据量下准确率也会好一些.
2.2 生成式模型
B批模型对应了生成式模型。并且需要注意的是,在模型训练中,我学习到的是X与Y的联合模型P(X,Y),也就是说, 我们在训练阶段只对P(X,Y)建模, 我们需要确定维护这个联合概率分布的所有信息参数. 之后在inference 再对新的sample 计算P(Y|X), 导出Y, 但是这已经不属于建模阶段了.
结合NB过一遍生成式模型的工作流程.
学习阶段, 建模
P
(
X
,
Y
)
=
P
(
X
∣
Y
)
P
(
Y
)
P(X, Y) = \frac {P(X|Y)}{P(Y)}
P(X,Y)=P(Y)P(X∣Y), 然后
P
(
Y
∣
X
)
=
P
(
X
,
Y
)
/
P
(
X
)
P(Y|X) = P(X,Y)/P(X)
P(Y∣X)=P(X,Y)/P(X)
所以生成式模型的特征总结如下:
- 对P(X,Y)建模
- 这里主要讲分类, 所以是要对每个label(yi) 都需要建模, 最终选择最优概率的label作为结果, 所以没有什么判别边界(对于序列标注问题, 那只需要构建一个model)
- 中间生成联合分布, 并可生成采样数据.
- 生成式模型的优点在于, 所包含的信息非常齐全, 不仅可以用来输入label, 还可以干其他事情. 生成式模型关注结果是如何产生的. 但是生成式模型需要非常充足的数据量以保证采样到了数据本来的面目, 所以速度相比之下,慢.
这一点明白后,后面讲到的HMM与CRF的区别也会非常清晰。
最后identity the picture below:
3. 序列建模
为序列问题建模
序列包括时间序列以及general sequence,但两者无异。连续的序列在分析时也会先离散化处理。常见的序列有如:时序数据、本文句子、语音数据、等等。
广义下的序列有这些特点:
节点之间有关联依赖性/无关联依赖性
序列的节点是随机的/确定的
序列是线性变化/非线性的
.....
对不同的序列有不同的问题需求,常见的序列建模方法总结有如下:
- 拟合,预测未来节点(或走势分析):
a. 常规序列建模方法:AR、MA、ARMA、ARIMA
b. 回归拟合
c. Neural Networks - 判断不同序列类别,即分类问题:HMM、CRF、General Classifier(ML models、NN models)
- 不同时序对应的状态的分析,即序列标注问题:HMM、CRF、RecurrentNNs
在本篇文字中,我们只关注在2. & 3.类问题下的建模过程和方法。
二. HMM
HMM即隐马尔可夫模型,它是处理序列问题的统计学模型,描述的过程为:由隐马尔科夫链随机生成不可观测的状态随机序列,然后各个状态分别生成一个观测,从而产生观测随机序列。
在这个过程中,不可观测的序列称为状态序列(state sequence), 由此产生的序列称为观测序列(observation sequence)。
该过程可通过下图描述:
上图中, 𝑋1,𝑋2,…𝑋𝑇是隐含序列,而𝑂1,𝑂2,…𝑂𝑇是观察序列。
隐马尔可夫模型由三个概率确定:
- 初始概率分布,即初始的隐含状态的概率分布,记为𝜋;
- 状态转移概率分布,即隐含状态间的转移概率分布, 记为𝐴;
- 观测概率分布,即由隐含状态生成观测状态的概率分布, 记为𝐵。
以上的三个概率分布可以说就是隐马尔可夫模型的参数,而根据这三个概率,能够确定一个隐马尔可夫模型𝜆=(𝐴,𝐵,𝜋)
。
而隐马尔科夫链的三个基本问题为:
- 概率计算问题。即给定模型𝜆=(𝐴,𝐵,𝜋) 和观测序列𝑂,计算在模型𝜆下观测序列出现的最大概率𝑃(𝑂|𝜆),主要使用前向-后向算法解决;
- 学习问题。即给定观测序列𝑂,估计模型的参数𝜆, 使得在该参数下观测序列出现的概率最大,即𝑃(𝑂|𝜆)最大,主要使用Baum-Welch算法EM迭代计算(若不涉及隐状态,则使用极大似然估计方法解决);
- 解码问题。给定模型𝜆=(𝐴,𝐵,𝜋)和观测序列𝑂,计算最有可能产生这个观测序列的隐含序列𝑋, 即使得概率𝑃(𝑋|𝑂,𝜆)最大的隐含序列𝑋,主要使用维特比算法(动态规划思想)解决。
HMM最初用于传染病模型和舆情传播问题,这些问题里面的当前状态可以简化为只与前一状态有关,即具备马尔科夫性质。但是,试想一个语言标注问题,模型不仅需要考虑前一状态的标注,也应该考虑后一状态的标注(例如我爱中国,名词+动词+名词,上下文信息更丰富)。由此,自然会对模型做出更多的假设条件,也就引出了图模型(当前状态与相连的状态都有关)+ 条件模型(当前的状态与隐状态有关)= 条件随机场。
1. 理解HMM
我们只是讨论了常规的序列数据
(
x
1
,
x
2
,
.
.
x
n
)
(x_1, x_2,..x_n)
(x1,x2,..xn) ,像上图那样。像这种序列一般用马尔科夫模型就可以胜任。实际上我们碰到的更多的使用HMM的场景是每个节点
x
i
x_i
xi下还附带着另外一个节
Y
i
Y_i
Yi. 正所谓隐含马尔科夫模型,那么除了正常的节点,还要将隐含状态节点也得建模进去。正儿八经地,将
X
i
,
Y
i
X_i, Y_i
Xi,Yi换成
i
i
,
o
i
i_i, o_i
ii,oi,并且他们的名称变为状态节点, 观测节点,状态节点正是我的隐状态。
HMM属于典型的生成式模型。对照上文讲解,应该是要从训练数据中学到数据的各种分布,那么有哪些分布呢以及是什么呢?直接正面回答的话,正是HMM的5要素,其中有3个就是整个数据的不同角度的概率分布:
- N ,隐藏状态集 N = q 1 , q 2 , . . q n N = {q_1, q_2, ..q_n} N=q1,q2,..qn , 我的隐藏节点不能随意取,只能限定取包含在隐藏状态集中的符号。
- M, 观测集 M = v 1 , v 2 , . . . v m M = {v_1, v_2,...v_m} M=v1,v2,...vm , 同样我的观测节点不能随意取,只能限定取包含在观测状态集中的符号。
- A ,状态转移概率矩阵,这个就是其中一个概率分布。他是个矩阵, A = [ a i j ] N ∗ N A=[a_{ij}]_{N*N} A=[aij]N∗N(N为隐藏状态集元素个数),其中 a i j = p ( i t + 1 ∣ i t ) , i t a_{ij} = p(i_{t+1}|i_t), i_t aij=p(it+1∣it),it 即第i个隐状态节点,即所谓的状态转移嘛。
- B ,观测概率矩阵,这个就是另一个概率分布。他是个矩阵, B = [ b i j ] N ∗ M B = [b_{ij}]_{N*M} B=[bij]N∗M (N为隐藏状态集元素个数,M为观测集元素个数),其中 b i j = P ( o t ∣ i t ) , o t b_{ij} = P(o_t|i_t), o_t bij=P(ot∣it),ot即第i个观测节点, i t i_t it 即第i个隐状态节点,即所谓的观测概率(发射概率)嘛。
- π ,在第一个隐状态节点
i
t
i_t
it ,我得人工单独赋予,我第一个隐状态节点的隐状态是 N 中的每一个的概率分别是多少,然后 π 就是其概率分布.
图看起来是这样的:
模型先去学习要确定以上5要素,之后在inference阶段的工作流程是:首先,隐状态节点 i t i_t it是不能直接观测到的数据节点, o t o_t ot才是能观测到的节点,并且注意箭头的指向表示了依赖生成条件关系, i t i_t it在A的指导下生成下一个隐状态节点 i t + 1 i_{t+1} it+1,同时在 B 的指导下生成依赖于该 i t i_t it的观测节点 o t o_t ot,并且我只能观测到序列 ( o 1 , o 2 , . . o i ) (o_1, o_2,..o_i) (o1,o2,..oi).
举例子说明(序列标注问题,POS,标注集BES):
input: “学习出一个模型,然后再预测出一条指定”
expected output: 学/B 习/E 出/S 一/B 个/E 模/B 型/E ,/S 然/B 后/E 再/E 预/B 测/E ……
其中,input里面所有的char构成的字表,形成观测集 M ,因为字序列在inference阶段是我所能看见的;标注集BES构成隐藏状态集 N ,这是我无法直接获取的,也是我的预测任务;至于 A、B、π ,这些概率分布信息(上帝信息)都是我在学习过程中所确定的参数。
具有同时带着隐藏状态节点和观测节点的类型的序列,在HMM下就是这样子建模的
- 根据概率图分类,可以看到HMM属于有向图,并且是生成式模型,直接对联合概率分布建模 P ( O , I ) = ∑ t = 1 T P ( O t ∣ O t − 1 ) P ( I t ∣ O t ) P(O,I) = \sum_{t=1}^TP(O_t|O_{t-1})P(I_t|O_t) P(O,I)=∑t=1TP(Ot∣Ot−1)P(It∣Ot)(注意,这个公式不在模型运行的任何阶段能体现出来,只是我们都去这么来表示HMM是个生成式模型,他的联合概率P(O,I)就是这么计算来的.
- B中 b i j = P ( o t ∣ i t ) b_{ij} = P(o_t|i_t) bij=P(ot∣it), 这意味这o对i 有依赖性
- 在A中, a i j = P ( i t + 1 ∣ i t ) a_{ij} = P(i_{t+1}|i_t) aij=P(it+1∣it),也就是说只遵循了一阶马尔科夫假设,1-gram。试想,如果数据的依赖超过1-gram,那肯定HMM肯定是考虑不进去的。这一点限制了HMM的性能。
2. HMM模型运行过程
2.1 学习训练过程
HMM学习训练的过程,就是找出数据的分布情况,也就是模型参数的确定。
主要学习算法按照训练数据除了观测状态序列 ( o 1 , o 2 . . . o i ) (o_1, o_2...o_i) (o1,o2...oi),是否还有隐状态序列 ( i 1 , i 2 . . . i i ) (i_1, i_2...i_i) (i1,i2...ii)分为:
- 极大似然估计, with 隐状态序列
- Baum-Welch(前向后向), without 隐状态序列
2.1.1 极大似然估计
一般做NLP的序列标注等任务,在训练阶段肯定是有隐状态序列的。所以极大似然估计法是非常常用的学习算法,我见过的很多代码里面也是这么计算的。比较简单。
step1. 算A
a
i
j
=
A
i
j
∑
j
=
1
N
A
i
j
a_{ij} = \frac {A_{ij}}{\sum_{j=1}^N A_{ij}}
aij=∑j=1NAijAij
step2. 算B
b
j
(
k
)
=
B
j
k
∑
k
=
1
M
B
j
k
b_j(k) = \frac {B_{jk}}{\sum_{k=1}^M B_{jk}}
bj(k)=∑k=1MBjkBjk
step3. 直接估计 π \pi π
2.1.2 Baum-Welch(前向后向)
就是一个EM的过程,如果你对EM的工作流程有经验的话,对这个Baum-Welch一看就懂。EM的过程就是初始化一套值,然后迭代计算,根据结果再调整值,再迭代,最后收敛……好吧,这个理解是没有捷径的,去隔壁钻研EM吧。这里只提一下核心。因为我们手里没有隐状态序列信息,所以我先必须给初值 a i j 0 , b j ( k ) 0 , π 0 a_{ij}^0, b_j(k)^0, \pi^0 aij0,bj(k)0,π0, 初步确定模型,然后再迭代计算出 a i j n , b j ( k ) n , π n a_{ij}^n, b_j(k)^n, \pi^n aijn,bj(k)n,πn, ,中间计算过程会用到给出的观测状态序列. 另外,收敛性由EM的XXX定理保证,
2.2 序列标注(解码)过程
好了,学习完了HMM的分布参数,也就确定了一个HMM模型。需要注意的是,这个HMM是对我这一批全部的数据进行训练所得到的参数。序列标注问题也就是“预测过程”,通常称为解码过程。对应了序列建模问题3.。对于序列标注问题,我们只需要学习出一个HMM模型即可,后面所有的新的sample我都用这一个HMM去apply。我们的目的是,在学习后已知了P(Q,O), 现在求出P(Q|O), 进一步,
Q
m
a
x
=
a
r
g
m
a
x
a
l
l
Q
P
(
Q
,
O
)
P
(
O
)
Q_{max} = argmax_{allQ} \frac {P(Q, O)}{P(O)}
Qmax=argmaxallQP(O)P(Q,O)
再直白点就是,我现在要在给定的观测序列下找出一条隐状态序列,条件是这个隐状态序列的概率是最大的那个。
具体地,都是用Viterbi算法解码,是用DP思想减少重复的计算。Viterbi也是满大街的,不过要说的是,Viterbi不是HMM的专属,也不是任何模型的专属,他只是恰好被满足了被HMM用来使用的条件。
Viterbi计算有向无环图的一条最大路径 可以参考 如何通俗地讲解 viterbi 算法?
2.3 序列概率过程
通过HMM计算出序列的概率又有什么用?针对这个点我把这个问题详细说一下。
实际上,序列概率过程对应了序列建模问题2.,即序列分类。
在序列标注问题中,我用一批完整的数据训练出了一支HMM模型即可。好,那在序列分类问题就不是训练一个HMM模型了。我应该这么做(结合语音分类识别例子):
目标:识别声音是A发出的还是B发出的。
HMM建模过程:
1. 训练:我将所有A说的语音数据作为dataset_A,将所有B说的语音数据作为dataset_B(当然,先要分别对dataset A ,B做预处理encode为元数据节点,形成sequences),然后分别用dataset_A、dataset_B去训练出HMM_A/HMM_B
2. inference:来了一条新的sample(sequence),我不知道是A的还是B的,没问题,分别用HMM_A/HMM_B计算一遍序列的概率得到 P A ( S ) , P B ( S ) P_A(S), P_B(S) PA(S),PB(S)比较两者大小,哪个概率大说明哪个更合理,更大概率作为目标类别。
所以,本小节的理解重点在于,如何对一条序列计算其整体的概率。即目标是计算出 P ( O ∣ λ ) P(O|\lambda ) P(O∣λ). 这个问题前辈们在他们的经典中说的非常好了,比如参考李航老师整理的:
直接计算法(穷举搜索)
前向算法
后向算法
后面两个算法采用了DP思想,减少计算量,即每一次直接引用前一个时刻的计算结果以避免重复计算,跟Viterbi一样的技巧。
三. MEMM
MEMM,即最大熵马尔科夫模型,这个是在接触了HMM、CRF之后才知道的一个模型。说到MEMM这一节时,得转换思维了,因为现在这MEMM属于判别式模型。
1. 理解MEMM
MEMM正因为是判别模型,所以不废话,我上来就直接为了确定边界而去建模,比如说序列求概率(分类)问题,我直接考虑找出函数分类边界。这一点跟HMM的思维方式发生了很大的变化,如果不对这一点有意识,那么很难理解为什么MEMM、CRF要这么做。
HMM中,观测节点
o
i
o_{i}
oi 依赖隐藏状态节点
i
i
i_{i}
ii ,也就意味着我的观测节点只依赖当前时刻的隐藏状态。但在更多的实际场景下,观测序列是需要很多的特征来刻画的,比如说,我在做NER时,我的标注
i
i
i_{i}
ii 不仅跟当前状态
o
i
o_{i}
oi 相关,而且还跟前后标注
o
j
(
j
≠
i
)
o_{j}(j \neq i)
oj(j=i) 相关,比如字母大小写、词性等等。
为此,提出来的MEMM模型就是能够直接允许“定义特征”,直接学习条件概率,即
P
(
i
i
∣
i
i
−
1
,
o
i
)
P(i_i|i_{i-1}, o_i)
P(ii∣ii−1,oi), 总体为
并且,
P
(
i
∣
i
′
,
o
)
P(i|i', o)
P(i∣i′,o) 这个概率通过最大熵分类器建模(取名为MEMM的原因):
重点来了,这是ME的内容,也是理解MEMM的关键
未完待续。。