赞
踩
最近在搞信息抽取任务,用到了LSTM+CRF模型,之前没有深入了解过,就趁这次好好总结一下。把所有的代码,文章看完一遍后发现,这个LSTM+CRF和一般的CRF还是有点区别的,以及具体的代码实现还是有些细节需要注意的。本文打算对原理,数据的构造,模型的搭建进行详细叙述,不过由于不同人之间的前置知识不同,所以理解起来可能还会有些差别,如果描述的不是很清晰的话,可以在下方评论指出,模型的实现参考李航《统计学习方法第二版》中有关CRF的内容,以及代码具体实现时根据
https://github.com/SkyAndCloud/bilstm_crf_sequence_labeling_pytorch/blob/master/main.pygithub.com进行了check,保证代码准确性,代码使用了Pytorch框架。
解析分为原理篇和代码篇,此篇为原理篇。
原理解析:
首先我们要知道为什么使用LSTM+CRF,序列标注问题本质上是分类问题,因为其具有序列特征,所以LSTM就很合适进行序列标注,确实,我们可以直接利用LSTM进行序列标注。但是这样的做法有一个问题:每个时刻的输出没有考虑上一时刻的输出。我们在利用LSTM进行序列建模的时候只考虑了输入序列的信息,即单词信息,但是没有考虑标签信息,即输出标签信息。这样会导致一个问题,以“我 喜欢 跑步”为例,LSTM输出“喜欢”的标签是“动词”,而“跑步”的标签可能也是“动词”。但是实际上,“名词”标签更为合适,因为“跑步”这里是一项运动。也就是“动词”+“名词”这个规则并没有被LSTM模型捕捉到。也就是说这样使用LSTM无法对标签转移关系进行建模。而标签转移关系对序列标注任务来说是很重要的,所以就在LSTM的基础上引入一个标签转移矩阵对标签转移关系进行建模。这就和CRF很像了。我们知道,CRF有两类特征函数,一类是针对观测序列与状态的对应关系(如“我”一般是“名词”),一类是针对状态间关系(如“动词”后一般跟“名词”)。在LSTM+CRF模型中,前一类特征函数的输出由LSTM的输出替代,后一类特征函数就变成了标签转移矩阵。
如下图所示,对于一个输入序列
同样的,根据标签转移矩阵
一般来说,对于一个序列
这样我们就需要关注几个问题:
1.给定输入
2.给定训练数据
3.对于训练好的LSTM+CRF模型,给定输入
这三个问题其实也就对应CRF的三个基本问题。
首先是第一个问题
根据前面概率的定义,我们可以知道
而
最后,把所有的分数加起来即可得
然后我们需要下一步工作,计算所有可能的路径的分数指数和的对数
我们知道对于
我们知道对于
计算图解如下:
这样就需要我们维护一个
如果我们想根据
当得到最后一个时刻
这样,我们就能最终得到
然后是第二个问题,如何训练模型。
在CRF里面,模型训练方法有点麻烦,但是也还行,不过还是不如LSTM+CRF简单,因为所有的参数都是以神经网络的形式定义,我们只需要表示出损失函数,然后让Pytorch框架自动求导即可。
这里我们使用负对数似然函数作为损失函数,即
之后,我们就可以愉快地训练了。
第三个问题,当模型训练好后,如何求得最好的结果。
首先,我们要明白我们要寻找的最优路径即为得分最高的路径,下图是一个demo示例,不同颜色的箭头指向不同的节点,任意时刻,带有颜色的箭头表示的路径是指向该节点的得分最高的路径。
在最后一个时刻T=3,我们只需要找出得分最高的路径(某种颜色表示的路径)指向的节点,然后不断回溯即可找到整体的最优路径。
从上面的叙述中,我们可以发现,要想实现这种方法,我们需要保存每个节点对应的得分最高的路径及其分数。
我们扩展到第一个问题定义的情况下,即
首先,t=0时刻,我们获取各个节点对应的最大路径的得分
然后到t=1时刻我们要求各个节点对应的最大得分路径及其得分。
这时我们对
然后,不断重复上面的步骤,直到得到t=n-1时刻的
这个索引表示最优路径的最后一个节点。然后我们将
至此,上述三个问题全部解决。
后面会针对具体实现过程中的代码进行解析,指出一些需要注意的地方。代码地址为
https://github.com/visionshao/LSTM-CRFgithub.comCopyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。