BiLSTM模型中CRF层的运行原理(三)

在前面的部分中,我们学习了BiLSTM-CRF模型的结构和CRF损失函数的细节。您可以通过各种开源框架(Keras,Chainer,TensorFlow等)实现您自己的BiLSTM-CRF模型。最重要的事情之一是在这些框架上自动计算模型的反向传播,因此您不需要自己实现反向传播来训练模型(即计算梯度和更新参数)。此外,一些框架已经实现了CRF层,因此只需添加一行代码就可以非常轻松地将CRF层与您自己的模型相结合。

在本节中,我们将探讨如何预测句子的标签序列。

1. 预测句子的标签序列

第1步:BiLSTM-CRF模型的emission score和transition score
假设句子$x$包含3个字符:$x=[w_0, w_1, w_2]$。此外,假设我们已经获得了BiLSTM模型的emission score和CRF层的transition score:

$l_1$ $l_2$
$w_0$ $w_{01}$ $w_{02}$
$w_1$ $w_{11}$ $w_{12}$
$w_2$ $w_{21}$ $w_{22}$

$x_{ij}$表示$w_i$被标记为$l_j$的得分。

$l_1$ $l_2$
$l_1$ $t_{11}$ $t_{12}$
$l_2$ $t_{21}$ $t_{22}$

$t_{ij}$表示标签$i$转移到标签$j$的分数

第2步:预测
如果您熟悉Viterbi算法,这部分对您来说很容易。如果你不太了解的话,请不要担心,我将逐步解释算法。对于一个句子,我们将按从左到右的方式进行预测,即:

$w_0$
$w_0$–>$w_1$
$w_0$–>$w_1$–>$w_2$

你将看到两个变量:$obs$和$previous$。$previous$存储前面步骤的最终结果。$obs$表示来自当前单元的信息。


首先,我们来看看$w_0$,即:

$obs=[x_{01}, x_{02}]$

$previous=None$

对于第一个字符$w_0$。$w_0$的最优标签很简单。例如,如果$obs=[x_{01}=0.2, x_{02}=0.8]$,显然,$w_0$的最优标签是$l_2$,由于只有一个字符从而无标签到标签之间的transition,因此不用计算transition scores。


接着,对于$w_0$ –> $w_1$:

$obs=[x_{11, x_{12}}]$

$previous=[x_{01}, x_{02}]$

1).扩展$previous$为:

$$previous=\left(^{previous[0] \quad previous[0]}{previous[1] \quad previous[1]}\right)=\left(^{x{01} \quad x_{01}}_{x_{02} \quad x_{02}}\right)$$

2).扩展$obs$为:

$$obs=\left(^{obs[0] \quad obs[1]}{obs[0] \quad obs[1]}\right)=\left(^{x{11} \quad x_{12}}_{x_{11} \quad x_{12}}\right)$$

3).将$previous$,$obs$和transition score进行求和:

$$scores=\left(^{x_{01} \quad x_{01}}_{x_{02} \quad x_{02}}\right) + \left(^{x_{11} \quad x_{12}}_{x_{11} \quad x_{12}}\right) + \left(^{t_{11} \quad t_{12}}_{t_{21} \quad t_{22}}\right)$$

即:

$$scores=\left(^{x_{01}+x_{11}+t_{11} \quad x_{01}+x_{12}+t_{12}}_{x_{02}+x_{11}+t{21} \quad x_{02}+x_{12}+t_{22}}\right)$$

当我们计算所有可能标签序列组合的总得分时,您可能想知道与前一部分没有有区别。接下来我们将看到其中的差异性。

更新$previous$值:

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

假设,我们得到的score为:

$$scores=\left(^{x_{01}+x_{11}+t_{11} \quad x_{01}+x_{12}+t_{12}}_{x_{02}+x_{11}+t{21} \quad x_{02}+x_{12}+t_{22}}\right)=\left( ^{0.2 \quad 0.3}_{0.5 \quad 0.4}\right)$$

则$previous$将更新为:

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

$previous$是什么意思?$previous$列表存储当前字符对每个标签的最大得分。

1.1 案例

假设,在语料库中,我们总共有2个标签,$label1(l_1)$和$label2(l_2)$,这两个标签的索引分别为0和1。

$previous[0]$是以第0个标签$l_1$结束的序列的最大得分,类似的$previous[1]$是以$l_2$结束的序列的最大得分。在每次迭代过程中,我们仅仅保留每个标签对应的最优序列的信息($previous=[\max(scores[00], scores[10]),\max( scores[01], scores[11])]$)。分数较少的序列信息将被丢弃。

回到我们的主要任务:

同时,我们还有两个变量来存储历史信息(分数和索引),即$alpha_0$和$alpha_1$。
每次迭代,我们都将最好的得分追加到$alpha_0$。为方便起见,每个标签的最高分都有下划线。

