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

2024-06-21 08:58

本文主要是介绍BiLSTM上的CRF,用命名实体识别任务来解释CRF(4),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方“AI公园”,关注公众号,选择加“星标“或“置顶”


作者: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 labels2) The log total score of all the possbile paths of current sentence3) Compute the cost on this sentence using the results from 1) and 2)4) Total Cost += Cost of this sentence'''return Total Costdef 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 Lossfor 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 thetrue labels (p 2.4)3) Compute the log total score of all the possbile paths of currentsentence (p 2.5)4) Compute the cost on this sentence using the results from 2)and 3) that is -(real_path_score - all_path_score). (p 2.5)5) Total Cost += the cost of current sentence'''return Total Costdef 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 (p 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 parametersoptimizer.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/

请长按或扫描二维码关注本公众号

喜欢的话,请给我个好看吧

这篇关于BiLSTM上的CRF,用命名实体识别任务来解释CRF(4)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1080770

相关文章

浅谈Redis Key 命名规范文档

《浅谈RedisKey命名规范文档》本文介绍了Redis键名命名规范,包括命名格式、具体规范、数据类型扩展命名、时间敏感型键名、规范总结以及实际应用示例,感兴趣的可以了解一下... 目录1. 命名格式格式模板:示例:2. 具体规范2.1 小写命名2.2 使用冒号分隔层级2.3 标识符命名3. 数据类型扩展命

Django之定时任务django-crontab的实现

《Django之定时任务django-crontab的实现》Django可以使用第三方库如django-crontab来实现定时任务的调度,本文主要介绍了Django之定时任务django-cront... 目录crontab安装django-crontab注册应用定时时间格式定时时间示例设置定时任务@符号

使用Python和PaddleOCR实现图文识别的代码和步骤

《使用Python和PaddleOCR实现图文识别的代码和步骤》在当今数字化时代,图文识别技术的应用越来越广泛,如文档数字化、信息提取等,PaddleOCR是百度开源的一款强大的OCR工具包,它集成了... 目录一、引言二、环境准备2.1 安装 python2.2 安装 PaddlePaddle2.3 安装

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3