DeepLearning中CRF计算原理

主要内容来处:https://createmomo.github.io

通常在序列标注模型的最后一层layer会添加CRF计算,因为序列标注任务中lable之前有较强的约束性,例如,B-Person与I-Person之前有强关联,B-Person和I-Locations之间有强“非关联”,而CRF模型中的转移矩阵则可以很好体现这些特性。

以下面为例,对去北京进行预测得到结果如下:

B-Location I-Location O
0.1 0.1 0.8
0.8 0.1 0.1
0.1 0.4 0.5

通过会取个字对应标签的最大值做为最终标签,结果就是:O B-Location O,显然B-Location 后面应该是I-Location 才对,而模型却只从单个标签的概率值来决定,即只考虑了局部最优没考虑到全局最优。

既然问题是由于没考虑B-Location到I-Location的可能性引起的,所以把这个特征加到模型中不就能解决我们的问题了吗,就也是CRF的方式。

PS: 如果实际经验中使用LSTM+CRF模型后发现,发现学习到的转移矩阵很弱,这可能是由于学习率和初始化发射矩阵的问题;

CRF计算方法

如上面所述,加入crf层的主要目的是要对最后的输出标签进行约束,因此我们想告诉模型的时,B-Location后面大概率是I-Location,而不是O;所以在决定最终标签时不再只考虑局部标签的概率,也要考虑全局标签和标签之间的关联性。因此,引入CRF中的转移概率矩阵:

B-Location I-Location O
B-Location 0.1 0.8 0.1
I-Location 0.1 0.45 0.45
O 0.2 0.01 0.79

原来计算路径的方式是:去(O=0.8) + 北(B-Location=0.8)+ 京(O=0.5)

CRF计算路径的方式是:去(O=0.8) + 北(B-Location=0.8)+ 京(O=0.5)+ (O->B-Location=0.2) + (B-Location->O=0.1)

可以看到,原来计算方式去(O)北(B-Location)京(O)路径上的得分是最高的,而改成CRF的计算方式的话

去(O)北(B-Location)京(O)去(O)北(B-Location)京(I-Location)的路径得分更高,以此也就达到了我们想要的结果。

去(O)北(B-Location)京(O) = 0.8 + 0.8 + 0.5 + 0.2 + 0.1 = 2.4
去(O)北(B-Location)京(I-Location) = 0.8 + 0.8 + 0.4 + 0.2 + 0.8 = 3

到这里,已经了解到如何计算一条路径上的得分,那么目标是让true path上的得分在total path的占比最大,即:

\[ObjectiveFunction = \frac{P_{TruePath}}{P_{TotalPath}} \]

true path 已经知道如何计算了,但 total path的计算相对比较难办,我们当然可以通过遍历所有的路径得到total path,但时间复杂度太高,这里的技巧是使用动态规划的方式来计算。

\(p_i\) 是每i条路径,则所有路径的得分是:

\[P_{total} = P_1 + P_2 + … + P_N = e^{S_1} + e^{S_2} + … + e^{S_N} \]

那么crf的损失函数如下:

\[Loss Function = \frac{P_{RealPath}}{P_1 + P_2 + … + P_N} \]

那么:

\[LogLossFunction = \log \frac{P_{RealPath}}{P_1 + P_2 + … + P_N} \]

因此要最小化:

\[\begin{aligned} LogLossFunction &= -\log \frac{P_{RealPath}}{P_1 + P_2 + … + P_N} \\ &= - \log \frac{P_{RealPath}}{P_1 + P_2 + … + P_N} \\ &= - (\log(e^{S_{RealPath}}) - \log(e^{S_1} + e^{S_2} + … + e^{S_N})) \\ &= - (S_{RealPath} - \log(e^{S_1} + e^{S_2} + … + e^{S_N})) \\ \end{aligned} \]

即真实路径在所有路径中的概率最大。因此我们只有计算出\(P_{RealPath}\)\(P_{total}\)这两部分,就可以进行训练了。

单路径分数

单路径得分上面已经讲过如何计算了,现在重新整理一下:

\(S_i\)由两部分组成:

\[S_i = EmissionScore + TransitionScore \]

举例,计算 t0,t1,t0 这条路径的值:

\[EmissionScore=Emission_{w0,t0}+Emission_{w1,t1}+Emission_{w2,t0} \]

\[TransitionScore=Transition_{to->t1} + Transition_{t1->t0} \]

所有路径总分数

计算所有路径总分数需要先定义2个变量:
obs:obj表示当前的信息
previous:previous表示上一步各个tag经过这个tag的所有路径的得分总各。
另外用transition表示转移矩阵
\(w_0\)->\(w_1\)
当前变量值 :

\[\begin{aligned} obs = [x_{11}, x_{12}] \\ previous = [x_{01}, x_{02}] \end{aligned} \]

\[scores = previous + obj + transition \]

\[scores = \begin{pmatrix} x_{01}&x_{01}\\ x_{02}&x_{02} \end{pmatrix} + \begin{pmatrix} x_{11}&x_{12}\\ x_{11}&x_{12} \end{pmatrix} + \begin{pmatrix} t_{11}&t_{12}\\ t_{21}&t_{22} \end{pmatrix} \]

\[previous=[\log (e^{x_{01}+x_{11}+t_{11}} + e^{x_{02}+x_{11}+t_{21}}), \log (e^{x_{01}+x_{12}+t_{12}} + e^{x_{02}+x_{12}+t_{22}})] \]

注意这里的\(x_{01}\)指的是,第0个字的第1个标签的预测值。

解码

解码这里和上面比较像,最主要的区别是,这里取的是max,上面取的是sum。

\[scores = \begin{pmatrix} x_{01}+x_{11}+t_{11}&x_{01}+x_{12}+t_{12}\\ x_{02}+x_{11}+t_{21}&x_{02}+x_{12}+t_{22} \end{pmatrix} \]

\[previous=[\max (scores[00], scores[10]),\max (scores[01],scores[11])] \]

\[scores = \begin{pmatrix} x_{01}+x_{11}+t_{11}&x_{01}+x_{12}+t_{12}\\ x_{02}+x_{11}+t_{21}&x_{02}+x_{12}+t_{22} \end{pmatrix}= \begin{pmatrix} 0.2&0.3\\ 0.5&0.4 \end{pmatrix} \]

\[previous=[\max (scores[00], scores[10]),\max (scores[01],scores[11])] = [0.5, 0.4] \]

posted @ 2021-06-07 21:13  hwYang  阅读(287)  评论(0编辑  收藏  举报