BiLSTM上的CRF,用命名实体识别任务来解释CRF(4)

2020 年 3 月 30 日 AINLP


者:CreateMoMo

编译:ronghuaiyang

导读

今天给大家介绍一下具体的代码实现。


3 Chainer实现

在本节中,我将解释代码的结构。此外,还将给出实现CRF损失层的一个重要技巧。最后,会公布Chainer(2.0版)实现的源代码。

3.1 总体结构

可以看到,代码主要包括三个部分:初始化、损失计算和句子的预测标签。(完整的代码将在下一篇文章中发布)

class My_CRF():
def __init__():
#[Initialization]
'''
Randomly initialize transition scores
'''

def __call__(training_data_set):
#[Loss Function]
Total Cost = 0.0

#Compute CRF Loss
'''
for sentence in training_data_set:
1) The real path score of current sentence according the true labels
2) The log total score of all the possbile paths of current sentence
3) Compute the cost on this sentence using the results from 1) and 2)
4) Total Cost += Cost of this sentence
'''

return Total Cost

def argmax(new sentences):
#[Prediction]
'''
Predict labels for new sentences
'''

3.2 增加两个额外的标签(START和END)

如2.2节所述,在transition评分矩阵中,我们添加了两个START和END标签。当我们计算某句话的损失时,这将影响transition得分矩阵的初始化和emission得分矩阵的值。

[Example]

假设在我们的数据集中,我们只有一种类型的命名实体PERSON,因此我们实际上有三个标签(不包括开始和结束):B-PERSON、I-PERSON和O。

Transition得分举证

在添加了两个额外的标签(START和END)之后,当我们在init函数中初始化transition分数时,我们这样做:

n_label = 3 #B-PERSON, I-PERSON AND O
transitions = np.array(value, dtype=np.float32)

value的形状是(n_label + 2, n_label + 2),2是START和END的数量。另外,“value”的值是随机生成的。

Emission得分矩阵

你应该知道,BiLSTM层的输出是[2.1]中描述的句子的transition分数。例如,我们的句子有3个单词,BiLSTM的输出应该是这样的:

添加了额外的START和END标签后,emission分数矩阵为:

如上表所示,我们通过添加两个单词(start和end)及其对应的标签(START和END)来扩展排放emission矩阵。BiLSTM层的输出不包括新增单词的emission分数,但是我们可以手动指定这些分数(即 )。单词“start”上的其他标签的emission分数应该是一个小的值(例如-1000)。如果你想再设置一个小的值,这是完全可以的,不会影响我们模型的性能。

3.3 更新整个结构

基于上面的解释,这里有一个更详细的伪代码:

class My_CRF():
def __init__(n_label):
#[Initialization]
'''
1) Randomly initialize transition score matrix.
The shape of this matrix is (n_label+2, n_label+2).
n_labels is the number of named entity classes in our dataset (e.g. B-Person, I-Person, O).
2 is the number of our added labels (i.e. START and END).
2) Moreover, we also set the small value as -1000 here.
'''


def __call__(training_data_set):
#[Loss Function]
Total Cost = 0.0

#Compute CRF Loss
for sentence in training_data_set:
'''
1) Extend the emission score matrix by adding words(start and end)
and adding labels(START and END)
2) Compute the real path score of current sentence according the
true labels (section 2.4)
3) Compute the log total score of all the possbile paths of current
sentence (section 2.5)
4) Compute the cost on this sentence using the results from 2)
and 3) that is -(real_path_score - all_path_score). (section 2.5)
5) Total Cost += the cost of current sentence
'''

return Total Cost

def argmax(new sentences):
#[Prediction]
for sentence in new_sentences:
'''
1) Extend the emission score matrix by adding words(start and end)
and adding labels(START and END)
2) Predict the labels for the current new sentence (section 2.6)
'''

3.4 Demo

在这一节中,我们将造两个假句子,分别只有2个单词和1个单词。此外,我们还会随机生成他们的真实答案。最后,我们将展示如何使用Chainer v2.0训练CRF层。包括CRF层在内的所有代码都是来自GitHub:https://github.com/createmomo/CRF-Layer-on-the-Top-of-BiLSTM。

首先,我们导入自己的CRF层含义,' MyCRFLayer '。

import numpy as np
import chainer
import MyCRFLayer

在我们的数据集中我们只有两个标签(例如B-Person, O)

n_label = 2

下面的代码块生成两个句子,xs = [x1, x2]。句子x1有两个单词,x2只有一个单词。

a = np.random.uniform(-1, 1, n_label).astype('f')
b = np.random.uniform(-1, 1, n_label).astype('f')
x1 = np.stack([b, a])
x2 = np.stack([a])
xs = [x1, x2]

应该注意的是,x1和x2的元素不是词嵌入,而是BiLSTM层的emission分数,这里没有实现。

例如,在x1句子中,我们有两个单词w0和w1,而x1是一个形状为(2, 2)的矩阵。第一个“2”表示它有两个单词,第二个“2”表示我们的数据集中有两个标签,如下表所示。

接下来,我们应该有这两个句子的真正标签。

ys = [np.random.randint(n_label,size = x.shape[0],dtype='i') for x in xs]
print('Ground Truth:')
for i,y in enumerate(ys):
print('\tsentence {0}: [{1}]'.format(str(i),' '.join([str(label) for label in y])))

这里是随机生成的ground truth。

Ground Truth:
sentence 0: [0 0]
sentence 1: [1]

虽然我们并没有真正的BiLSTM层,但这并不会影响我们展示如何在chainer中训练一个模型。我们模拟了BiLSTM层的输出和真实答案。因此,我们可以使用一些优化器来优化CRF层。