$$scores=\left(^{x_{01}+x_{11}+t_{11} \quad x_{01}+x_{12}+t_{12}}{\underline{x{02}+x_{11}+t{21}} \quad \underline{x_{02}+x_{12}+t_{22}}}\right)=\left( ^{0.2 \quad 0.3}_{\underline{0.5} \quad \underline{0.4}}\right)$$

$$alpha_0=[(scores[10],scores[11])]=[(0.5,0.4)]$$

另外,相应的列的索引被保存在$alpha_1$:

$$alpha_1=[(ColumnIndex(scores[10]),ColumnIndex(scores[11]))]=[(1,1)]$$

其中,$l_1$的索引是0,$l_2$的索引是1,所以$(1, 1)=(l_2, l_2)$,这意味着对于当前的单元$w_i$和标签$l^(i)$:
$(1, 1)=(l_2, l_2)$=(当序列是$\underline{l^{(i-1)}=l_2} -> \underline{l^{(i)}=l_1}$时我们可以得到最大得分为0.5, 当序列是$\underline{l^{(i-1)}=l_2} -> \underline{l^{(i)}=l_2}$时我们可以得到最大得分为0.4)

$l^{(i-1)}$是前一个字符$w_{i-1}$对应的标签


最后,我们计算$w_0$ –> $w_1$ –> $w_2$:

$obs=[x_{21}, x_{22}]$

$previous=[0.5, 0.4]$

1).扩展$previous$为:

$$previous=\left(^{previous[0] \quad previous[0]}{previous[1] \quad previous[1]}\right)=\left(^{0.5 \quad 0.5}{0.4 \quad 0.4}\right)$$

2).扩展$obs$为:

$$obs=\left(^{obs[0] \quad obs[1]}{obs[0] \quad obs[1]}\right)=\left(^{x{21} \quad x_{22}}_{x_{21} \quad x_{22}}\right)$$

3).对$previous$,$obs$和transition score进行求和:

$$scores=\left(^{0.5 \quad 0.5}{0.4 \quad 0.4}\right) +\left(^{x{21} \quad x_{22}}_{x_{21} \quad x_{22}}\right)+ \left(^{t_{11} \quad t_{12}}_{t_{21} \quad t_{22}}\right)$$

即:

$$scores=\left(^{0.5+x_{21}+t_{11} \quad 0.5+x_{22}+t_{12}}{0.4+x{21}+t{21} \quad 0.4+x_{22}+t_{22}}\right)$$

更新$previous$为:

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

比如,我们得到的scores为:

$$scores=\left( ^{0.6 \quad \underline{0.9}}_{\underline{0.8} \quad 0.7}\right)$$

因此,$previous$将更新为:

$$previous=[0.8, 0.9]$$

实际上,$previousp[0]$和$previous[1]$之间的较大的一个是最好的预测结果的得分。与此同时,每个标签的最大得分和索引将被添加到$alpha_0$和$alpha_1$中:

$alpha_0=[(0.5,0.4),\underline{(scores[10],scores[01])}]$

$   =[(0.5,0.4),\underline{(0.8,0.9)}]$

$alpha_1=[(1,1),\underline{(1,0)}]$


第3步:找出得分最高的最佳序列
在该步骤中,我们将根据$previousp[0]$和$previous[1]$找到最高的得分。我们将从右到左的方式反推最优序列,即最后一个单元反推到第一个单元。


$w_1$ –> $w_2$:
首先,检查$alpha_0$和$alpha_1$最后一个元素:(0.8, 0.9)和(1, 0)。0.9是最高分数,其对应的位置是1,因此对应的标签是$l_2$。继续从$alpha_1$中对应位置获得$w_1$对应的标签索引, 即(1, 0)[1]=0。索引0表示$w_1$对应的标签是$l_1$。因此我们可以得到$w_1 -> w_2$的最佳序列是$l_1 -> l_2$。

$w_0$ –> $w_1$:

接着,我们继续向前移动并获得$alpha_1$的上一个元素:(1, 1)。从上面可知$w_1$的标签是$l_1$(标签对应的索引为0),因此我们可以得到$w_0$对应的标签索引为(1,1)[0]=1。所以我们可以得到$w_0 -> w_1$的最佳序列是$l_2 -> l_1$。

最终可以得到$w_0 -> w_1 -> w_2$的最佳标签序列是$l_2 -> l_1 -> l_2$

参考

[1] Lample, G., Ballesteros, M., Subramanian, S., Kawakami, K. and Dyer, C., 2016. Neural architectures for named entity recognition. arXiv preprint arXiv:1603.01360.

https://arxiv.org/abs/1603.01360