BiLSTM + CRF 核心概念理解

对于命名实体识别任务,基于神经网络的方法应用非常常见。其中的 CRF 层对于刚刚接触学习的同学可能不是特别容易理解,下联链接的文章的作者对 CRF 做了非常好的讲解。我认真学习了作者的相关文章,把自己的理解总结下来,想看原文的同学,下面给出了链接,共有 8 篇相关的博文:

https://createmomo.github.io/2017/09/12/CRF_Layer_on_the_Top_of_BiLSTM_1/
https://createmomo.github.io/2017/09/23/CRF_Layer_on_the_Top_of_BiLSTM_2/
https://createmomo.github.io/2017/10/08/CRF-Layer-on-the-Top-of-BiLSTM-3/
https://createmomo.github.io/2017/10/17/CRF-Layer-on-the-Top-of-BiLSTM-4/
https://createmomo.github.io/2017/11/11/CRF-Layer-on-the-Top-of-BiLSTM-5/
https://createmomo.github.io/2017/11/24/CRF-Layer-on-the-Top-of-BiLSTM-6/
https://createmomo.github.io/2017/12/06/CRF-Layer-on-the-Top-of-BiLSTM-7/
https://createmomo.github.io/2017/12/07/CRF-Layer-on-the-Top-of-BiLSTM-8/

要理解 CRF 层是如何工作的,我们需要先理解:

  1. BiLSTM + CRF 输出内容
  2. BiLSTM + CRF 序列分数
  3. BiLSTM + CRF 损失函数
  4. BiLSTM + CRF 公式推导
  5. BiLSTM + CRF 预测输出

1. BiLSTM + CRF 输出内容

BiLSTM + CRF 的网络模型架构如下图所示:

我们经常使用 BiLSTM + CRF 模型来做 NER 任务,模型共有两个非常重要的网络层:BiLSTM 层、CRF 层,其中 BiLSTM 的作用就是接收输入,并提取每个输入字词的上下文语义(因为是双向),CRF 层主要就是用来给输出提供约束,使得预测的结果更符合真实情况。

如果没有 CRF 层模型预测的实体标签,很多可能都不符合实际的规则。比如:第一个字的预测标签不可能是 I-Organnization。为了避免这种情况,模型除了学习要预测出标签,还得学习标签的输出规则,约束。CRF 层里的参数,就是模型的约束规则。

所以,BiLSTM + CRF 的模型架构看起来是需要学习两套参数,BiLSTM 里的参数,以及 CRF 的约束参数。这些参数根据什么来学习呢?当然是根据我们的训练数据了。

2. BiLSTM + CRF 序列分数

计算一个序列的预测分数,我们需要用到 BiLSTM 的输出,如下图所示:

BiLSTM 的输出理解为一个矩阵,横轴是输入的字、纵轴是每个字预测为各个标签的分数。这个矩阵也叫做 emission score,也可以叫做发射分数。

CRF 层是啥呢? 就是一系列约束,例如:前一个 B-Person 标签的话,后面一个不能再来个 B-Person,再或者第一字的标签不能是 I-Person 之类的,这些约束怎么去表示呢?用一个矩阵表示就行,假设,咱们使用 BIO 标签体系,那么共有 7 种标签,因为我们一般识别实体主要是:人名、组织名、机构名、其他,我们用到的标签有:

  1. 人名:B-PER、I-PER
  2. 组织:B-ORG、I-ORG
  3. 地名:B-LOC、I-LOC
  4. 其他:O

接下来使用 7 标签构建一个带有初始状态分数的转移矩阵,如下图所示:

张图中,START、END 其实是为了表示初始状态概率,比如:START->B-PER 就表示第一个标签是 B-PER 的概率。上图中,其实我没有填写任何值,在初始时,里面的值可以是随机的,因为随着训练的进行,里面的值会进行调整。并且,该矩阵中的值都是要学习的参数。这个矩阵也叫做转移矩阵,里面存储的值也叫做 transition score。

注意: BiLSTM 的参数和上面的矩阵就是模型要学习的内容。

当我们向模型输入一句话,那么可能产生的预测序列就会有很多种,例如:输入的是 3 个字,则可能序列有:

  1. B-PER -> I-PER -> O
  2. B-PER -> O -> I-PER
  3. I-PER -> B-PER -> O
  4. 等等

