• [转] LSTM+ CRF中的损失函数


    from https://blog.csdn.net/u013963380/article/details/108696552

    本文翻译,原文地址:

    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/

    三、CRF损失函数

    CRF损失函数由两部分组成,真实路径的分数 和 所有路径的总分数。真实路径的分数应该是所有路径中分数最高的。

    例如,我们的数据集中有如下几种类别:

    Label Index
    B-Person 0
    I-Person 1
    B-Organization 2
    I-Organization 3
    O 4
    START 5
    END 6

    一个包含5个单词的句子,可能的类别序列如下:

    • 1) START B-Person B-Person B-Person B-Person B-Person END
    • 2) START B-Person I-Person B-Person B-Person B-Person END
    • 10) START B-Person I-Person O B-Organization O END
    • N) O O O O O O O

    假设每种可能的路径的分数为P_{i},共有N条路径,则路径的总分是:

    P_{total}=P_{1}+P_{2}+...+P_{N}=e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}e是一个数学常量。(下节会详细介绍如何计算S_{i},这里你可以把它当作这条路径的分数)。

    如果第十条路径是真实路径,也就是说第十条是正确预测结果,那么P_{10}应该是所有可能路径里分数最高的。根据如下损失函数,在训练过程中,BiLSTM-CRF模型的参数值将随着训练过程的迭代不断更新,使得真实路径所占的比值越来越大。

    LossFunction=frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}}

    那么现在的问题就是:

    • 如何定义路径的分数
    • 怎么计算所有路径的分数
    • 当计算所有的路径分时,是否需要穷举多有可能的路径?(答案是不需要)

    四、真实路径分数

    很明显,在所有的可能的路径中有一条是真实的路径。比如在上述的类别序列中,“START B-Person I-Person O B-Organization O END”是一条真实的路径。不正确的路径如“START B-Person B-Organization O I-Person I-Person B-Person”。e^{S_{1}}是第i条路径的分数。

    在训练阶段,crf的损失函数只需要两种类别的分数,真实路径的分数 和 所有路径的总分数。在所有的可能路径的分数中,真实路径的分数应该是最高的。

    当然计算e^{S_{1}}是十分简单的,下面让我们聚焦如何来计算S_{i}

    我们假设“START B-Person I-Person O B-Organization O END”是一条真实的路径:

    • 一个句子中有5个单词,分别是w_{1},w_{2},w_{3},w_{4},w_{5}
    • 添加开始和结尾单词,分别是w_{0},w_{6}
    • S_{i}包含两个部分,S_{i}=EmissionScore+TransitionScore

    tips:Emission Score 和 Transition Score在《BiLSTM中的CRF层(二)CRF层》一文中已经介绍。

    (1)Emission Score(发射分数):

    EmissionScore=x_{0,START}+x_{1,B-Person}+x_{2,I-Person}+x_{3,O}+x_{4,B-Organization}+x_{5,O}+x_{6,END}

    • x_{index,label}是第index索引的单词被标注为label的分数
    • x_{1,B-Person},x_{2,I-Person},x_{3,O},x_{4,B-Organization},x_{5,O}这些分数来自前一层BiLstm的输出
    • x_{0,START},x_{6,END}可以设置为0

    (2)Transition Score(转移分数):

    TransitionScore=t_{START->B-Person}+t_{B-Person->I-Person}+t_{I-Person->O}+t_{O->B-Organization}+t_{B-Organization->O}+t_{O->END}

    • t_{label1->label2}是从label1转移到label2的分数
    • 这些分数来自于CRF层。换句话说,这些分数其实是CRF层的参数

    五、所有路径的分数

    上面提到所有路径的分数P_{total}=P_{1}+P_{2}+...+P_{N}=e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}。计算所有路径的总分最简单的方式是:穷举所有可能的路径,分别计算路径分,最后求和。但是这种方式是十分低效的,而且训练时间也是不可忍受的。

    下面以一个简单的例子来说明如何高效的计算所有路径的分数。

    Step1: recall the CRF loss function

    CRF损失函数的定义是LossFunction=frac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}},我们把它变成log损失函数如下:

    LogLossFunction=logfrac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}},由于我们训练的目标通常是最小化损失函数,所以我们加上负号:

    LogLossFunction=logfrac{P_{RealPath}}{P_{1}+P_{2}+...+P_{N}}\=-logfrac{e^{S_{RealPath}}}{e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}}\=-(loge^{S_{RealPath}}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))\ =-(S_{RealPath}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))\ =-(sum_{i=1}^{N}x_{iyi}+sum_{i=1}^{N-1}t_{yiyi+1}-log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}}))

    (原文中在求真实路径的分数的时候,求和用的是N和N-1,但是从上面的求解发射分数和转移分数公式看,这里的N应该是句子的长度words,N-1应该是标签数num_tag,所有的路径总数N应该是N=(num_tag)^(words),否则对应不上。不知道是不是作者为了简化统一用N表示,还是本人理解错误。。。囧囧囧)

    在上面,我们已经知道如何计算真实路径的分数,下面我们只需要找到一种高效的方式来计算log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

    Step2:recall the Emission and Transition Score

    为了简化说明,这里我们假设我们训练模型的句子只有3的长度,标签只有2种:

    x=[w_{0},w_{1},w_{2}]

    labelset=[l_{1}, l_{2}]

    我们从Bi-Lstm层获得的发射分数如下:

      l_{1} l_{2}
    w_{0} x_{01} x_{02}
    w_{1} x_{11} x_{12}
    w_{2} x_{21} x_{22}

    tips:x_{ij}表示单词w_{i}被标签为l_{j}的分数。

    从CRF层获得的转移分数如下:

      l_{1} l_{2}
    l_{1} t_{11} t_{12}
    l_{2} t_{21} t_{22}

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

    Step3:START FIGHTING! 

    首先要记得我们的目标是log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

    整个过程其实是分数累加的过程。它的思想和动态规划如出一辙。总而言之就是,首先单词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},前一个步骤没有任何的结果,因此previous=None。另外,我们只能获取到obs=[x_{01},x_{02}]x_{01}x_{02}是上面提到的从BiLSTM层获得的发射分数。

    因此,这里单词w_{0}的所有路径分数为:

    TotalScore(w_{0})=log(e^{x_{01}}+e^{x_{02}})

    =======================================================================================================

    w_{0}->w_{1}

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

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

    (1) 将previous扩展为:

    previous=egin{pmatrix} x_{01} & x_{01} \ x_{02} & x_{02} end{pmatrix}

    (2) 将obs扩展为:

    obs=egin{pmatrix} x_{11} & x_{12} \ x_{11} & x_{12} end{pmatrix}

    将previos和obs扩展是为了计算总分更加高效。下面将会看到

    (3) 对previou、obs和转移分数求和:

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

    score=egin{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}

    然后改变previos的值

    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}})]

    到这里,第二次迭代实际上已经完成了。然后,我们使用新的previous值来计算w_{0}->w_{1}的所有路径总分:

    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^{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}})

    从上面公式可以看出,这就是我们的求解目标log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})

    在上述公式中:

    • S_{1}=x_{01}+x_{11}+t_{11} (label1->label1)
    • S_{2}=x_{02}+x_{11}+t_{21} (label2->label1)
    • S_{3}=x_{01}+x_{12}+t_{12} (label1->label2)
    • S_{4}=x_{02}+x_{12}+t_{22} (label2->label2)

    =======================================================================================================

    下面的手码太累了,直接贴原文的截图,截图出自(https://createmomo.github.io/2017/11/11/CRF-Layer-on-the-Top-of-BiLSTM-5/),原理是一样的。

    =======================================================================================================

    上述过程建议用手推一遍,对理解这个过程十分有用。。。

    至此,我们完成了log(e^{S_{1}}+e^{S_{2}}+...+e^{S_{N}})的求解过程。

    六、如何利用CRF来推理

    前面几节介绍了Bi-Lstm-CRF的模型结构以及CRF损失函数。我们可以使用开源的深度学习框架(Keras、tensorflow等)来实现一个Bi-Lstm-CRF模型。而且用这些框架最好的是不用自己来实现反向传播这个过程,更有的框架已经实现了CRF层,只需要添加一行代码就可以完全实现Bi-Lstm-CRF模型。

    推理的过程和上述求解所有路径总分的过程有点相似,每次获取得分最高的路径,最终选择所有路径中得分最高的路径为最佳路径。

    详细过程见原文:https://createmomo.github.io/2017/11/24/CRF-Layer-on-the-Top-of-BiLSTM-6/

    这里不再讲述,因为整个过程十分简单,理解了第五节中的求解过程即可。

    /* 人应该感到渺小,在宇宙面前,在美面前,在智慧面前; 而在人群中,应该意识到自己的尊严。*/
  • 相关阅读:
    js/jsp常用记录(一)
    Oracle 存储过程的基本语法 及注意事项
    PL/SQL Developer使用技巧、快捷键
    Zookeeper的功能以及工作原理
    牛客网PAT练兵场-德才论
    牛客网PAT练习场-数素数
    牛客网PAT练兵场-D进制的A+B
    牛客网PAT练习场-个位数的统计
    牛客网PAT练习场-数字分类
    牛客网PAT练习场-A+B和C
  • 原文地址:https://www.cnblogs.com/Arborday/p/15131455.html
Copyright © 2020-2023  润新知