机器学习-- CRF总结

博客内容将首发在微信公众号"跟我一起读论文啦啦",上面会定期分享机器学习、深度学习、数据挖掘、自然语言处理等高质量论文,欢迎关注!
在这里插入图片描述

本次要总结的是条件随机场(CRF)相关知识

从hmm缺点和MHMM标注偏置讲起

HMM回顾

HMM基本概念

hmm 是对 p ( x , y ) p(x,y) p(x,y) 联合概率进行建模,为生成式模型。

  1. 问题建模:
    在这里插入图片描述

    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(Xy)

    注意是联合概率建模

  2. 模型推断:
    y ^ = a r g m a x y ∈ Y P ( x , y ) \hat{y} = argmax_{y \in Y}P(x, y) y^=argmaxyYP(x,y)

    维特比算法进行推断,维特比的核心是:达每一列的时候都会删除不符合最短路径要求的路径,大大降低时间复杂度

  3. 参数估计

    H M M HMM HMM 是生成模型,因为它对状态序列本身的分布 P ( y ) P(y) P(y) (状态转移矩阵)和给定状态后观测值的分布 P ( x ∣ y ) P(x|y) P(xy) (发射矩阵)都进行了建模。有监督时可以从训练数据中很容易统计出

有三个主要因素

  • 初始概率分布 π \pi π
  • 状态转移概率分布 A A A
  • 观测概率 B B B,也称发射矩阵

在有监督方法里,这三个因素可以从训练样本轻松统计到。

两个齐次假设:

  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(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(itit1,ot1,it2,ot2...i1,o1)=P(itit1)
    也即是当前时刻的隐状态只与前一时刻的隐状态有关。

  2. 观测独立性假设:
    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(otiT,oT,iT1,oT1,...,i1,o1)=P(otit)

可以用下图表示:
在这里插入图片描述

注意箭头方向,表示依赖关系

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^=argmaxyYP(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(VN)=9/10P(DN)=1/10
观测矩阵中有
P ( a ∣ V ) = 1 / 2 , P ( a ∣ D ) = 1 P(a|V)=1/2,P(a|D)=1 P(aV)=1/2P(aD)=1

那么在预测样本中,存在一个样本的,上一时刻的状态 y t − 1 = N y_{t-1}=N yt1=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/101/2=0.45,取 D D D 时,概率为 1 / 10 ∗ 1 = 0.1 1/10*1 =0.1 1/101=0.1

那么由此推断出当前时刻为状态 V V V 合理吗? 训练集中明明出现了这个exist sample
在这里插入图片描述
模型却没有选 D D D 这个状态,而预测出了一个训练集中从未出现过的样本。

由此可以得到如下结论

  • HMM 能生成训练集中从未出现过的样本,而训练集中明确存在的样本,HMM不一定就会生成。
  • 当训练集足够大时,HMM模型表现可能并不好,但是训练集比较小的时候,预测效果反而可能比较好。

那么造成这样的原因是什么呢?

  • HMM 模型在训练时,对状态转移矩阵和观测(发射)矩阵是分开建模的,两者是独立的。

MHMM 回顾

MHMM 基本概念

p ( s ∣ x ) p(s|x) p(sx) 进行建模,是判别式模型。
在这里插入图片描述
上式中 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}) si1)。如下图:
在这里插入图片描述

同样注意箭头方向,表示依赖

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(sisi1,x1...xm)=sSexp(w ϕ (x1...xm,i,si1,s))exp(w ϕ (x1...xm,i,si1,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 loglinear 模型的角度看CRF模型。

CRF对 p ( s ∣ x ) p(s|x) p(sx) 进行建模,是判别式模型
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,....,smx1,...,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 sSm 表示 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 sSm 可以看出,分母计算量巨大,需要计算所有时刻的所有状态的值。

我们可以看下 Φ ⃗ ( 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=1mϕ (x ,j,sj1,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=1mϕk(x ,j,sj1,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(sj1,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(sj1,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 )=sexp(j,kλkfk(sj1,sx ,j)+j,kμkgk(s,x ,j))exp(j,kλkfk(sj1,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 {(x i,s i)}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 x i=x1i,x2i,...,xmi s ⃗ i = s 1 i , . . . , s m i \vec{s}^i =s_1^i,...,s_m^i s i=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=1nlogp(s ix i;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=1nlogp(s ix i;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(x i,s i)is Smp(x x i;w )Φk(x i,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(x i,s i)=ij=1mϕk(x i,j,sj1i,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 Smp(x x i;w )Φk(x i,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 Smp(x x i;w )j=1mϕk(x i,j,sj1,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=1ms Smp(s x i;w)ϕk(x i,j,sj1,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=1ma S,bSs Sm;sj1=a,sj=bp(s x i;w )ϕk(x i,j,sj1,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=1ma S,bSϕk(x i,j,sj1,sj)s Sm;sj1=a,sj=bp(s x i;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=1ma S,bSqji(a,b)ϕk(x i,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;sj1=a,sj=bp(s x i;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 x i;w ) 分布下,在 j j j 时刻状态为 b b b j − 1 j-1 j1 时刻状态为 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 Sms 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=1mϕ (x ,j,sj1,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=1mw ϕ (x ,j,sj1,sj)

上述公式中 x ⃗ \vec{x} x 表示某一个输入样本, j j j 表示当前时刻, m m m 表示序列长度

显然这是可以递推的问题,可以用维特比算法解决。

viterbi 维特比算法核心:在到达每一列的时候都会删除不符合最短路径要求的路径,大大降低时间复杂度。更详细可参考:如何通俗地讲解 viterbi 算法?

故本问题,在 j j j时刻的每个状态上,需要保留和标记从 j − 1 j-1 j1 时刻递推到 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...ms=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]=maxsS[π[j1,s]+w ϕ (x ,j,s,s)]

    每个时刻,都在前一个时刻最大路径基础上,选择最大得分路径, π [ j − 1 , s ′ ] \pi[j-1, s'] π[j1,s]在前一个时刻,每个状态的最大得分路径,然后加上从 j − 1 j-1 j1 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=1mw ϕ (x ,j,sj1,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 Smexp(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(sj1,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 BiLSTMCRF 的网络结构图,输入的词,输出的是词性。需要注意的是,上图中,词性不仅受 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 xX可以是输出 y ∈ Y y \in Y yY的父对象。本质上,生成模型是直接描述 输出如何概率地“生成”输入的模型。

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(yX)=p(X)p(Xy)p(y)p(X,y)

显然里面有 p ( X ∣ y ) p(X|y) p(Xy),是对 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=jx)=k=1KexTwkexTwj

是对 p ( y ∣ X ) p(y|X) p(yX) 建模,是无向图

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(yx;w )=yyexp(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 Smexp(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 Smexp(w Φ (x ,s ))
= l o g ∑ i K e s c o r e i =log {\sum_i^K e^{score_i}} =logiKescorei
= 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=1KescoreiA)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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值