模型最终的预测结果应该分数最高的那个序列。那么该序列的分数就可以用该序列的 emission score + transition score 计算获得。比如:上面可能的预测序列中,第一个序列是最终的预测序列,我们就可以从发射矩阵中找到每一个字的对应的 B-PER、I-PER、O 的分数加起来,再加上转移矩阵中的,START->B-PER、B-PER->I-PER、I-PER->O 的分数,最后再计算 \(e^{totalscore}\) 就得到了该预测序列最终的分数。

3. BiLSTM + CRF 损失函数

当我们在知道了要学习的目标,接下来就需要针对我们的目标来设计损失函数,由损失函数引导模型向我们预想的目标方向去学习。我们现在的目标是:

  1. 希望 BiLSTM 层能够更加准确的预测标签
  2. 希望 CRF 层能够约束、校正 BiLSTM 预测的标签

损失函数为:

该损失函数非常容易理解,\(P_{real_path}\) 指的就是训练样本中的正确的标签序列的分数,分母为模型可能预测出的所有序列的分数总和,咱们的目标是模型学习完之后,能够把正确序列的分数预测的越高越好。

这里需要注意的是:P 表示一个序列的分数,这个分数是由发射分数和转移分数计算得来的。所以,当反向传播优化参数时,必然会去调整 BiLSTM 里的参数和 CRF 的参数,这样使得网络参数在损失函数的指导下得以学习。

分子就一个序列计算起来没啥压力,但是分母是所有可能序列分数的总和,如果序列长一些,大家可以脑补下,待计算的序列数量就会有很多,计算效率就会很低,进而训练就会变得很慢。所以,作者提出了一些方法来加快计算,我简单总结了下大致有两个小点:

  1. 尽量在计算中使用矩阵运算的方式,咱们知道矩阵运算的效率,肯定比一个一个的计算效率高。
  2. 使用了动态规划的思想。

4. BiLSTM + CRF 公式推导

所谓的公式推导其实就是看看作者如何将分母的计算转换为矩阵运算+动态规划的思想。我们先将损失函数转换为对数损失函数函数,公式如下:

原来的损失函数我们希望值越大越好,改成 log 损失之后,我们在前面加了一个符号,此时就变成了一个极小值的问题,即:当模型参数是什么的时候,能够使得该损失函数最小。该公式继续展开:

上述公式中,第二项就一个真实的序列,一个序列好计算。关键是第一项,如何高效的计算。作者给出一个简单的例子,假设输入有 3 个字 \(w_0 w_1 w_2\),标签 2 个 \(L_1 L_2\),BiLSTM 的发射矩阵和 CRF 的转移矩阵如下:

我们现在要计算的目标是 \(log(P_1+P_2…+P_n)\),先引入两个辅助的变量 obs、pre,其中 obs 表示当前要计算的词的发射分数,pre 是上一个词的计算分数。

第一步 \(w_0\):pre = None, obs = [ \(x_{01},x_{02}\)]

第二步 \(w_0 -> w_1\):pre = [ \(x_{01},x_{02}\) ],obs =[ \(x_{11},x_{12}\) ],从第二步我们要对 pre 和 obs 进行维度扩展了,为的就是使用矩阵运算。pre、obs 扩展之后如下图所示:

pre 是先转置下,然后横向广播一个维度,obs 是直接纵向广播一个维度。分数计算如下:

score 矩阵中的 4 个值,就是 \(w_0 -> w_1\) 的 4 个不同的序列。其 LogLoss 值为:

第三步\(w_0 -> w_1 -> w_2\):

pre = [ \( 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}}) \) ]

obs = [ \(x_{21},x_{22}\)]

还是按照第二步的方法,把 pre、obs 广播维度,然后计算分数。下面的图直接从原文拷贝了,就不自己写了,扩展之后的 pre 和 obs 为:

然后还按照 obs + pre + transmition 的方法计算分数:

对应的对数损失为:

到此,我们就推导计算完毕了,再次感谢原作者非常好的例子。我们总结下计算 BiLSTM + CRF 的损失函数计算过程:

计算分母:

  1. 第一个字不涉及到转移分数的计算,所以直接计算 log 损失值
  2. 第二个字开始:
    1. 先把 pre 转置横向广播一个维度
    2. 再把 obs 纵向广播一个维度
    3. prev + obs + transition 计算每条路径的分数
    4. 再计算 \(log(e^{p1} + e^{p2} … e^{pn})\)
    5. 重复上面过程,直到所有的字都计算完毕

计算分子:直接统计路径的发射分数和转移分数,并计算 log 损失即可。

5. BiLSTM + CRF 预测输出

当 BiLSTM + CRF 去预测最优的的输出序列时,我们使用维特比算法。

未经允许不得转载:一亩三分地 » BiLSTM + CRF 核心概念理解