命名实体识别LSTM+CRF的前向计算推导

文章目录

  • 1. log linear model
    • 1.2 逻辑回归
    • 1.1 CRF与逻辑回归的区别
  • 2. NER中的LSTM+CRF
    • 2.1 CRF的特征定义
    • 2.2 参数估计
    • 2.3 全局正则项的计算推导
  • 参考文献

在用LSTM+CRF做命名实体识别任务时,由于pytorch框架的crf需要自己实现,网上的很多教程都跳过了一些关键部分导致自己难以理解。本文用来记录自己的相关理解,仅针对线性链式的CRF。欢迎指正。

1. log linear model

CRF、MEMM、N元逻辑回归都属于log linear model。我们先来理解这个大类。
p ( y ∣ x ; w ∣ J ∣ ) = exp ⁡ ( w ∣ J ∣ ⋅ F ∣ J ∣ ( x , y ) ) ∑ y ′ ∈ Y exp ⁡ ( w ∣ J ∣ ⋅ F ∣ J ∣ ( x , y ′ ) ) p ( y | x ; \boldsymbol { w }_{|J|} ) = \frac { \exp ( \boldsymbol { w }_{|J|} \cdot \boldsymbol F_{|J|} ( x , y ) ) } { \sum _ { y ^ { \prime } \in \mathcal { Y } } \exp \left( \boldsymbol { w }_{|J|} \cdot \boldsymbol F_{|J|} \left( x , y ^ { \prime } \right) \right) } p(yx;wJ)=yYexp(wJFJ(x,y))exp(wJFJ(x,y))
其中 w \boldsymbol { w } w为模型参数, F ∣ J ∣ ( x , y ) \boldsymbol { F }_{|J|}( x , y ) FJ(x,y)为给定输入特征 x x x,输出标签 y y y的特征向量。

注意:这里模型参数和特征向量都为J, 物理意义是该模型一共有J个特征。点乘表示用这J个特征计算一个分数。与NLP任务中输入序列长度无关!

1.2 逻辑回归

各种log linear model模型的区别,仅仅是在特征函数 F ∣ J ∣ ( x , y ) \boldsymbol { F }_{|J|}( x , y ) FJ(x,y)的定义不同。对于逻辑回归,假设特征x长度为M, 标签类别数为N, 那么 J = M ∗ N J=M*N J=MN。且 F j = f l a t e n ( x × I y = C ) F_j=flaten(\boldsymbol x \times \boldsymbol I_{y=C}) Fj=flaten(x×Iy=C)

1.1 CRF与逻辑回归的区别

CRF与逻辑回归的不同,在于

  • (1)CRF的特征函数 F ∣ J ∣ ( x , y ) \boldsymbol { F }_{|J|}( x , y ) FJ(x,y)考虑了输入数据中的时序信息
    F ∣ J ∣ ( x , y ) = ∑ i = 2 T f ∣ J ∣ ( x i , y i , y i − 1 ) (1.1) \boldsymbol { F }_{|J|}( x , y )=\sum_{i=2}^Tf_{|J|}(x_i, y_i, y_{i-1}) \tag{1.1} FJ(x,y)=i=2TfJ(xi,yi,yi1)(1.1)
  • (2)CRF的y与x都增加了一个维度,即序列长度T

2. NER中的LSTM+CRF

2.1 CRF的特征定义

对于NER任务中,序列长度为T,标签类别数为n的数据,LSTM的输出特征矩阵 B T × n B_{T\times n} BT×n作为CRF层的输入, B i , j B_{i,j} Bi,j为第 i i i个时间步为标签 j j j的概率。NER任务的CRF中我们定义了两个特征函数:

  • 输入特征B (代码中的feats, 可以理解为发射概率矩阵)
  • 和转移特征A (代码中的transition矩阵)

权重 w = [ 1 , 1 ] w=[1,1] w=[1,1]现在重写CRF的特征如下,并将其定义为score:
s c o r e ( y ∣ A , B ) = w ∣ J ∣ ⋅ F ∣ J ∣ ( x , y ) ) = w ⋅ ∑ i = 2 T f ∣ J ∣ ( x i , y i , y i − 1 ) = B 1 , y 1 + ∑ i = 2 T ( B i , y i + A y i − 1 , y i ) \begin{aligned} score(y|A,B) &=\boldsymbol { w }_{|J|} \cdot \boldsymbol F_{|J|} ( x , y ) )\\ &=\boldsymbol { w } \cdot \sum_{i=2}^Tf_{|J|}(x_i, y_i, y_{i-1})\\ &=B_{1, y_1}+\sum_{i=2}^T(B_{i,y_i} + A_{y_{i-1},y_i}) \end{aligned} score(yA,B)=wJFJ(x,y))=wi=2TfJ(xi,yi,yi1)=B1,y1+i=2T(Bi,yi+Ayi1,yi)

理解了这两个特征,就成功的将CRF于NER任务结合了。下面要知道如何估计特征参数,即反向传播A和B。

2.2 参数估计

