博客内容将首发在微信公众号"跟我一起读论文啦啦",上面会定期分享机器学习、深度学习、数据挖掘、自然语言处理等高质量论文,欢迎关注!
本次要总结的是条件随机场(CRF)相关知识
文章目录
从hmm缺点和MHMM标注偏置讲起
HMM回顾
HMM基本概念
hmm 是对 p ( x , y ) p(x,y) p(x,y) 联合概率进行建模,为生成式模型。
-
问题建模:
F ( x , y ) = P ( x , y ) = P ( y ) P ( X ∣ y ) F(x,y) = P(x,y)=P(y)P(X|y) F(x,y)=P(x,y)=P(y)P(X∣y)
注意是联合概率建模
-
模型推断:
y ^ = a r g m a x y ∈ Y P ( x , y ) \hat{y} = argmax_{y \in Y}P(x, y) y^=argmaxy∈YP(x,y)维特比算法进行推断,维特比的核心是:达每一列的时候都会删除不符合最短路径要求的路径,大大降低时间复杂度。
-
参数估计
H M M HMM HMM 是生成模型,因为它对状态序列本身的分布 P ( y ) P(y) P(y) (状态转移矩阵)和给定状态后观测值的分布 P ( x ∣ y ) P(x|y) P(x∣y) (发射矩阵)都进行了建模。有监督时可以从训练数据中很容易统计出
有三个主要因素
- 初始概率分布 π \pi π
- 状态转移概率分布 A A A
- 观测概率 B B B,也称发射矩阵
在有监督方法里,这三个因素可以从训练样本轻松统计到。
两个齐次假设:
-
齐次假设:
P ( i t ∣ i t − 1 , o t − 1 , i t − 2 , o t − 2 . . . i 1 , o 1 ) = P ( i t ∣ i t − 1 ) P(i_t|i_{t-1},o_{t-1},i_{t-2},o_{t-2}...i_1,o_1)=P(i_t|i_{t-1}) P(it∣it−1,ot−1,it−2,ot−2...i1,o1)=P(it∣it−1)
也即是当前时刻的隐状态只与前一时刻的隐状态有关。 -
观测独立性假设:
P ( o t ∣ i T , o T , i T − 1 , o T − 1 , . . . , i 1 , o 1 ) = P ( o t ∣ i t ) P(o_t|i_T,o_T,i_{T-1},o_{T-1},...,i_1,o_1) = P(o_t|i_t) P(ot∣iT,oT,iT−1,oT−1,...,i1,o1)=P(ot∣it)
可以用下图表示:
注意箭头方向,表示依赖关系
HMM缺点
在利用维特比算法进行推断时,找到能使联合概率最大的
y
^
\hat{y}
y^
y
^
=
a
r
g
m
a
x
y
∈
Y
P
(
x
,
y
)
\hat{y} = arg max_{y\in Y} P(x, y)
y^=argmaxy∈YP(x,y)
但是这样找出来的 y ^ \hat{y} y^ 有可能不是正确答案,下面举个简单例子来说
在训练集中有:
则其状态转移矩阵中有
P
(
V
∣
N
)
=
9
/
10
,
P
(
D
∣
N
)
=
1
/
10
P(V|N) = 9/10,P(D|N)=1/10
P(V∣N)=9/10,P(D∣N)=1/10
观测矩阵中有
P
(
a
∣
V
)
=
1
/
2
,
P
(
a
∣
D
)
=
1
P(a|V)=1/2,P(a|D)=1
P(a∣V)=1/2,P(a∣D)=1
那么在预测样本中,存在一个样本的,上一时刻的状态 y t − 1 = N y_{t-1}=N yt−1=N,当前时刻观测值为 x t = a x_t=a xt=a,需要推断当前时刻的状态
显然当前时刻状态取状态
V
V
V 时,概率最大,取
9
/
10
∗
1
/
2
=
0.45
9/10 * 1/2=0.45
9/10∗1/2=0.45,取
D
D
D 时,概率为
1
/
10
∗
1
=
0.1
1/10*1 =0.1
1/10∗1=0.1
那么由此推断出当前时刻为状态
V
V
V 合理吗? 训练集中明明出现了这个exist sample
模型却没有选
D
D
D 这个状态,而预测出了一个训练集中从未出现过的样本。
由此可以得到如下结论
- HMM 能生成训练集中从未出现过的样本,而训练集中明确存在的样本,HMM不一定就会生成。
- 当训练集足够大时,HMM模型表现可能并不好,但是训练集比较小的时候,预测效果反而可能比较好。
那么造成这样的原因是什么呢?
- HMM 模型在训练时,对状态转移矩阵和观测(发射)矩阵是分开建模的,两者是独立的。
MHMM 回顾
MHMM 基本概念
对
p
(
s
∣
x
)
p(s|x)
p(s∣x) 进行建模,是判别式模型。
上式中
x
1
,
x
2
,
.
.
.
,
x
m
x_1, x_2,...,x_m
x1,x2,...,xm 表示观测序列,
s
1
,
s
2
,
.
.
.
,
s
m
s_1,s_2,...,s_m
s1,s2,...,sm 表示状态序列
其中
其中每一时刻的状态都依赖于整体的观测序列(
x
1
,
x
2
,
.
.
.
,
x
m
x_1, x_2,...,x_m
x1,x2,...,xm) 和上一时刻状态(
s
i
−
1
)
s_{i-1})
si−1)。如下图:
同样注意箭头方向,表示依赖
Label Bias(标注偏置)
可得每个时刻的条件概率为:
p
(
s
i
∣
s
i
−
1
,
x
1
.
.
.
x
m
)
=
e
x
p
(
w
⃗
⋅
ϕ
⃗
(
x
1
.
.
.
x
m
,
i
,
s
i
−
1
,
s
i
)
∑
s
′
∈
S
e
x
p
(
w
⃗
⋅
ϕ
⃗
(
x
1
.
.
.
x
m
,
i
,
s
i
−
1
,
s
′
)
)
p(s_i|s_{i-1},x_1...x_m)=\frac{exp(\vec{w} \cdot \vec{\phi}(x_1...x_m,i,s_{i-1},s_i)}{\sum_{s' \in S}exp(\vec{w} \cdot \vec{\phi}(x_1...x_m,i,s_{i-1},s'))}
p(si∣si−1,x1...xm)=∑s′∈Sexp(w⋅ϕ(x1...xm,i,si−1,s′))exp(w⋅ϕ(x1...xm,i,si−1,si)
上述 ϕ ⃗ \vec{\phi} ϕ 表示一个函数,得到一个向量结果。当确定了 ϕ ⃗ \vec{\phi} ϕ 的形式,就可以利用训练样本对其中的参数 w w w 进行学习了。
- x 1 . . . . x m x_1....x_m x1....xm表示整个要被标注的源句子
- i i i 表示当前要被标注的 第 i i i 个位置
- s 表示上一个时刻状态
- s’ 表示当前时刻的状态
这里需要特别注意:
每一步(时刻)都会做上述公式的归一化操作。
模型会倾向给那些分支路径较少的状态较大的概率
分支路径多少,也就是某个状态后面能跟多少个其他状态,是由训练集中样本决定。
如下图
上图中
S
t
a
t
e
1
State1
State1 在每个时刻都仅有两个分支,而
S
t
a
t
e
2
State2
State2有四个分支;在每个时刻经过归一化后,
S
t
a
t
e
1
State1
State1 后面的分支概率基本都大于
S
t
a
t
e
s
2
States2
States2的分支。
故Viterbi算法解码后,最优路径为 1 − > 1 − > 1 − > 1 1-> 1-> 1-> 1 1−>1−>1−>1。而这显然是不合理的。
MHMM 模型解决了HMM的独立建模的问题,但是又引出了一个标注偏置的新问题,且看CRF模型如何解决这些问题。
CRF模型
问题建模
CRF原始论文 Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data,但是我感觉这篇论文容易把人看晕,其实表达的意思很简单,可以先从 l o g − l i n e a r log-linear log−linear 模型的角度看CRF模型。
CRF对
p
(
s
∣
x
)
p(s|x)
p(s∣x) 进行建模,是判别式模型
p
(
s
1
,
.
.
.
.
,
s
m
∣
x
1
,
.
.
.
,
x
m
)
=
p
(
s
⃗
∣
x
⃗
)
p(s_1,....,s_m|x_1,...,x_m)=p(\vec{s}|\vec{x})
p(s1,....,sm∣x1,...,xm)=p(s∣x)
上式中
s
⃗
\vec{s}
s 表示状态序列,
x
⃗
\vec{x}
x 表示观测序列
再定义一个特征函数:
ϕ
⃗
(
x
⃗
,
s
⃗
)
∈
R
d
\vec{\phi}(\vec{x}, \vec{s}) \in R^d
ϕ(x,s)∈Rd
需要将 ϕ ⃗ \vec{\phi} ϕ 理解为全局的,因为其输入的变量是整体的状态序列,而不是某个单一时刻的,这点至关重要,这也是避免MHMM 模型的 l a b e l b i a s label\ bias label bias 的关键。
p ( s ⃗ ∣ x ⃗ ; w ⃗ ) = e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ∑ s ′ ⃗ ∈ S m e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ′ ⃗ ) ) p(\vec{s}|\vec{x};\vec{w})=\frac{exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}{\sum_{\vec{s'} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s'}))} p(s∣x;w)=∑s′∈Smexp(w⋅Φ(x,s′))exp(w⋅Φ(x,s))
s ∈ S m s \in S^m s∈Sm 表示 tag_space
对于上式要特别注意以下几点
- 上式中的无论分子还是分母的 e x p exp exp 都是考虑和计算全局 时刻的,而非单一时刻,从上式中 p ( s ⃗ ∣ x ⃗ ; w ⃗ ) p(\vec{s}|\vec{x};\vec{w}) p(s∣x;w) 里的向量形式可以看出。
- 从分母中的 s ′ ∈ S m s' \in S^m s′∈Sm 可以看出,分母计算量巨大,需要计算所有时刻的所有状态的值。
我们可以看下
Φ
⃗
(
x
⃗
,
s
⃗
)
\vec{\Phi}(\vec{x}, \vec{s})
Φ(x,s) 的抽象定义如何?
Φ
⃗
(
x
⃗
,
s
⃗
)
=
∑
j
=
1
m
ϕ
⃗
(
x
⃗
,
j
,
s
j
−
1
,
s
j
)
\vec{\Phi}(\vec{x}, \vec{s})=\sum_{j=1}^{m}\vec{\phi}(\vec{x}, j, s_{j-1},s_j)
Φ(x,s)=j=1∑mϕ(x,j,sj−1,sj)
可以看出上式中
ϕ
⃗
,
Φ
⃗
\vec{\phi}, \vec{\Phi}
ϕ,Φ 均是向量形式,可以理解为
k
k
k 维度,其中
k
=
1
,
2
,
3
,
.
.
.
,
d
k=1,2,3,...,d
k=1,2,3,...,d,则第
k
k
k 个全局特征形如如下:
Φ
⃗
k
(
x
⃗
,
s
⃗
)
=
∑
j
=
1
m
ϕ
k
(
x
⃗
,
j
,
s
j
−
1
,
s
j
)
\vec{\Phi}_k(\vec{x}, \vec{s}) = \sum_{j=1}^m \phi_k(\vec{x}, j, s_{j-1},s_j)
Φk(x,s)=j=1∑mϕk(x,j,sj−1,sj)
上式中全局特征 Φ k \Phi_k Φk 为局部特征 ϕ k \phi_k ϕk 在不同的状态序列上之和。
下面我们再来看看
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s})
w⋅Φ(x,s) 具体如何定义呢?CRF原始论文 Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data 是如下定义的:
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
=
∑
j
,
k
λ
k
f
k
(
s
j
−
1
,
s
j
,
x
⃗
,
j
)
+
∑
j
,
k
μ
k
g
k
(
s
j
,
x
⃗
,
j
)
\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}) = \sum_{j,k}\lambda_kf_k(s_{j-1},s_j, \vec{x},j)+\sum_{j,k}\mu_kg_k(s_j,\vec{x}, j)
w⋅Φ(x,s)=j,k∑λkfk(sj−1,sj,x,j)+j,k∑μkgk(sj,x,j)
上面右式可以抽象成左式的,其中 k k k 表示 Φ ⃗ \vec{\Phi} Φ 维度, j j j 表示时刻维度。
f k ( s j − 1 , s j , x ⃗ , j ) f_k(s_{j-1},s_j, \vec{x},j) fk(sj−1,sj,x,j) 表示对状态转移矩阵建模, g k ( s j , x ⃗ , j ) g_k(s_j,\vec{x}, j) gk(sj,x,j) 表示对单个时刻状态建模。
p ( s ⃗ ∣ x ⃗ ; w ⃗ ) = e x p ( ∑ j , k λ k f k ( s j − 1 , s j , x ⃗ , j ) + ∑ j , k μ k g k ( s j , x ⃗ , j ) ) ∑ s ′ e x p ( ∑ j , k λ k f k ( s j − 1 , s ′ x ⃗ , j ) + ∑ j , k μ k g k ( s ′ , x ⃗ , j ) ) p(\vec{s} |\vec{x};\vec{w})=\frac{exp(\sum_{j,k}\lambda_kf_k(s_{j-1},s_j, \vec{x},j)+\sum_{j,k}\mu_kg_k(s_j,\vec{x}, j))}{\sum_{s'}exp(\sum_{j,k}\lambda_kf_k(s_{j-1},s' \vec{x},j)+\sum_{j,k}\mu_kg_k(s',\vec{x}, j))} p(s∣x;w)=∑s′exp(∑j,kλkfk(sj−1,s′x,j)+∑j,kμkgk(s′,x,j))exp(∑j,kλkfk(sj−1,sj,x,j)+∑j,kμkgk(sj,x,j))
参数估计
这里假设我们有
n
n
n 个带标签的样本,
{
(
x
⃗
i
,
s
⃗
i
)
}
i
=
1
n
\{(\vec{x}^i,\vec{s}^i)\}_{i=1}^n
{(xi,si)}i=1n,例如第
i
i
i 个样本
x
⃗
i
=
x
1
i
,
x
2
i
,
.
.
.
,
x
m
i
\vec{x}^i=x_1^i,x_2^i,...,x_m^i
xi=x1i,x2i,...,xmi,
s
⃗
i
=
s
1
i
,
.
.
.
,
s
m
i
\vec{s}^i =s_1^i,...,s_m^i
si=s1i,...,smi,则似然函数为:
L
(
w
⃗
)
=
∑
i
=
1
n
l
o
g
p
(
s
⃗
i
∣
x
⃗
i
;
w
⃗
)
−
λ
2
∣
∣
w
⃗
∣
∣
2
L(\vec{w})=\sum_{i=1}^n log p(\vec{s}^i|\vec{x}^i;\vec{w})-\frac{\lambda}{2} ||\vec{w}||^2
L(w)=i=1∑nlogp(si∣xi;w)−2λ∣∣w∣∣2
λ 2 ∣ ∣ w ⃗ ∣ ∣ 2 \frac{\lambda}{2} ||\vec{w}||^2 2λ∣∣w∣∣2 为正则项, i i i 表示第i个样本
则有:
w
⃗
∗
=
a
r
g
m
a
x
w
⃗
∈
R
d
∑
i
=
1
n
l
o
g
p
(
s
⃗
i
∣
x
⃗
i
;
w
⃗
)
−
λ
2
∣
∣
w
⃗
∣
∣
2
\vec{w}^*= arg\ max_{\vec{w} \in R ^d} \sum_{i=1}^n log p(\vec{s}^i|\vec{x}^i;\vec{w})-\frac{\lambda}{2} ||\vec{w}||^2
w∗=arg maxw∈Rdi=1∑nlogp(si∣xi;w)−2λ∣∣w∣∣2
可以用梯度下降法:
φ
φ
w
k
L
(
w
⃗
)
=
∑
i
Φ
k
(
x
⃗
i
,
s
⃗
i
)
−
∑
i
∑
s
⃗
∈
S
m
p
(
x
⃗
∣
x
⃗
i
;
w
⃗
)
Φ
k
(
x
⃗
i
,
s
⃗
)
−
λ
w
k
\frac{\varphi}{\varphi_{w_k}}L(\vec{w}) = \sum_i \Phi_k(\vec{x}^i, \vec{s}^i) - \sum_i\sum_{\vec{s} \in {S^m} }p(\vec{x}|\vec{x}^i;\vec{w}) \Phi_k(\vec{x}^i, \vec{s})-\lambda {w_k}
φwkφL(w)=i∑Φk(xi,si)−i∑s∈Sm∑p(x∣xi;w)Φk(xi,s)−λwk
显然第一项为
∑
i
Φ
k
(
x
⃗
i
,
s
⃗
i
)
=
∑
i
∑
j
=
1
m
ϕ
k
(
x
⃗
i
,
j
,
s
j
−
1
i
,
s
j
i
)
\sum_i \Phi_k(\vec{x}^i, \vec{s}^i)=\sum_i\sum_{j=1}^m\phi_k(\vec{x}^i,j,s_{j-1}^i,s_j^i)
i∑Φk(xi,si)=i∑j=1∑mϕk(xi,j,sj−1i,sji)
第一项很好求,遍历所有样本
i
=
1....
n
i=1....n
i=1....n,和每个样本的所有时刻
j
=
1...
m
j=1...m
j=1...m
第二项要遍历所有样本,且每个样本的每个位置都要遍历所有可能的状态,时间复杂度很高,比较难求解,可以尝试用动态规划方法求解。
∑ s ⃗ ∈ S m p ( x ⃗ ∣ x ⃗ i ; w ⃗ ) Φ k ( x ⃗ i , s ⃗ ) \sum_{\vec{s} \in {S^m} }p(\vec{x}|\vec{x}^i;\vec{w}) \Phi_k(\vec{x}^i, \vec{s}) s∈Sm∑p(x∣xi;w)Φk(xi,s)
= ∑ s ⃗ ∈ S m p ( x ⃗ ∣ x ⃗ i ; w ⃗ ) ∑ j = 1 m ϕ k ( x ⃗ i , j , s j − 1 , s j ) =\sum_{\vec{s} \in {S^m} }p(\vec{x}|\vec{x}^i;\vec{w})\sum_{j=1}^{m}\phi_k(\vec{x}^i,j,s_{j-1},s_j) =s∈Sm∑p(x∣xi;w)j=1∑mϕk(xi,j,sj−1,sj)
= ∑ j = 1 m ∑ s ⃗ ∈ S m p ( s ⃗ ∣ x ⃗ i ; w ) ϕ k ( x ⃗ i , j , s j − 1 , s j ) =\sum_{j=1}^m\sum_{\vec{s} \in S^m}p(\vec{s}|\vec{x}^i;w)\phi_k(\vec{x}^i,j,s_{j-1},s_j) =j=1∑ms∈Sm∑p(s∣xi;w)ϕk(xi,j,sj−1,sj)
= ∑ j = 1 m ∑ a ∈ S , b ∈ S ∑ s ⃗ ∈ S m ; s j − 1 = a , s j = b p ( s ⃗ ∣ x ⃗ i ; w ⃗ ) ϕ k ( x ⃗ i , j , s j − 1 , s j ) =\sum_{j=1}^{m}\sum_{a \in \ S, b \in S}\sum_{\vec{s} \in S^m;s_{j-1}=a, s_j=b} p(\vec{s}|\vec{x}^i;\vec{w})\phi_k(\vec{x}^i,j,s_{j-1},s_j) =j=1∑ma∈ S,b∈S∑s∈Sm;sj−1=a,sj=b∑p(s∣xi;w)ϕk(xi,j,sj−1,sj)
= ∑ j = 1 m ∑ a ∈ S , b ∈ S ϕ k ( x ⃗ i , j , s j − 1 , s j ) ∑ s ⃗ ∈ S m ; s j − 1 = a , s j = b p ( s ⃗ ∣ x ⃗ i ; w ⃗ ) =\sum_{j=1}^{m}\sum_{a \in \ S, b \in S}\phi_k(\vec{x}^i,j,s_{j-1},s_j) \sum_{\vec{s} \in S^m;s_{j-1}=a, s_j=b} p(\vec{s}|\vec{x}^i;\vec{w}) =j=1∑ma∈ S,b∈S∑ϕk(xi,j,sj−1,sj)s∈Sm;sj−1=a,sj=b∑p(s∣xi;w)
= ∑ j = 1 m ∑ a ∈ S , b ∈ S q j i ( a , b ) ϕ k ( x ⃗ i , j , a , b ) =\sum_{j=1}^{m}\sum_{a \in \ S, b \in S} q_j^i(a,b)\phi_k(\vec{x}^i,j,a,b) =j=1∑ma∈ S,b∈S∑qji(a,b)ϕk(xi,j,a,b)
其中:
q
j
i
(
a
,
b
)
=
∑
s
⃗
∈
S
m
;
s
j
−
1
=
a
,
s
j
=
b
p
(
s
⃗
∣
x
⃗
i
;
w
⃗
)
q_j^i(a,b)=\sum_{\vec{s} \in S^m;s_{j-1}=a, s_j=b} p(\vec{s}|\vec{x}^i;\vec{w})
qji(a,b)=s∈Sm;sj−1=a,sj=b∑p(s∣xi;w)
显然 q j i ( a , b ) q_j^i(a,b) qji(a,b) 表示在 p ( s ⃗ ∣ x ⃗ i ; w ⃗ ) p(\vec{s}|\vec{x}^i;\vec{w}) p(s∣xi;w) 分布下,在 j j j 时刻状态为 b b b, j − 1 j-1 j−1 时刻状态为 a a a 的概率,可以递推求解,这里可以用动态规划的方式。
上面大致讲了参数学习过程,实际在代码实现时,只要定义好目标函数即可,大部分深度学习框架可以自动求导,更新参数。
解码过程
解码过程只需要分子最大即可,故解码得分不一定在0-1之间
a
r
g
m
a
x
s
⃗
∈
S
m
e
x
p
(
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
)
∑
s
′
⃗
∈
S
m
e
x
p
(
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
′
⃗
)
)
arg\ max_{\vec{s} \in S^m}\frac{exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}{\sum_{\vec{s'} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s'}))}
arg maxs∈Sm∑s′∈Smexp(w⋅Φ(x,s′))exp(w⋅Φ(x,s))
=
a
r
g
m
a
x
s
⃗
∈
S
m
e
x
p
(
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
)
=arg\ max_{\vec{s} \in S^m}{exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}
=arg maxs∈Smexp(w⋅Φ(x,s))
=
a
r
g
m
a
x
s
⃗
∈
S
m
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
=arg\ max_{\vec{s} \in S^m}{\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s})}
=arg maxs∈Smw⋅Φ(x,s)
=
a
r
g
m
a
x
s
⃗
∈
S
m
w
⃗
⋅
∑
j
=
1
m
ϕ
⃗
(
x
⃗
,
j
,
s
j
−
1
,
s
j
)
=arg\ max_{\vec{s} \in S^m}\ {\vec{w} \cdot \sum_{j=1}^m \vec{\phi}(\vec{x},j, s_{j-1}, s_j)}
=arg maxs∈Sm w⋅j=1∑mϕ(x,j,sj−1,sj)
=
a
r
g
m
a
x
s
⃗
∈
S
m
∑
j
=
1
m
w
⃗
⋅
ϕ
⃗
(
x
⃗
,
j
,
s
j
−
1
,
s
j
)
=arg\ max_{\vec{s} \in S^m}\ {\sum_{j=1}^m \vec{w} \cdot \vec{\phi}(\vec{x},j, s_{j-1}, s_j)}
=arg maxs∈Sm j=1∑mw⋅ϕ(x,j,sj−1,sj)
上述公式中 x ⃗ \vec{x} x 表示某一个输入样本, j j j 表示当前时刻, m m m 表示序列长度
显然这是可以递推的问题,可以用维特比算法解决。
viterbi 维特比算法核心:在到达每一列的时候都会删除不符合最短路径要求的路径,大大降低时间复杂度。更详细可参考:如何通俗地讲解 viterbi 算法?
故本问题,在 j j j时刻的每个状态上,需要保留和标记从 j − 1 j-1 j−1 时刻递推到 j j j 时刻时最大得分路径。
-
初始时, j = 1 j=1 j=1 时
π [ 1 , s ] = w ⃗ ⋅ ϕ ⃗ ( x ⃗ , 1 , s 0 , s ) \pi[1, s] = \vec{w} \cdot \vec{\phi}(\vec{x}, 1, s_0, s) π[1,s]=w⋅ϕ(x,1,s0,s)s 0 s_0 s0 表示初始状态,初始时,需要保留到每个状态的路径,此时不需要过滤得分低的路径(因为初始时,一个状态只有一个路径)
-
当 j = 2... m ; s = 1... k j=2...m;s=1...k j=2...m;s=1...k 时
π [ j , s ] = m a x s ′ ∈ S [ π [ j − 1 , s ′ ] + w ⃗ ⋅ ϕ ⃗ ( x ⃗ , j , s ′ , s ) ] \pi[j,s]=max_{s' \in S}[\pi[j-1, s']+\vec{w} \cdot \vec{\phi}(\vec{x},j, s',s)] π[j,s]=maxs′∈S[π[j−1,s′]+w⋅ϕ(x,j,s′,s)]每个时刻,都在前一个时刻最大路径基础上,选择最大得分路径, π [ j − 1 , s ′ ] \pi[j-1, s'] π[j−1,s′]在前一个时刻,每个状态的最大得分路径,然后加上从 j − 1 j-1 j−1 到 j j j 的路径得分
由此可得:
m
a
x
s
1
.
.
.
s
m
∑
j
=
1
m
w
⃗
⋅
ϕ
⃗
(
x
⃗
,
j
,
s
j
−
1
,
s
j
)
=
m
a
x
s
π
[
m
,
s
]
max_{s_1...s_m} \sum_{j=1}^m \vec{w} \cdot \vec{\phi}(\vec{x},j, s_{j-1}, s_j)=max_s \pi[m,s]
maxs1...smj=1∑mw⋅ϕ(x,j,sj−1,sj)=maxsπ[m,s]
通过上述分析,我们知道该过程的时间复杂度为
O
(
m
k
2
)
O(mk^2)
O(mk2)
BiLSTM-CRF
由上述分析可知,CRF的目标函数为:
L
(
w
⃗
)
=
l
o
g
p
(
s
⃗
∣
x
⃗
;
w
⃗
)
L(\vec{w})= log p(\vec{s}|\vec{x};\vec{w})
L(w)=logp(s∣x;w)
= l o g ( e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ∑ s ⃗ ∈ S m e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ) =log\ (\frac{exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}{\sum_{\vec{s} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}) =log (∑s∈Smexp(w⋅Φ(x,s))exp(w⋅Φ(x,s)))
= w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) − l o g ( ∑ s ⃗ ∈ S m e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ) =\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s})) -log\ ({\sum_{\vec{s} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}) =w⋅Φ(x,s))−log (s∈Sm∑exp(w⋅Φ(x,s)))
目标函数越大越好,损失函数取负即可
再由CRF原始论文 Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data 的定义:
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
=
∑
j
,
k
λ
k
f
k
(
s
j
−
1
,
s
j
,
x
⃗
,
j
)
+
∑
j
,
k
μ
k
g
k
(
s
j
,
x
⃗
,
j
)
\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}) = \sum_{j,k}\lambda_kf_k(s_{j-1},s_j, \vec{x},j)+\sum_{j,k}\mu_kg_k(s_j,\vec{x}, j)
w⋅Φ(x,s)=j,k∑λkfk(sj−1,sj,x,j)+j,k∑μkgk(sj,x,j)
可知: w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) \vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}) w⋅Φ(x,s) 由两部分组成,第一项相当于转移概率矩阵,第二项可以理解为发射概率,
其发射概率可由BiLSTM网络得到。而转移概率矩阵可以理解为BiLSTM-CRF模型需要学习的参数矩阵。
如上图就是 B i L S T M − C R F BiLSTM-CRF BiLSTM−CRF 的网络结构图,输入的词,输出的是词性。需要注意的是,上图中,词性不仅受 B i L S T M BiLSTM BiLSTM影响,还受上一时刻的词性影响。
通过模型可以求得发射矩阵和转移矩阵表达式,从而可以得到目标函数
用BiLSTM显然是有好处的,可以结合上下文两个方向内容来做sequence tagging
定义好参数和目标函数,深度学习框架可以直接求导
该部分代码实现后面会有详细分析。
各模型比较
生成模型到判别模型
上图中白色圆圈表 Y Y Y,灰色圆圈表示 X X X。
有向图表示一个生成模型,其中输出( Y Y Y)在拓扑上先于输入( X X X),即没有 x ∈ X x \in X x∈X可以是输出 y ∈ Y y \in Y y∈Y的父对象。本质上,生成模型是直接描述 输出如何概率地“生成”输入的模型。
在
n
a
i
v
e
B
a
y
e
s
naive\ Bayes
naive Bayes 中:
p
(
y
∣
X
)
=
p
(
X
∣
y
)
⋅
p
(
y
)
p
(
X
)
∝
p
(
X
,
y
)
p(y|X)=\frac{p(X|y) \cdot p(y)}{p(X)} \propto p(X, y)
p(y∣X)=p(X)p(X∣y)⋅p(y)∝p(X,y)
显然里面有 p ( X ∣ y ) p(X|y) p(X∣y),是对 P ( X , y ) P(X, y) P(X,y) 建模,是生成模型,有向图
而逻辑回归:
p ( y = j ∣ x ) = e x T w j ∑ k = 1 K e x T w k p(y=j|x)=\frac{e^{x^Tw_j}}{\sum_{k=1}^{K}e^{x^Tw_k}} p(y=j∣x)=∑k=1KexTwkexTwj
是对 p ( y ∣ X ) p(y|X) p(y∣X) 建模,是无向图
log linear models
目标函数形如:
p ( y ∣ x ; w ⃗ ) = e x p ( w ⃗ ⋅ ϕ ⃗ ( x , y ) ) ∑ y ′ ∈ y e x p ( w ⃗ ⋅ ϕ ⃗ ( x , y ′ ) ) p(y|x;\vec{w})=\frac{exp(\vec{w} \cdot \vec{\phi}(x,y))}{\sum_{y' \in \boldsymbol{y}}exp(\vec{w} \cdot \vec{\phi}(x, y'))} p(y∣x;w)=∑y′∈yexp(w⋅ϕ(x,y′))exp(w⋅ϕ(x,y))
如上面所讲到的 MHMM 和 CRF、logistics回归等模型的目标函数都是形如上式。均是log linear model。
Logistics model是对非序列样本(表格数据)来说,而CRF、MHMM是对序列数据而言。故上图中Logistics model 通过 SEQUENCE 可变成序列数据上的CRF。
BiLSTM-CRF代码分析
代码参考自 pytorch-BiLSTM-CRF-tutorial
CRF的目标函数为:
L
(
w
⃗
)
=
l
o
g
p
(
s
⃗
∣
x
⃗
;
w
⃗
)
L(\vec{w})= log p(\vec{s}|\vec{x};\vec{w})
L(w)=logp(s∣x;w)
= l o g ( e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ∑ s ⃗ ∈ S m e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ) =log\ (\frac{exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}{\sum_{\vec{s} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}) =log (∑s∈Smexp(w⋅Φ(x,s))exp(w⋅Φ(x,s)))
= w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) − l o g ( ∑ s ⃗ ∈ S m e x p ( w ⃗ ⋅ Φ ⃗ ( x ⃗ , s ⃗ ) ) ) =\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s})) -log\ ({\sum_{\vec{s} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}) =w⋅Φ(x,s))−log (s∈Sm∑exp(w⋅Φ(x,s)))
分子较为好算,分母需要计算每个时刻所有状态
获取由BiLSTM模型得到的发射概率矩阵(所有时刻的)
def _get_lstm_features(self, sentence):
self.hidden = self.init_hidden()
embeds = self.word_embeds(sentence).view(len(sentence), 1, -1)
lstm_out, self.hidden = self.lstm(embeds, self.hidden)
lstm_out = lstm_out.view(len(sentence), self.hidden_dim)
lstm_feats = self.hidden2tag(lstm_out)
return lstm_feats
上述代码中的sentence为一个源句子的idx序列,self.hidden2tag为模型中定义好的参数矩阵nn.Linear(hidden_dim, self.tagset_size),用来将BiLSTM的输出映射到tag空间,方法返回的lstm_feats形状为[batch_size, time_step, tag_nums]
得到每个时刻的发射概率矩阵后,再看看怎么结合转移矩阵计算分母的
首先得先定义转移参数矩阵:
self.transitions = nn.Parameter(
torch.randn(self.tagset_size, self.tagset_size))
每两个相邻时刻的转移矩阵是共享的,self.transitions[tags[i + 1], tags[i]] 表示上一个时刻的状态为tags[i]到当前时刻状态为tag[i+1]的概率
def _forward_alg(self, feats):
# Do the forward algorithm to compute the partition function
init_alphas = torch.full((1, self.tagset_size), -10000.)
# START_TAG has all of the score.
init_alphas[0][self.tag_to_ix[START_TAG]] = 0.
# Wrap in a variable so that we will get automatic backprop
forward_var = init_alphas
# Iterate through the sentence
for feat in feats: ## 遍历每个时刻
alphas_t = [] # The forward tensors at this timestep
for next_tag in range(self.tagset_size): ##在每个时刻遍历所有可能的状态
# broadcast the emission score: it is the same regardless of
# the previous tag
emit_score = feat[next_tag].view(
1, -1).expand(1, self.tagset_size) ### 获取在当前时刻为当前状态的发射概率
# the ith entry of trans_score is the score of transitioning to
# next_tag from i
trans_score = self.transitions[next_tag].view(1, -1) ### 从上一时刻所有状态到当前时刻该状态的转移概率(向量)
# The ith entry of next_tag_var is the value for the
# edge (i -> next_tag) before we do log-sum-exp
next_tag_var = forward_var + trans_score + emit_score ### 发射概率+ 转移概率
# The forward variable for this tag is log-sum-exp of all the
# scores.
alphas_t.append(log_sum_exp(next_tag_var).view(1)) ### 将到该时刻该状态的所有路径得分加起来
forward_var = torch.cat(alphas_t).view(1, -1)
terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]]
alpha = log_sum_exp(terminal_var)
return alpha
上述代码中遍历了所有时刻,在每个时刻遍历了所有可能的状态,得到了目标函数的分母。
另外这里需要注意代码中的log_sum_exp函数
def log_sum_exp(vec):
pdb.set_trace()
max_score = vec[0, argmax(vec)]
max_score_broadcast = max_score.view(1, -1).expand(1, vec.size()[1])
return max_score + \
torch.log(torch.sum(torch.exp(vec - max_score_broadcast)))
分母中
l
o
g
∑
s
⃗
∈
S
m
e
x
p
(
w
⃗
⋅
Φ
⃗
(
x
⃗
,
s
⃗
)
)
log {\sum_{\vec{s} \in {S^m}} exp(\vec{w} \cdot \vec{\Phi}(\vec{x}, \vec{s}))}
logs∈Sm∑exp(w⋅Φ(x,s))
=
l
o
g
∑
i
K
e
s
c
o
r
e
i
=log {\sum_i^K e^{score_i}}
=logi∑Kescorei
=
A
+
l
o
g
(
∑
i
=
1
K
e
s
c
o
r
e
i
−
A
)
,
A
=
m
a
x
(
a
1
.
.
.
a
K
)
=A+log({\sum_{i=1}^K}e^{score_i-A}),A=max(a_1...a_K)
=A+log(i=1∑Kescorei−A),A=max(a1...aK)
K表示一共总共的路径数量
训练时,分子(gloden_score) 计算
def _score_sentence(self, feats, tags):
# Gives the score of a provided tag sequence
score = torch.zeros(1)
tags = torch.cat([torch.tensor([self.tag_to_ix[START_TAG]], dtype=torch.long), tags])
for i, feat in enumerate(feats):
score = score + \
self.transitions[tags[i + 1], tags[i]] + feat[tags[i + 1]]
score = score + self.transitions[self.tag_to_ix[STOP_TAG], tags[-1]]
return score
由此可以得到CRF的损失函数了
def neg_log_likelihood(self, sentence, tags):
feats = self._get_lstm_features(sentence)
forward_score = self._forward_alg(feats)
gold_score = self._score_sentence(feats, tags)
return forward_score - gold_score
解码维特比部分代码很简单,这里不再详述
至此,BiLSTM核心代码分析完毕。
个人总结
CRF可以理解,将发射矩阵和转移矩阵联合建模,避免了HMM的独立建模的问题;同时CRF有时在全局(所有时刻)上进行归一化,避免了MHMM的label bias问题。
参考文献
- http://www.cs.columbia.edu/~mcollins/crf.pdf
- https://people.cs.umass.edu/~mccallum/papers/crf-tutorial.pdf
- https://cs.nju.edu.cn/daixinyu/CRF.pdf
- https://speech.ee.ntu.edu.tw/~tlkagk/courses/ML_2016/Lecture/Sequence.pdf
- https://pytorch.org/tutorials/beginner/nlp/advanced_tutorial.html