在本文中,我们使用了随机梯度下降法来训练我们的模型。(如果你现在不熟悉训练方法,你可以以后再学。)这个优化器将根据我们的CRF层根据预测标签和ground truth标签之间的损失来更新参数(即transition矩阵)。

from chainer import optimizers
optimizer = optimizers.SGD(lr=0.01)
optimizer.setup(my_crf)
optimizer.add_hook(chainer.optimizer.GradientClipping(5.0))

CRF层通过标签的数量来初始化(不包括额外添加的开始和结束)。

my_crf = MyCRFLayer.My_CRF(n_label)

然后我们可以开始训练CRF层。

print('Predictions:')
for epoch_i in range(201):
with chainer.using_config('train', True):
loss = my_crf(xs,ys)
# update parameters
optimizer.target.zerograds()
loss.backward()
optimizer.update()
with chainer.using_config('train', False):
if epoch_i % 50 == 0:
print('\tEpoch {0}: (loss={1})'.format(str(epoch_i),str(loss.data)))
for i, prediction in enumerate(my_crf.argmax(xs)):
print('\t\tsentence {0}: [{1}]'.format(str(i), ' '.join([str(label) for label in prediction])))

正如我们的代码输出所示,损失正在减少,CRF层正在学习(预测正在变得正确)。

Predictions:
Epoch 0: (loss=3.06651592255)
sentence 0: [1 1]
sentence 1: [1]
Epoch 50: (loss=1.96822023392)
sentence 0: [1 1]
sentence 1: [1]
Epoch 100: (loss=1.51349794865)
sentence 0: [0 0]
sentence 1: [1]
Epoch 150: (loss=1.27118945122)
sentence 0: [0 0]
sentence 1: [1]
Epoch 200: (loss=1.09977662563)
sentence 0: [0 0]
sentence 1: [1]

3.5 GitHub

demo和CRF层代码可以在GitHub上找到。代码可能并不完美。因为为了便于理解,一些实现非常简单。我相信它可以被优化成一个更有效的算法。

END

英文原文:https://createmomo.github.io/2017/12/07/CRF-Layer-on-the-Top-of-BiLSTM-8/

推荐阅读

AINLP年度阅读收藏清单

【阿里巴巴 达摩院 小蜜团队】招聘NLP算法专家 & 实习生

自动作诗机&藏头诗生成器:五言、七言、绝句、律诗全了

逆向而行,中文轻量级预训练模型的探索之路

From Word Embeddings To Document Distances 阅读笔记

模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法

这门斯坦福大学自然语言处理经典入门课,我放到B站了

可解释性论文阅读笔记1-Tree Regularization

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。



登录查看更多
0

相关内容

条件随机域(场)(conditional random fields,简称 CRF,或CRFs),是一种判别式概率模型,是随机场的一种,常用于标注或分析序列资料,如自然语言文字或是生物序列。 如同马尔可夫随机场,条件随机场为具有无向的图模型,图中的顶点代表随机变量,顶点间的连线代表随机变量间的相依关系,在条件随机场中,随机变量 Y 的分布为条件机率,给定的观察值则为随机变量 X。原则上,条件随机场的图模型布局是可以任意给定的,一般常用的布局是链结式的架构,链结式架构不论在训练(training)、推论(inference)、或是解码(decoding)上,都存在效率较高的算法可供演算。
(ICML 2020 Tutorial)贝叶斯深度学习与概率模型构建,134页ppt
专知会员服务
154+阅读 · 2020年4月21日
【斯坦福大学-论文】实体上下文关系路径的知识图谱补全
NLP基础任务:文本分类近年发展汇总,68页超详细解析
专知会员服务
57+阅读 · 2020年1月3日
一文读懂命名实体识别
AINLP
31+阅读 · 2019年4月23日
命名实体识别(NER)综述
AI研习社
65+阅读 · 2019年1月30日
基于Lattice LSTM的命名实体识别
微信AI
47+阅读 · 2018年10月19日
基础 | 长文详解基于并行计算的条件随机场
黑龙江大学自然语言处理实验室
6+阅读 · 2018年6月9日
简明条件随机场CRF介绍 | 附带纯Keras实现
PaperWeekly
23+阅读 · 2018年5月22日
基础 | 一文轻松搞懂-条件随机场CRF
黑龙江大学自然语言处理实验室
16+阅读 · 2018年3月24日
基于attention的seq2seq机器翻译实践详解
黑龙江大学自然语言处理实验室
11+阅读 · 2018年3月14日
专栏 | Bi-LSTM+CRF在文本序列标注中的应用
机器之心
14+阅读 · 2018年1月3日
Generating Rationales in Visual Question Answering
Arxiv
5+阅读 · 2020年4月4日
Arxiv
9+阅读 · 2018年10月24日
Arxiv
5+阅读 · 2018年5月10日
VIP会员
相关资讯
一文读懂命名实体识别
AINLP
31+阅读 · 2019年4月23日
命名实体识别(NER)综述
AI研习社
65+阅读 · 2019年1月30日
基于Lattice LSTM的命名实体识别
微信AI
47+阅读 · 2018年10月19日
基础 | 长文详解基于并行计算的条件随机场
黑龙江大学自然语言处理实验室
6+阅读 · 2018年6月9日
简明条件随机场CRF介绍 | 附带纯Keras实现
PaperWeekly
23+阅读 · 2018年5月22日
基础 | 一文轻松搞懂-条件随机场CRF
黑龙江大学自然语言处理实验室
16+阅读 · 2018年3月24日
基于attention的seq2seq机器翻译实践详解
黑龙江大学自然语言处理实验室
11+阅读 · 2018年3月14日
专栏 | Bi-LSTM+CRF在文本序列标注中的应用
机器之心
14+阅读 · 2018年1月3日
Top
微信扫码咨询专知VIP会员