对于一个训练样本,有一个输入序列x和一个tag序列y。x经过LSTM层得到特征矩阵B。
我们的目标是求现有参数下的概率 p ( y ∣ A , B ) p(\boldsymbol y|A, B) p(yA,B),并最大化这个值,按照老规矩使用其负对数作为loss, 回到log-linear model的定义,:
l o s s = − l o g ( p ( y ∣ A , B ) ) = − l o g ( e x p ( s c o r e ( y ∣ A , B ) ) ∑ y ^ e x p ( s c o r e ( y ^ ∣ A , B ) ) ) = l o g ( ∑ y ^ e x p ( s c o r e ( y ^ ∣ A , B ) ) ) − s c o r e ( y ∣ A , B ) = l o g _ s u m _ e x p ( s c o r e ( y ^ ∣ A , B ) ) ) \begin{aligned} loss &= -log(p(\boldsymbol y|A,B) )\\ &= -log(\frac{exp(score(y|A,B))}{\sum_{\hat y}exp(score(\hat y|A,B))})\\ &=log(\sum_{\hat y}exp(score(\hat y|A,B))) - score(y|A,B)\\ &=log\_sum\_exp(score(\hat y|A,B))) \end{aligned} loss=log(p(yA,B))=log(y^exp(score(y^A,B))exp(score(yA,B)))=log(y^exp(score(y^A,B)))score(yA,B)=log_sum_exp(score(y^A,B)))

一旦loss确定,剩下的事就可以交给pytorch框架来自动优化了。但是上面这个loss怎么计算呢? s c o r e ( y ∣ A , B ) score(y|A,B) score(yA,B)这一项好说,线性复杂度O(T)。

2.3 全局正则项的计算推导

Z = l o g ( ∑ y ^ e x p ( s c o r e ( y ^ ∣ A , B ) ) ) Z = log(\sum_{\hat y}exp(score(\hat y|A,B))) Z=log(y^exp(score(y^A,B)))这一项,如果用暴力计算,就是要先算出每一个时间步的所有可能路径,复杂度为 O ( T n T ) O(Tn^T) O(TnT), 分类数稍多一点就会凉。需要想办法消掉指数复杂度,而很巧的是,这确实可以在输入序列上转换为子问题,从而使用动态规划算法。根据上述score的计算公式,可以将输入序列长度为 T T T的正则项写为:
Z = l o g ( ∑ y ^ e x p ( s c o r e ( y ^ ( 1 , T − 1 ) ∣ A , B ) + s c o r e ( y ^ ( T − 1 , T ) ∣ A , B ) ) ) = l o g ( ∑ y ^ ( e s c o r e ( y ^ ( 1 , T − 1 ) ∣ A , B ) ⋅ e s c o r e ( y ^ ( T − 1 , T ) ∣ A , B ) ) ) Z=log(\sum_{\hat y}exp(score(\hat y^{(1,T-1)}|A,B)+score(\hat y^{(T-1,T)}|A,B)))\\ =log(\sum_{\hat y}(e^{score(\hat y^{(1,T-1)}|A,B)}\cdot e^{score(\hat y^{(T-1,T)}|A,B)})) Z=log(y^exp(score(y^(1,T1)A,B)+score(y^(T1,T)A,B)))=log(y^(escore(y^(1,T1)A,B)escore(y^(T1,T)A,B)))
注意这里 s c o r e ( y ^ ( T − 1 , T ) ∣ A , B ) = B T , y T + A y T − 1 , y T score(\hat y^{(T-1,T)}|A,B)=B_{T,y_T} + A_{y_{T-1},y_T} score(y^(T1,T)A,B)=BT,yT+AyT1,yT,表示所有路径在第T-1到第T步的分数,将其作为系数,合并同类项:
Z ( T ) = l o g ( ∑ e s c o r e ( y ^ ( T − 1 , T ) ∣ A , B ) ) ∑ y ^ ( e s c o r e ( y ^ ( 1 , T − 1 ) ∣ A , B ) ) = Z ( T − 1 ) + l o g _ s u m _ e x p ( s c o r e ( y ^ ( T − 1 , T ) ∣ A , B ) ) Z^{(T)}=log(\sum e^{score(\hat y^{(T-1,T)}|A,B)}) \sum_{\hat y}(e^{score(\hat y^{(1,T-1)}|A,B)})\\ =Z^{(T-1)}+log\_sum\_exp(score(\hat y^{(T-1,T)}|A,B)) Z(T)=log(escore(y^(T1,T)A,B))y^(escore(y^(1,T1)A,B))=Z(T1)+log_sum_exp(score(y^(T1,T)A,B))
到这里就该知道是标准的动态规划了。

参考文献

  1. Pytorch Bi-LSTM + CRF 代码详解
  2. Bi-LSTM-CRF for Sequence Labeling
  3. Bi-LSTM Conditional Random Field Discussion
  4. 系列文章:CRF Layer on the Top of BiLSTM - 5

你可能感兴趣的:(AI调参侠)