线性条件随机场代码解读

  NERCRF是必不可少的环节,特地看了一遍CRF相关理论以及allennlpCRF的代码,特在这里笔记记录下来!

1.线性CRF简介

1.1一般形式

  关于线性条件随机场的详细介绍,请参考李航老师的《统计学习方法》或者这里,这里仅仅给出一般的公式定义。
  设 P(Y|X) P ( Y | X ) 为线性链条件随机场,则在随机变量 X X 取值为 x x 的条件下,随机变量 Y Y 取值为 y y 的条件概率具有如下形式(注意 x x , y y 都是序列):

P(y|x)=1Z(x)exp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i))(11.10) P ( y | x ) = 1 Z ( x ) e x p ( ∑ i , k λ k t k ( y i − 1 , y i , x , i ) + ∑ i , l μ l s l ( y i , x , i ) ) ( 11.10 )

其中,
Z(x)=yexp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i))(11.11) Z ( x ) = ∑ y e x p ( ∑ i , k λ k t k ( y i − 1 , y i , x , i ) + ∑ i , l μ l s l ( y i , x , i ) ) ( 11.11 )

式子中, tk t k 转移特征函数,依赖于当前和前一个位置 sl s l 状态特征函数,依赖于当前位置 λk λ k μl μ l 是对应的权重。 Z(x) Z ( x ) 是规范化因子,求和是在所有可能的输出序列上进行的(注意这个所有可能不是任意的组合,这需要依赖于 x x 的取值)。

1.2简化形式

  注意到条件随机场式(11.10)中同一特征在各个位置都有定义,可以对同一个特征在各个位置求和,将局部特征函数转哈U为一个全局特征函数,这样就可以将条件随机场写成权值向量和特征向量(包括转移特征和状态特征)的内积形式,即条件随机场的简化形式。
  首先将转移特征和状态特征及其权值用统一的符号表示,设有 K1 K 1 个转换特征, K2 K 2 个状态特征, K=K1+K2 K = K 1 + K 2 ,记:

