NER中CRF是必不可少的环节,特地看了一遍CRF相关理论以及allennlp中CRF的代码,特在这里笔记记录下来!
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(yi−1,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(yi−1,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(yi−1,yi,x,i)={tk(yi−1,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(yi−1,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)exp∑k=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)=∑yexp∑k=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(w∗F(y,x))(11.19) P w ( y | x ) = 1 Z ( x ) e x p ( w ∗ F ( y , x ) ) ( 11.19 )
其中,
Zw(x)=∑yexp(w∗F(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(yi−1,yi|x)](11.21) M i ( x ) = [ M i ( y i − 1 , y i | x ) ] ( 11.21 )
Mi(yi−1,yi|x)=exp(Wi(yi−1,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(yi−1,yi|x)=∑k=1Kwkfk(yi−1,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(yi−1,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(yi−1,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(yi−1,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(yi−1,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(yi−1,yi,x,i))= ∏ i e x p ( ∑ k = 1 K w k f k ( y i − 1 , y i , x , i ) ) =
∏iexp(Wi(yi−1,yi|x))=∏iMi(yi−1,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 确定,我们需要利用前向-后向算法,计算出给定输入序列和对应的实际标签序列的 log−likelihood 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)=αTi−1(yi−1|x)[Mi(yi−1,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)=αTi−1(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(yi−1,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 是通过
bi−LSTM b i − L S T M 预测的各个位置各标签的得分矩阵,大小为
n∗k 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=1nAyi−1,yi+∑i=1nPi,yi其中y0为start标签 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操作!本质上二者是一致的(分子部分)。其中 Ai−1,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 ,分别对应
y0和yn+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 可能预测的所有标签序列集合。在训练的时候,我们一般是最大化正确标签序列对应的
log−probability l o g − p r o b a b i l i t y 值:
log(p(y|X))=s(X,y)−log⎛⎝∑y˘∈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 ˘ )
所以,我们在计算这个
log−likelihood 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=1nAyi−1,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=11Ayi−1,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=12Ayi−1,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=1nAyi−1,yi+∑i=1nPi,yi=Sn−1+Ayn−1,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 进行迭代时,只需要一直记录对应的
Si−1,A,P S i − 1 , A , P 这三项值,就能够计算出分子部分的值!
3.2.2 分母部分
分母部分的计算相对来说比较麻烦,也需要构造每一步迭代项,分母部分计算公式如下:
Z(X)=log⎛⎝∑y˘∈YXes(X,y˘)⎞⎠=log⎛⎝∑y˘∈YXexp(∑i=1nAyi−1,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=log⎛⎝∑y˘∈tagsexp(∑i=11Ayi−1,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 ) ) =
log⎛⎝∑y˘∈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=log⎛⎝∑y˘∈tagsexp(∑i=12Ay˘i−1,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 ) ) =
log⎛⎝∑y˘∈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 ) ) =
log⎛⎝∑y˘∈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 ) ) =
log⎛⎝∑y˘∈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=log⎛⎝∑y˘∈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=log⎛⎝exp(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 ) ) =
log⎛⎝∑y˘∈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=log⎛⎝∑y˘∈tagsexp(Zn−1+Ay˘n−1,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 ) )
这样我们也找到了递推项,当我们沿着句子的每个位置进行迭代时,只需要一直记录对应的
Zi−1,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).
这个方法的作用是,预选准备