作者:CreateMoMo 编译:ronghuaiyang

导读 今天是第三部分,介绍如何推理新的句子。

前两篇链接: https://www.6aiq.com/article/1585116912485 https://www.6aiq.com/article/1585415235824

2.6 为新的句子推理标签

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

在本节中,我们将探索如何在模型准备好时在测试期间推断句子的标签。

步骤 1:BiLSTM-CRF 模型的 Emission 和 transition 得分

假设,我们有一个包含三个单词的句子:x=[w0,w1,w2]x = [w_0,w_1,w_2]

此外,我们已经从 BiLSTM 模型得到了 Emission 分数,从下面的 CRF 层得到了 transition 分数:

xijx_{ij}表示wiw_i被标记为ljl_j的得分。

tijt_{ij}是从标签 i 转换成标签 j 的得分。

步骤 2:开始推理


如果你熟悉 Viterbi 算法,那么这一部分对你来说很容易。但如果你不熟悉,请不要担心。与前一节类似,我将逐步解释该算法。我们将从句子的左到右进行推理算法,如下图所示:

  • w0w_0
  • w0>w1w_0 -> w_1
  • w0>w1>w2w_0 -> w_1 -> w_2

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

alpha0alpha_0是历史最好得分,alpha1alpha_1是历史对应的索引。这两个变量的细节将在它们出现时进行解释。请看下面的图片:你可以把这两个变量当作狗在探索森林时沿路留下的“记号”,这些“记号”可以帮助狗找到回家的路。

狗需要找到最好的路径来得到他最喜欢的骨头玩具,然后沿着他来的路回家


w0w_0:

obs=[x01,x02]previous=Noneobs=[x_{01}, x_{02}] previous=None

现在,我们观察到第一个单词,现在,对于是很明显的。

比如,如果obs=[x01=0.2,x02=0.8]obs=[x_{01}=0.2, x_{02}=0.8],很显然,w0w_0的最佳标签是l2l_2. 因为只有一个单词,而且没有标签直接的转换,transition 的得分没有用到。


w0>w1w_0 -> w_1:

obs=[x11,x12]previous=[x01,x02]obs=[x_{11}, x_{12}] previous=[x_{01}, x_{02}]

  1. previous 扩展成:

  1. obs 扩展成:

  1. previous, obstransition 分数都加起来:

然后:

你可能想知道,当我们计算所有路径的总分时,与上一节没有什么不同。请耐心和细心,你很快就会看到区别。

为下一次迭代更改 previous 的值:

比如,如果我们的得分是:

我们的下个迭代的 previous 是:

previous 有什么含义吗? previous 列表存储了每个当前的单词的标签的最大的得分。

[Example Start]

举个例子:

我们知道在我们的语料中,我们总共只有 2 个标签label1(l1)label1(l_1)label2(l2)label2(l_2)。这两个标签的索引是 0 和 1。previous[0]是以第 0 个标签l1l_1为结尾的路径的最大得分,类似的 previous[1]是以第 1 个标签l2l_2为结尾的路径的最大得分。在每个迭代中,变量 previous 存储了以每个标签为结尾的路径的最大得分。换句话说,在每个迭代中,我们只保留了每个标签的最佳路径的信息 (previous=max(scores[00],scores[10]),max(scores[01],scores[11])previous = max(scores[00], scores[10]), max(scores[01], scores[11]))。具有小得分的路径信息会被丢掉。

[Example End]

回到我们的主任务:

同时,我们还有两个变量用来存储历史信息(得分和索引),alpha0alpha_0alpha1alpha_1。 在这个迭代中,我们把最佳得分加上alpha0alpha_0,为了方便,每个标签的最大得分会加上下划线。

另外,对应的列的索引存在alpha1alpha_1里。

说明一下,l1l_1的索引是 0, l2l_2的索引是 1,所以(1,1)=(l2,L2)(1, 1) = (l_2,L_2)表示对于当前的单词wiw_i和标签l(i)l^{(i)},当路径是l(i1)=l2>li=l1l^{(i-1)} = l_2 -> l^i = l_1的时候,我们可以得到最大的得分是 0.5,当路径是l(i1)=l2>li=l2l^{(i-1)} = l_2 -> l^i = l_2的时候,我们可以得到最大的得分是 0.4。li1l^{i-1}是过去的单词wi1w_{i-1}的标签。


w0>w1>w2w_0 -> w_1 -> w_2:

obs=[x21,x22]previous=[0.5,0.4]obs=[x_{21}, x_{22}] previous=[0.5,0.4]

  1. previous 扩展成:

  1. obs 扩展成:

  1. previous, obstransition 分数都加起来:

然后:

为下一次迭代更改 previous 的值:

这次迭代我们得到的分数是:

我们得到最新的 previous

实际上,previous[0]和 previous[1]中最大的那个就是预测的最佳路径。

同时,每个标签和索引的最大得分会加到alpha0alpha_0alpha1alpha_1上。

步骤 3:找到具有最高得分的最佳路径

这是最后一步!你就快完成了!在此步骤中,将使用alpha0alpha_0alpha1alpha_1来查找得分最高的路径。我们将从最后一个到第一个的元素检查这两个列表中。


w1>w2w_1 -> w_2:

首先,检查alpha0alpha_0alpha1alpha_1的最后一个元素:(0.8,0.9)和(1,0)。0.9 表示当 label 为l2l_2时,我们可以得到最高的路径分数 0.9。我们还知道l2l_2的索引是 1,因此检查(1,0)[1]=0 的值。索引“0”表示前一个标签为l1l_1(l1的索引为0l_1的索引为0),因此我们可以得到是w1>w2w_1 -> w_2的最佳路径是l1>l2l_1 -> l_2

w0>w1w_0 -> w_1:

其次,我们继续向后移动并得到alpha1alpha_1:(1,1)的元素。从上一段我们知道 w1 的 label 是l1l_1(index 是 0),因此我们可以检查(1,1)[0]=1。因此,我们可以得到这部分的最佳路径w0>w1l2>l1w_0 -> w_1,l_2 -> l_1 恭喜!我们这个例子中的最佳路径是l2>l1>l2l_2 -> l_1 -> l_2

英文原文:https://createmomo.github.io/2017/11/24/CRF-Layer-on-the-Top-of-BiLSTM-6/