fk(yi1,yi,x,i)={tk(yi1,yi,x,i),sl(yi,x,i),k=1,2,...,Kk=K1+l;l=1,2,...,K2(11.12) f k ( y i − 1 , y i , x , i ) = { t k ( y i − 1 , y i , x , i ) , k = 1 , 2 , . . . , K s l ( y i , x , i ) , k = K 1 + l ; l = 1 , 2 , . . . , K 2 ( 11.12 )

然后,对转移与状态特征在各个位置i求和,记作:
fk(y,x)=infk(yi1,yi,x,i),k=1,2,...,K(11.13) f k ( y , x ) = ∑ i n f k ( y i − 1 , y i , x , i ) , k = 1 , 2 , . . . , K ( 11.13 )

wk w k 表示特征 fk(y,x) f k ( y , x ) 的权值,即:
wk={λk,μl,k=1,2,...,Kk=K1+l;l=1,2,...,K2(11.14) w k = { λ k , k = 1 , 2 , . . . , K μ l , k = K 1 + l ; l = 1 , 2 , . . . , K 2 ( 11.14 )

于是用上面的简化形式,条件随机场可以表示为:
P(y|x)=1Z(x)expk=1Kwkfk(y,x)(11.15) P ( y | x ) = 1 Z ( x ) e x p ∑ k = 1 K w k f k ( y , x ) ( 11.15 )

Z(x)=yexpk=1Kwkfk(y,x)(11.16) Z ( x ) = ∑ y e x p ∑ k = 1 K w k f k ( y , x ) ( 11.16 )

若以w表示权值向量,即:
w=(w1,w2,...,wK)T w = ( w 1 , w 2 , . . . , w K ) T ,以 F(y,x)=(f1(y,x),f2(y,x),...,fK(y,x))T F ( y , x ) = ( f 1 ( y , x ) , f 2 ( y , x ) , . . . , f K ( y , x ) ) T ,则条件随机场可以写成向量 w w F(y,x) F ( y , x ) 的内积形式:
Pw(y|x)=1Z(x)exp(wF(y,x))(11.19) P w ( y | x ) = 1 Z ( x ) e x p ( w ∗ F ( y , x ) ) ( 11.19 )

其中,
Zw(x)=yexp(wF(y,x))(11.20) Z w ( x ) = ∑ y e x p ( w ∗ F ( y , x ) ) ( 11.20 )

1.3条件随机场的矩阵形式

  条件随机场还可以由矩阵表示,事实上,在代码实现中,我们肯定需要用到矩阵运算的!假设 Pw(y|x) P w ( y | x ) 是由式子 (11.15)(11.16) ( 11.15 ) 和 ( 11.16 ) 给出的线性链条件随机场,表示对给定观测序列 x x ,相应的标记序列 y y 的条件概率。引进特殊的起点和终点标记 y0=start,yn+1=stop y 0 = s t a r t , y n + 1 = s t o p ,这时 Pw(y|x) P w ( y | x ) 可以通过矩阵形式表示。
  对观测序列 x x 的每一个位置 i=1,2,...,n+1 i = 1 , 2 , . . . , n + 1 ,定义一个 m m 阶矩阵( m m 是标记 yi y i 取值的个数)

Mi(x)=[Mi(yi1,yi|x)](11.21) M i ( x ) = [ M i ( y i − 1 , y i | x ) ] ( 11.21 )

Mi(yi1,yi|x)=exp(Wi(yi1,yi|x))(11.22) M i ( y i − 1 , y i | x ) = e x p ( W i ( y i − 1 , y i | x ) ) ( 11.22 )

Wi(yi1,yi|x)=k=1Kwkfk(yi1,yi|x)(11.23) W i ( y i − 1 , y i | x ) = ∑ k = 1 K w k f k ( y i − 1 , y i | x ) ( 11.23 )

这样,给定观察序列x,相应标记序列y的非规范化概率可以通过该序列 n+1 n + 1 个矩阵适当元素的乘积 n+1i=1Mi(yi,yi|x) ∏ i = 1 n + 1 M i ( y i , y i | x ) 表示.于是,条件概率 Pw(y|x) P w ( y | x ) 是:
Pw(y|x)=1Z(x)i=1n+1Mi(yi,yi|x)(11.24) P w ( y | x ) = 1 Z ( x ) ∏ i = 1 n + 1 M i ( y i , y i | x ) ( 11.24 )

其中 Zw(x) Z w ( x ) 为规范化因子,是 (n+1) ( n + 1 ) 个矩阵的乘积的 (start,stop) ( s t a r t , s t o p ) 元素:
Zw(x)=(M1(x)M2(x)...Mn+1(x))start,stop Z w ( x ) = ( M 1 ( x ) M 2 ( x ) . . . M n + 1 ( x ) ) s t a r t , s t o p

注意, y0=start y 0 = s t a r t yn+1=stop y n + 1 = s t o p 表示开始和终止状态,规范化因子 Zw(x) Z w ( x ) 是以 start s t a r t 为起点 stop s t o p 为终点通过状态的所有路径 y1y2...yn y 1 y 2 . . . y n 的非规范化概率 n+1i=1Mi(yi,yi|x) ∏ i = 1 n + 1 M i ( y i , y i | x ) 之和, 这个所有路径与 x x 的取值也是息息相关的, x x 能够决定各位置各标签的得分!.

  下面,我们将1.1和1.3的内容拼接起来,证明二者的一致性!

P(y|x)=1Z(x)exp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i)) P ( y | x ) = 1 Z ( x ) e x p ( ∑ i , k λ k t k ( y i − 1 , y i , x , i ) + ∑ i , l μ l s l ( y i , x , i ) )

这里,我们仅仅考虑后面的非规范化项。
exp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i))= e x p ( ∑ i , k λ k t k ( y i − 1 , y i , x , i ) + ∑ i , l μ l s l ( y i , x , i ) ) =

exp(i(kλktk(yi1,yi,x,i)+lμlsl(yi,x,i)))= e x p ( ∑ i ( ∑ k λ k t k ( y i − 1 , y i , x , i ) + ∑ l μ l s l ( y i , x , i ) ) ) =

