NER任务的CRF-layer的原理 |
文章目录
- 一. 预备工作
- 二. BILSTM-CRF模型
- 2.1. BiLSTM层输出
- 2.2. 如果没有CRF层会怎么样
- 2.3. CRF层可以从训练数据中学到约束
- 三. CRF层
- 3.1. 发射(Emission)分数
- 3.2. 转移(Transition)分数
- 3.3. CRF损失函数
- 3.4. 实际路径得分
- 3.5. 所有可能的路径的得分
- 3.5.1. 步骤1: 回想一下CRF损失函数
- 3.5.2. 步骤2: 回忆一下Emission和Transition得分
- 3.5.3. 步骤3: 开始战斗(准备好纸笔)
- 3.6. 为新的句子推理标签
- 四. 参考文献
- 用命名实体识别任务来解释CRF:https://arxiv.org/abs/1603.01360,该文提出了一个使用词和字嵌入的 BiLSTM-CRF 命名实体识别模型。下将以本文中的模型为例来解释CRF层是如何工作的。
- 更详细的文章请参考该系列:https://createmomo.github.io/2017/09/12/CRF_Layer_on_the_Top_of_BiLSTM_1/
一. 预备工作
- 假设有一个数据集,有两个实体类型,
Person和Organization
。但是,事实上,在我们的数据集中,我们有5个实体标签:
- B-Person
- I- Person
- B-Organization
- I-Organization
- O
- 此外, x \mathbf x x 是一个包含5个单词的句子, w 0 , w 1 , w 2 , w 3 , w 4 w_0,w_1,w_2,w_3,w_4 w0,w1,w2,w3,w4。更重要的是,在句子 x \mathbf x x 中, [ w 0 , w 1 ] [w_0,w_1] [w0,w1] 是一个
Person
实体, [ w 3 ] [w_3] [w3] 是一个Organization
实体,其他都是“O”
。
二. BILSTM-CRF模型
- 如下图所示:
- 首先,将句子 x \mathbf x x 中的每个单词表示为一个向量,其中包括 单词的嵌入和字符的嵌入。字符嵌入是随机初始化的。词嵌入通常是从一个预先训练的词嵌入文件导入的。所有的嵌入将在训练过程中进行微调。
- 第二,BiLSTM-CRF模型的输入是这些嵌入,输出是句子 x \mathbf x x 中的单词的预测标签。
2.1. BiLSTM层输出
- 虽然不需要知道BiLSTM层的细节,但是为了更容易的理解CRF层,我们需要知道BiLSTM层输出的意义是什么。
- 上图说明BiLSTM层的输出是每个标签的分数。例如,对于 w 0 w_0 w0, BiLSTM节点的输出为1.5 (B-Person)、0.9 (I-Person)、0.1 (B-Organization)、0.08 (I-Organization)和0.05 (O),这些分数将作为 CRF层的输入。
- 然后,将BiLSTM层预测的所有分数输入CRF层。在CRF层中,选择预测得分最高的标签序列作为最佳答案。
2.2. 如果没有CRF层会怎么样
- 你可能已经发现,即使没有CRF层,也就是说,我们可以训练一个BiLSTM命名实体识别模型,如下图所示。
- 因为每个单词的BiLSTM的输出是标签分数。我们可以选择每个单词得分最高的标签。
- 例如,对于 w 0 w_0 w0,“B-Person”得分最高(1.5),因此我们可以选择“B-Person”作为其最佳预测标签。同样,我们可以为 w 0 w_0 w0选择“I-Person”,为 w 2 w_2 w2选择“O”,为 w 3 w_3 w3选择“B-Organization”,为 w 4 w_4 w4选择“O”。
- 虽然在这个例子中我们可以得到正确的句子 x \mathbf x x的标签,但是并不总是这样。再试一下下面图片中的例子。
- 显然,这次的输出是无效的,“I-Organization I-Person”和“B-Organization I-Person”。
2.3. CRF层可以从训练数据中学到约束
- CRF层可以向最终的预测标签添加一些约束,以确保它们是有效的。这些约束可以由CRF层在训练过程中从训练数据集自动学习。
- 约束条件可以是:
- 句子中第一个单词的标签应该以“B-”或“O”开头,而不是“I-”
- “B-label1 I-label2 I-label3 I-…”,在这个模式中,label1、label2、label3…应该是相同的命名实体标签。例如,“B-Person I-Person”是有效的,但是“B-Person I-Organization”是无效的。
- “O I-label”无效。一个命名实体的第一个标签应该以“B-”而不是“I-”开头,换句话说,有效的模式应该是“O B-label”
- 有了这些有用的约束,无效预测标签序列的数量将显著减少。
三. CRF层
- 下面了解为什么CRF层可以学习这些约束。 在CRF层的损失函数中,我们有两种类型的分数。这两个分数是CRF层的关键概念。
3.1. 发射(Emission)分数
- 第一个是emission分数。这些emission分数来自BiLSTM层。例如,如下图所示,标记为B-Person的 w 0 w_0 w0 的分数为1.5。
- 为了方便起见,我们将 给每个标签一个索引号,如下表所示。
Label | index |
---|---|
B-Person | 0 |
I-Person | 1 |
Organization | 2 |
I-Organization | 3 |
O | 4 |
- 我们用 x i y j x_{iy_j} xiyj来表示emission分数。 i i i 是word的索引, y j y_j yj 是label的索引。如上一节图中所示, x i = 1 , y j = 2 = x w 1 , B − O r g a n i z a t i o n = 0.1 x_{i=1, y_j=2}=x_{w_1, B-Organization}=0.1 xi=1,yj=2=xw1,B−Organization=0.1,即 w 1 w_1 w1作为B-Organization的得分为0.1。
3.2. 转移(Transition)分数
- 转移概率矩阵(Transition Probability Matrix):矩阵各元素都是非负的,并且各行元素之和等于 1 1 1,各元素用概率表示,在一定条件下是互相转移的,故称为转移概率矩阵。 P ( k ) P^{(k)} P(k) 表示 k k k 步转移概率矩阵。转移概率矩阵有如下特征:
- 0 ≤ P i j ≤ 1 0 \leq P_{ij} \leq 1 0≤Pij≤1,各元素值都是处于0到1之前。
- ∑ j = 1 n P i j = 1 \displaystyle\sum^{n}_{j=1}P_{ij}=1 j=1∑nPij=1,即矩阵中每一行转移概率之和等于1。
- 我们使用 t y i y j t_{y_iy_j} tyiyj 来表示transition分数。例如, t B − P e r s o n , I − P e r s o n = 0.9 t_{B-Person, I-Person}=0.9 tB−Person,I−Person=0.9 表示标签的transition, B − P e r s o n → I − P e r s o n B-Person \rightarrow I-Person B−Person→I−Person 得分为0.9。因此,我们有一个transition得分矩阵,它存储了所有标签之间的所有得分。
- 为了使transition评分矩阵更健壮,我们将添加另外两个标签,START和END。START是指一个句子的开头,而不是第一个单词。END表示句子的结尾。
- 下面是一个transition得分矩阵的例子,包括额外添加的START和END标签。
- 如上表所示,我们可以发现transition矩阵已经学习了一些有用的约束。
- 句子中第一个单词的标签应该以“B-”或“O”开头,而不是“I-”开头 (从“START”到“I- person或I- organization”的transition分数非常低)
- “B-label1 I-label2 I-label3 I-…”,在这个模式中,label1、label2、label3…应该是相同的命名实体标签。例如,“B-Person I-Person”是有效的,但是“B-Person I-Organization”是无效的。(例如,从“B-Organization”到“I-Person”的分数只有0.0003,比其他分数低很多)
- “O I-label”无效。一个被命名实体的第一个标签应该以“B-”而不是“I-”开头,换句话说,有效的模式应该是“O B-label”(同样, t O , I − P e r s o n t_{O, I-P e r s o n} tO,I−Person的分数非常小)
- 你可能想问一个关于矩阵的问题。在哪里或如何得到transition矩阵?
- 实际上,该矩阵是BiLSTM-CRF 模型的一个参数。在训练模型之前,可以随机初始化矩阵中的所有transition分数。所有的随机分数将在你的训练过程中自动更新。换句话说,CRF层可以自己学习这些约束。我们不需要手动构建矩阵。随着训练迭代次数的增加,分数会逐渐趋于合理。
3.3. CRF损失函数
- CRF损失函数由 真实路径得分 和 所有可能路径的总得分 组成。在所有可能的路径中,真实路径的得分应该是最高的。 例如,如果我们的数据集中有如下表所示的这些标签:
- 例如,如果我们的数据集中有如下表所示的这些标签:
- 我们还是有一个5个单词的句子。可能的路径是:
- ①START B-Person B-Person B-Person B-Person B-Person END
- ②START B-Person I-Person B-Person B-Person B-Person END
- …
- 10 10 10 START B-Person I-Person O B-Organization O END
- N N N …
- 假设每条可能的路径都有一个分数 P i P_i Pi,并且总共有 N N N条可能的路径,所有路径的总分数是 P total = P 1 + P 2 + … + P N = e S 1 + e S 2 + … + e S N P_{\text {total }}=P_1+P_2+\ldots+P_N=e^{S_1}+e^{S_2}+\ldots+e^{S_N} Ptotal =P1+P2+…+PN=eS1+eS2+…+eSN。(在第3.4节中,我们将解释如何计算,你也可以把它当作这条路径的分数)
- 如果我们说第10条路径是真正的路径,换句话说,第10条路径是我们的训练数据集提供的黄金标准标签。在所有可能的路径中,得分 P 10 P_{10} P10 应该是百分比最大的。
- 在训练过程中,我们的BiLSTM-CRF模型的参数值将会一次又一次的更新,以保持增加真实路径的分数百分比。
L o s s F u n c t i o n = P R e a l P a t h P 1 + P 2 + … + P N (1) LossFunction=\frac{P_{RealPath}}{P_1+P_2+\ldots+P_N} \tag{1} LossFunction=P1+P2+…+PNPRealPath(1)
- 现在的问题是:①如何定义一个路径的分数?②如何计算所有可能路径的总分?③当我们计算总分时,我们需要列出所有可能的路径吗?(这个问题的答案是否定的)
3.4. 实际路径得分
- 在3.3节中,我们假设每条可能的路径都有一个得分,并且有N条可能的路径,所有路径的总得分为 P t o t a l = P 1 + P 2 + … + P N = e S 1 + e S 2 + … + e S N P_{total}=P_1+P_2+\ldots+P_N=e^{S_1}+e^{S_2}+\ldots+e^{S_N} Ptotal=P1+P2+…+PN=eS1+eS2+…+eSN。
- 显然,在所有可能的路径中,一定有一条是真实路径。对于这个例子来说,前面中句子的实际路径是 “START B-Person I-Person O B-Organization O END”。其他的是不正确的,如“START B-Person B-Organization O I-Person I-Person B-Person”。 e S i e^{S_i} eSi是第 i i i条路径的得分。
- 在训练过程中,CRF损失函数只需要两个分数: 真实路径的分数和所有可能路径的总分数。所有可能路径的分数中,真实路径分数所占的比例会逐渐增加。
- 计算实际路径分数 e S i e^{S_i} eSi非常简单。这里我们主要关注的是 S i {S_i} Si的计算。
- 选取真实路径,“START B-Person I-Person O B-Organization O END”,我们以前用过,例如:
- ①我们有一个5个单词的句子, w 1 , w 2 , w 3 , w 4 , w 5 w_1,w_2,w_3,w_4, w_5 w1,w2,w3,w4,w5
- ②我们增加了两个额外的单词来表示一个句子的开始和结束, w 0 , w 6 w_0,w_6 w0,w6
- ③ S i {S_i} Si 由两部分组成: S i = S_i= Si= EmissionScore + + + TransitionScore
- Emission得分:
EmissionScore = x 0 , S T A R T + x 1 , B − P e r s o n + x 2 , I − P e r s o n + x 3 , O + x 4 , B − O r g a n i z a t i o n + x 5 , O + x 6 , E N D (2) \text { EmissionScore }=\\ x_{0, START}+x_{1, B-Person}+x_{2, I-Person}+x_{3, O}+x_{4, B-Organization }+x_{5, O}+x_{6, E N D}\tag{2} EmissionScore =x0,START+x1,B−Person+x2,I−Person+x3,O+x4,B−Organization+x5,O+x6,END(2)- x i n d e x , l a b e l x_{index, label} xindex,label 是第index个单词被label标记的分数
- 这些得分 x 1 , B − P e r s a n ; x 2 , I − P e r son ; x 3 , O ; x 4 , B − O r g a n i z a t i o n ; x 5 , O x_{1, B-P e r s a n};x_{2, I-P e r \operatorname{son}}; x_{3, O} ;x_{4, B-Organization}; x_{5, O} x1,B−Persan;x2,I−Person;x3,O;x4,B−Organization;x5,O 来自之前的BiLSTM输出。
- 对于 x 0 , S T A R T x_{0, START} x0,START 和 x 6 , E N D x_{6, E N D} x6,END,我们可以把它们设为0。
- Transition得分:
TransitionScore = t S T A R T − > B − P e r s o n + t B − P e r s o n − > I − P e r s o n + t I − P e r s o n − > O + t O − > B − O r g n i z a t i o n + t B − O r g n i z a t i o n − > O + t O − > E N D (3) \text { TransitionScore }= \\t_{S T A R T->B- Person}+t_{B-Person->I-Person} +t_{I-Person-> O}+\\ t_{O->B-Orgnization}+t_{B-Orgnization->O}+t_{O-> END}\tag{3} TransitionScore =tSTART−>B−Person+tB−Person−>I−Person+tI−Person−>O+tO−>B−Orgnization+tB−Orgnization−>O+tO−>END(3)
- 综上所述,现在我们可以计算出 S i {S_i} Si以及路径得分 e S i e^{S_i} eSi。
3.5. 所有可能的路径的得分
- 如何逐步计算一个toy例子一个句子的所有可能的路径的总分。
- 在上一节中,我们学习了如何计算一个路径(即)的标签路径得分。到目前为止,我们还有一个需要解决的问题,就是如何得到所有路径的总分( P t o t a l = P 1 + P 2 + … + P N = e S 1 + e S 2 + … + e S N P_{total}=P_1+P_2+\ldots+P_N=e^{S_1}+e^{S_2}+\ldots+e^{S_N} Ptotal=P1+P2+…+PN=eS1+eS2+…+eSN)。
- 衡量总分最简单的方法是:列举所有可能的路径并将它们的分数相加。是的,你可以用这种方法计算总分。然而,这是非常低效的。训练的时间将是难以忍受的。
- 在探索以下内容之前,我建议你先准备一张白纸和一支笔,并按照示例中列出的步骤进行操作。我相信这将有助于你更好地理解算法的细节。此外,你应该知道如何用你喜欢的编程语言实现它。
3.5.1. 步骤1: 回想一下CRF损失函数
- 在3.3中,我们将CRF损失函数定义为:
L o s s F u n c t i o n = P R e a l P a t h P 1 + P 2 + … + P N LossFunction=\frac{P_{RealPath}}{P_1+P_2+\ldots+P_N} LossFunction=P1+P2+…+PNPRealPath- 现在我们 把loss函数变成log loss函数:
L o g L o s s F u n c t i o n = log P R e a l P a t h P 1 + P 2 + … + P N (4) LogLossFunction=\log\frac{P_{RealPath}}{P_1+P_2+\ldots+P_N}\tag{4} LogLossFunction=logP1+P2+…+PNPRealPath(4)- 因为当我们训练一个模型时,通常我们的目标是 最小化 我们的损失函数,我们加上一个负号:
L o g L o s s F u n c t i o n = − log P R e a l P a t h P 1 + P 2 + … + P N = − log e S R e a l P a t h e S 1 + e S 2 + … + e S N 这里根据前面的定义 = − [ log ( e S R e a l P a t h ) − log ( e S 1 + e S 2 + … + e S N ) ] = − [ S R e a l P a t h − log ( e S 1 + e S 2 + … + e S N ) ] = − [ ∑ i = 1 N x i y i + ∑ i = 1 N − 1 t y i y i + 1 − log ( e S 1 + e S 2 + … + e S N ) ] 前面两项就是真实 (5) \begin{aligned}LogLossFunction & =-\log \frac{P_{RealPath}}{P_1+P_2+\ldots+P_N} \\ & =-\log \frac{e^{S_{RealPath}}}{e^{S_1}+e^{S_2}+\ldots+e^{S_N}} \text{这里根据前面的定义}\\ & =-\left[\log \left(e^{S_{RealPath}}\right)-\log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right)\right] \\ & =-\left[S_{RealPath}-\log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right)\right] \\ & =-\left[\sum_{i=1}^N x_{i y i}+\sum_{i=1}^{N-1} t_{y_i y_{i+1}}-\log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right)\right] \text{前面两项就是真实} \end{aligned}\tag{5} LogLossFunction=−logP1+P2+…+PNPRealPath=−logeS1+eS2+…+eSNeSRealPath这里根据前面的定义=−[log(eSRealPath)−log(eS1+eS2+…+eSN)]=−[SRealPath−log(eS1+eS2+…+eSN)]=−[i=1∑Nxiyi+i=1∑N−1tyiyi+1−log(eS1+eS2+…+eSN)]前面两项就是真实(5)- 在上一节中,我们已经知道如何计算实际路径得分,现在我们需要找到一个有效的解决方案来计算 log ( e S 1 + e S 2 + … + e S N ) \log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right) log(eS1+eS2+…+eSN)
3.5.2. 步骤2: 回忆一下Emission和Transition得分
- 为了简化,我们假设我们从这个句子中训练我们的模型,它的 长度只有3:
x = [ w 0 , w 1 , w 2 ] \mathbf x=[w_0, w_1, w_2] x=[w0,w1,w2]- 此外,在我们的数据集中,我们有 两个标签:
L a b e l S e t = { l 1 , l 2 } LabelSet=\{l_1, l_2\} LabelSet={l1,l2}- 我们还有Bi-LSTM层 输出的Emission分数: x i j x_{ij} xij表示 w i w_i wi 被标记为 l j l_j lj 的得分。参考3.1
l 1 l_1 l1 | l 2 l_2 l2 | |
---|---|---|
w 0 w_0 w0 | x 01 x_{01} x01 | x 02 x_{02} x02 |
w 1 w_1 w1 | x 11 x_{11} x11 | x 12 x_{12} x12 |
w 2 w_2 w2 | x 21 x_{21} x21 | x 22 x_{22} x22 |
- 此外,Transition分数来自CRF层: t i j t_{ij} tij表示标签 i i i 到标签 j j j 的Transition得分。参考3.2
l 1 l_1 l1 | l 2 l_2 l2 | |
---|---|---|
l 1 l_1 l1 | t 11 t_{11} t11 | t 12 t_{12} t12 |
l 2 l_2 l2 | t 21 t_{21} t21 | t 22 t_{22} t22 |
3.5.3. 步骤3: 开始战斗(准备好纸笔)
- 记住:我们的目标是: log ( e S 1 + e S 2 + … + e S N ) \log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right) log(eS1+eS2+…+eSN)
- 这个过程就是分数的累加。其思想与动态规划相似(如果你不知道什么是动态编程,也可以继续阅读本文)。我将逐步解释这个例子。但我强烈建议你学习动态规划算法。
- 简而言之,计算 w 0 w_0 w0 的所有可能路径的总分。然后,我们用总分来计算 w 0 → w 1 w_0→w_1 w0→w1。最后,我们使用最新的总分来计算 w 0 → w 1 → w 2 w_0→w_1→w_2 w0→w1→w2。我们需要的是最后的总分。
- 在接下来的步骤中,你将看到两个变量:obs和previous。previous存储前面步骤的最终结果。obs表示当前单词的信息。
- 实际上,第二次迭代已经完成。如果有人想知道如何计算所有可能路径的总分 (label1→label1, label1→label2, label2→label1, label2→label2),从 w 0 到 w 1 w_0到w_1 w0到w1,可以做如下计算。
- 我们使用新的previous中的元素: TotalScore ( w 0 → w 1 ) = log ( e previous [ 0 ] + e previous [ 1 ] ) = log ( e log ( e x 01 + x 11 + t 11 + e x 02 + x 11 + t 21 ) + e log ( e x 01 + x 12 + t 12 + e x 02 + x 12 + t 22 ) ) = log ( e x 01 + x 11 + t 11 + e x 02 + x 11 + t 21 + e x 01 + x 12 + t 12 + e x 02 + x 12 + t 22 ) \begin{aligned} & \operatorname{TotalScore}\left(w_0 \rightarrow w_1\right) \\ & =\log \left(e^{\text {previous }[0]}+e^{\text {previous }[1]}\right) \\ & =\log \left(e^{\log \left(e^{x_{01}+x_{11}+t_{11}}+e^{x_{02}+x_{11}+t_{21}}\right)}+e^{\log \left(e^{x 01+x 12+t 12}+e^{x 02+x 12+t_{22}}\right)}\right) \\ & =\log \left(e^{x_{01}+x_{11}+t_{11}}+e^{x_{02}+x_{11}+t_{21}}+e^{x_{01}+x_{12}+t_{12}}+e^{x_{02}+x_{12}+t_{22}}\right) &\end{aligned} TotalScore(w0→w1)=log(eprevious [0]+eprevious [1])=log(elog(ex01+x11+t11+ex02+x11+t21)+elog(ex01+x12+t12+ex02+x12+t22))=log(ex01+x11+t11+ex02+x11+t21+ex01+x12+t12+ex02+x12+t22)
- 你发现了吗?这正是我们的目标: log ( e S 1 + e S 2 + … + e S N ) \log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right) log(eS1+eS2+…+eSN)
- 在这个等式中,我们可以看到:
S 1 = x 01 + x 11 + t 11 ( label 1 → label 1 ) S 2 = x 02 + x 11 + t 21 ( label 2 → label 1 ) S 3 = x 01 + x 12 + t 12 ( label 1 → label 2 ) S 4 = x 02 + x 12 + t 22 ( label 2 → label 2 ) \begin{aligned} & S_1=x_{01}+x_{11}+t_{11}\left(\text {label}_1 \rightarrow \text {label}_1\right) \\ & S_2=x_{02}+x_{11}+t_{21}\left(\text {label}_2 \rightarrow \text {label}_1\right) \\ & S_3=x_{01}+x_{12}+t_{12}\left(\text {label}_1 \rightarrow \text {label}_2\right) \\ & S_4=x_{02}+x_{12}+t_{22}\left(\text {label}_2 \rightarrow \text {label}_2\right) \end{aligned} S1=x01+x11+t11(label1→label1)S2=x02+x11+t21(label2→label1)S3=x01+x12+t12(label1→label2)S4=x02+x12+t22(label2→label2)
- 恭喜!
- 我们达到了目标, log ( e S 1 + e S 2 + … + e S N ) \log \left(e^{S_1}+e^{S_2}+\ldots+e^{S_N}\right) log(eS1+eS2+…+eSN),我们的toy句子有三个单词,label set有两个label,所以一共应该有8种可能的label path。 虽然你发现这个过程相当复杂,但是实现这个算法要容易得多。使用计算机的优点之一是可以完成一些重复性的工作。现在你可以自己实现CRF损失函数,并开始训练自己的模型。
- 详细可以参考该链接:BiLSTM上的CRF,用命名实体识别任务来解释CRF(2)损失函数
3.6. 为新的句子推理标签
- 在前面的章节中,我们学习了BiLSTM-CRF模型的结构和CRF损失函数的细节。你可以通过各种开源框架(Keras、Chainer、TensorFlow等)实现自己的BiLSTM-CRF模型。最重要的事情之一是模型的反向传播是在这些框架上自动计算的,因此你不需要自己实现反向传播来训练你的模型(即计算梯度和更新参数)。此外,一些框架已经实现了CRF层,因此将CRF层与你自己的模型结合起来非常容易,只需添加一行代码即可。
- 这部分直接参考文章:BiLSTM上的CRF,用命名实体识别任务来解释CRF(3)推理
四. 参考文献
- https://createmomo.github.io/2017/09/12/CRF_Layer_on_the_Top_of_BiLSTM_1/
- https://createmomo.github.io/2017/10/08/CRF-Layer-on-the-Top-of-BiLSTM-3/
- 详细可以参考该链接:BiLSTM上的CRF,用命名实体识别任务来解释CRF(2)损失函数
- https://github.com/createmomo/CRF-Layer-on-the-Top-of-BiLSTM