iexp(kλktk(yi1,yi,x,i)+lμlsl(yi,x,i))= ∏ i e x p ( ∑ k λ k t k ( y i − 1 , y i , x , i ) + ∑ l μ l s l ( y i , x , i ) ) =

iexp(k=1Kwkfk(yi1,yi,x,i))= ∏ i e x p ( ∑ k = 1 K w k f k ( y i − 1 , y i , x , i ) ) =

iexp(Wi(yi1,yi|x))=iMi(yi1,yi|x)=iMi(x) ∏ i e x p ( W i ( y i − 1 , y i | x ) ) = ∏ i M i ( y i − 1 , y i | x ) = ∏ i M i ( x )

其中第二步到第三步是根据 exp e x p 相加可以展开为连乘的特性,第三步到第四步用到了 1.2中的简化形式,后面就是直接套用 M M 的定义了。通过这个证明可以发现: 无论是先将所有得分先加起来做 exp e x p 还是直接先 exp e x p 再连乘,答案都是一样的!实现的时候,可以考虑这两种不同的方式!

2.前向-后向算法

  条件随机场(CRF)完全由特征函数 tk,sl t k , s l 和对应的权重 λk,μl λ k , μ l 确定,我们需要利用前向-后向算法,计算出给定输入序列和对应的实际标签序列的 loglikelihood l o g − l i k e l i h o o d 概率值,然后通过最大化这个概率值,来更新上面特征和权重中的参数,实现学习的效果! 学习完这些参数之后,对于一个给定的输入序列,我们可以用维特比算法找出当前参数下得分最高的预测标签序列!
  这里讲解学习过程中一个很重要的算法,前向-后向算法!
  对于每个指标 i=0,1,...,n+1 i = 0 , 1 , . . . , n + 1 (包括了start和stop),定义前向向量 αi(x) α i ( x ) :

α0(y|x)={1,0,y=start(11.26) α 0 ( y | x ) = { 1 , y = s t a r t 0 , 否则 ( 11.26 )

递推公式为:
αTi(yi|x)=αTi1(yi1|x)[Mi(yi1,yi|x)],i=1,2,...,n+1(11.27) α i T ( y i | x ) = α i − 1 T ( y i − 1 | x ) [ M i ( y i − 1 , y i | x ) ] , i = 1 , 2 , . . . , n + 1 ( 11.27 )
又可以表示为:
αTi(x)=αTi1(x)Mi(x)(11.28) α i T ( x ) = α i − 1 T ( x ) M i ( x ) ( 11.28 )

αTi(yi|x) α i T ( y i | x ) 表示在位置 i i 的标记是 yi y i 并且到位置 i i 的前部分标记序列的非规范化概率, yi y i 可取的值由 m m 个,所以 αi(x) α i ( x ) m m 维列向量。为了更好的理解递推过程,我们可以对前几个 α α 进行展开,当然 M M 也进行相应的展开。
α1(x)=α0(x)M1(x)=α0(x)exp(k=1Kwkfk(y0,y1,x,1)) α 1 ( x ) = α 0 ( x ) M 1 ( x ) = α 0 ( x ) e x p ( ∑ k = 1 K w k f k ( y 0 , y 1 , x , 1 ) )

α2(x)=α0(x)exp(k=1Kwkfk(y0,y1,x,1))exp(k=1Kwkfk(y1,y2,x,2)) α 2 ( x ) = α 0 ( x ) e x p ( ∑ k = 1 K w k f k ( y 0 , y 1 , x , 1 ) ) e x p ( ∑ k = 1 K w k f k ( y 1 , y 2 , x , 2 ) )

.... . . . .

αi(x)=α0(x)exp(k=1Kwkfk(y0,y1,x,1))...(k=1Kwkfk(yi1,yi,x,i)) α i ( x ) = α 0 ( x ) e x p ( ∑ k = 1 K w k f k ( y 0 , y 1 , x , 1 ) ) . . . ( ∑ k = 1 K w k f k ( y i − 1 , y i , x , i ) )

注意,这里的连乘是 exp e x p 连乘,转换为先连加在 exp e x p 是等价的。
  同样,对每个指标 i=0,1,...,n+1 i = 0 , 1 , . . . , n + 1 ,定义后向向量 βi(x) β i ( x ) :
βn+1(yn+1|x)={1,0,yn+1=stop(11.29) β n + 1 ( y n + 1 | x ) = { 1 , y n + 1 = s t o p 0 , 否则 ( 11.29 )

βi(yi|x)=[Mi(yi,yi+1|x)]βi+1(yi+1|x) β i ( y i | x ) = [ M i ( y i , y i + 1 | x ) ] β i + 1 ( y i + 1 | x )

又可以表示为
βi(x)=Mi+1(x)βi+1(x) β i ( x ) = M i + 1 ( x ) β i + 1 ( x )

βi(yi|x) β i ( y i | x ) 表示在位置 i i 的标记为 yi y i 并且从 i+1 i + 1 n n 的后部分标记序列的非规范化概率。
  由前向-后向定义不难得到:
Z(x)=αTn(x)1=1Tβ1(x) Z ( x ) = α n T ( x ) ∗ 1 = 1 T ∗ β 1 ( x )

这里, 1 1 是元素均为1的 m m 维列向量。
  你会发现,前后向算法本质上差不多,目的也是一样的,只是方向不同!

3.CRF优化问题

3.1正确序列的概率表达式

  我们这里以bi-LSTM + CRF为例子。假设输入为:

X=(x1,x2,...,xn) X = ( x 1 , x 2 , . . . , x n )

我们假设 P P 是通过 biLSTM b i − L S T M 预测的各个位置各标签的得分矩阵,大小为 nk n ∗ k k k 是独立的标签的总数量, Pi,j P i , j 是句中第 i i 个词预测第 j j 个标签的得分。假设句子预测的标签为:
y=(y1,y2,...,yn) y = ( y 1 , y 2 , . . . , y n )

我们定义它的得分为:
s(X,y)=i=1nAyi1,yi+i=1nPi,yiy0start s ( X , y ) = ∑ i = 1 n A y i − 1 , y i + ∑ i = 1 n P i , y i 其 中 y 0 为 s t a r t 标 签

你可能会觉得这里为什么和1.1小节中的式(11.10)略有不同,(11.10)中分子中多了exp是因为它做了一个softmax操作!本质上二者是一致的(分子部分)。其中 Ai1,yi A i − 1 , y i 对应转换特征,仅仅有一个转换特征,也就是 k=1 k = 1 ; Pi,yi P i , y i 是状态特征,仅仅有一个,也就是 l=1 l = 1 其中 A A 标签转换得分矩阵,即从一种标签转化为另一种标签的分数,这是需要学习的参数;我们一般会为 A A 加上两个标签 start s t a r t end e n d 标签,或者称为 stop s t o p ,分别对应 y0yn+1 y 0 和 y n + 1
  我们的目标是让目标标签序列的总体得分尽可能的大。用 softmax s o f t m a x 表示就是:
p(y|X)=es(X,y)y˘YXes(X,y˘) p ( y | X ) = e s ( X , y ) ∑ y ˘ ∈ Y X e s ( X , y ˘ )

这个式子和式 (11.10) ( 11.10 ) 就完全等价了,其中 YX Y X 表示输入序列 X X 可能预测的所有标签序列集合。在训练的时候,我们一般是最大化正确标签序列对应的 logprobability l o g − p r o b a b i l i t y 值:
log(p(y|X))=s(X,y)logy˘YXes(X,y˘)=s(X,y)logaddy˘YXs(X,y˘) l o g ( p ( y | X ) ) = s ( X , y ) − l o g ( ∑ y ˘ ∈ Y X e s ( X , y ˘ ) ) = s ( X , y ) − l o g a d d y ˘ ∈ Y X s ( X , y ˘ )

所以,我们在计算这个 loglikelihood l o g − l i k e l i h o o d 概率时,需要计算两部分,前一部分对应分子部分,后一部分对应分母部分。我们希望能够迭代计算出相应的值!

3.2 计算log-likelihood概率

  计算分两部分进行,第一部分是分子部分的值,也就是 s(X,y) s ( X , y ) ;第二部分是分母部分的值,也就是 log(y˘YXes(X,y˘)) l o g ( ∑ y ˘ ∈ Y X e s ( X , y ˘ ) )

3.2.1 分子部分

  首先给出 S(X,y) S ( X , y ) 分数计算方式:

S(X,y)=i=1nAyi1,yi+i=1nPi,yi S ( X , y ) = ∑ i = 1 n A y i − 1 , y i + ∑ i = 1 n P i , y i

在代码实现中,我们是沿着句子中每个位置进行推进迭代的,也就是使用前向算法,我们列举每一步迭代的结果:
S1=i=11Ayi1,yi+i=11Pi,yi=Ay0,y1+P1,y1 S 1 = ∑ i = 1 1 A y i − 1 , y i + ∑ i = 1 1 P i , y i = A y 0 , y 1 + P 1 , y 1

S2=i=12Ayi1,yi+i=12Pi,yi=Ay0,y1+Ay1,y2+P1,y1+P2,y2=S1+Ay1,y2+P2,y2 S 2 = ∑ i = 1 2 A y i − 1 , y i + ∑ i = 1 2 P i , y i = A y 0 , y 1 + A y 1 , y 2 + P 1 , y 1 + P 2 , y 2 = S 1 + A y 1 , y 2 + P 2 , y 2

... . . .
Sn=i=1nAyi1,yi+i=1nPi,yi=Sn1+Ayn1,yn+Pn,yn S n = ∑ i = 1 n A y i − 1 , y i + ∑ i = 1 n P i , y i = S n − 1 + A y n − 1 , y n + P n , y n

所以,我们在沿着句子中某个位置 i i 进行迭代时,只需要一直记录对应的 Si1,A,P S i − 1 , A , P 这三项值,就能够计算出分子部分的值!

3.2.2 分母部分

  分母部分的计算相对来说比较麻烦,也需要构造每一步迭代项,分母部分计算公式如下:

Z(X)=logy˘YXes(X,y˘)=logy˘YXexp(i=1nAyi1,yi+i=1nPi,yi) Z ( X ) = l o g ( ∑ y ˘ ∈ Y X e s ( X , y ˘ ) ) = l o g ( ∑ y ˘ ∈ Y X e x p ( ∑ i = 1 n A y i − 1 , y i + ∑ i = 1 n P i , y i ) )

我们也按照句子中的每一个位置进行展开!
Z1=logy˘tagsexp(i=11Ayi1,yi+i=11Pi,yi)= Z 1 = l o g ( ∑ y ˘ ∈ t a g s e x p ( ∑ i = 1 1 A y i − 1 , y i + ∑ i = 1 1 P i , y i ) ) =

logy˘tagsexp(Ay0˘,y1˘+P1,y˘1)(3,1) l o g ( ∑ y ˘ ∈ t a g s e x p ( A y 0 ˘ , y 1 ˘ + P 1 , y ˘ 1 ) ) ( 3 , 1 )

其中 tags t a g s 表示所有标签集合, y˘i y ˘ i 表示位置 i i 的对应的任意标签。
Z2=logy˘tagsexp(i=12Ay˘i1,y˘i+i=1nPi,y˘i)= Z 2 = l o g ( ∑ y ˘ ∈ t a g s e x p ( ∑ i = 1 2 A y ˘ i − 1 , y ˘ i + ∑ i = 1 n P i , y ˘ i ) ) =

logy˘tagsexp(Ay˘0,y˘1+Ay˘1,y˘2+P1,y˘1+P2,y˘2)= l o g ( ∑ y ˘ ∈ t a g s e x p ( A y ˘ 0 , y ˘ 1 + A y ˘ 1 , y ˘ 2 + P 1 , y ˘ 1 + P 2 , y ˘ 2 ) ) =

logy˘tagsexp(Ay˘0,y˘1+P1,y˘1)exp(Ay˘1,y˘2+P2,y˘2)= l o g ( ∑ y ˘ ∈ t a g s e x p ( A y ˘ 0 , y ˘ 1 + P 1 , y ˘ 1 ) e x p ( A y ˘ 1 , y ˘ 2 + P 2 , y ˘ 2 ) ) =

logy˘tagsexp(Ay˘0,y˘1+P1,y˘1)y˘tagsexp(Ay˘1,y˘2+P2,y˘2)(3,2) l o g ( ∑ y ˘ ∈ t a g s e x p ( A y ˘ 0 , y ˘ 1 + P 1 , y ˘ 1 ) ∑ y ˘ ∈ t a g s e x p ( A y ˘ 1 , y ˘ 2 + P 2 , y ˘ 2 ) ) ( 3 , 2 )

从第三步到第四步可以展开为两个求和,因为长度为2的任意标签序列是两个长度为1的任意标签序列的任意组合。注意根据式 (3,1) ( 3 , 1 )
Z1=logy˘tagsexp(Ay0˘,y1˘+P1,y˘1) Z 1 = l o g ( ∑ y ˘ ∈ t a g s e x p ( A y 0 ˘ , y 1 ˘ + P 1 , y ˘ 1 ) )
,
所以
exp(Z1)=y˘tagsexp(Ay˘0,y˘1+P1,y˘1)(3,4) e x p ( Z 1 ) = ∑ y ˘ ∈ t a g s e x p ( A y ˘ 0 , y ˘ 1 + P 1 , y ˘ 1 ) ( 3 , 4 )

将这个式子带入到式子 (3.2) ( 3.2 ) 的前半部分,所以:
Z2=logexp(Z1)y˘tagsexp(Ay˘1,y˘2+P2,y˘2)= Z 2 = l o g ( e x p ( Z 1 ) ∑ y ˘ ∈ t a g s e x p ( A y ˘ 1 , y ˘ 2 + P 2 , y ˘ 2 ) ) =

logy˘tagsexp(Z1+Ay˘1,y˘2+P2,y˘2) l o g ( ∑ y ˘ ∈ t a g s e x p ( Z 1 + A y ˘ 1 , y ˘ 2 + P 2 , y ˘ 2 ) )

这里 Z1 Z 1 可以直接放进去是因为此时的 Z1 Z 1 已经计算出来了,是一个常量值了。
进行推广:
.... . . . .
Zn=logy˘tagsexp(Zn1+Ay˘n1,y˘n+P2,y˘2) Z n = l o g ( ∑ y ˘ ∈ t a g s e x p ( Z n − 1 + A y ˘ n − 1 , y ˘ n + P 2 , y ˘ 2 ) )

这样我们也找到了递推项,当我们沿着句子的每个位置进行迭代时,只需要一直记录对应的 Zi1,A,P Z i − 1 , A , P 这三个值,就可以计算出分母部分的值。

4.CRF学习算法

  一般使用梯度下降法, tensorflow t e n s o r f l o w pytorch p y t o r c h 等学习工具都提供了梯度下降法的支持!

5.源码解读

  下面对allennlp中提供的CRF源码进行解读!代码如下:

def allowed_transitions(constraint_type: str, tokens: Dict[int, str]) -> List[Tuple[int, int]]:
    """
    Given tokens and a constraint type, returns the allowed transitions. It will
    additionally include transitions for the start and end states, which are used
    by the conditional random field.

    Parameters
    ----------
    constraint_type : ``str``, required
        Indicates which constraint to apply. Current choices are "BIO" and "BIOUL".
    tokens : ``Dict[int, str]``, required
        A mapping {token_id -> token}. Most commonly this would be the value from
        Vocabulary.get_index_to_token_vocabulary()
        这应该是标签的tokens, 即所有的标签列表->id列表,类似于idx2tag

    Returns
    -------
    ``List[Tuple[int, int]]``
        The allowed transitions (from_token_id, to_token_id).

    这个方法的作用是,预选准备�

你可能感兴趣的:(Python,数据挖掘与机器学习,NLP)