基于BiLSTM-CRF的中文电子病历命名实体识别

声明:博客未经允许禁止抄袭转载。

前言

最近有粉丝在后台私信我能不能更一篇关于命名实体识别(NER,Named Entity Recognition)的经典模型BiLSTM-CRF的实战文章,前段时间有点忙所有一直没有更新,趁着最近有点空,满足一下这个粉丝的愿望,话不多说直接上干货。

说明:为方便起见,本文沿用了之前的博客NLP实战:面向中文电子病历的命名实体识别中的数据集。关于命名实体识别的概念、实验评价指标、数据集介绍以及数据预处理的详细信息,同样可以参考我上面发布的博客。

词嵌入

关于词嵌入,本文的重点是探索条件随机场(Conditional Random Field, CRF)对命名实体识别的影响,因此弱化了词嵌入,直接采用了可学习的词嵌入nn.Embedding。为此,需要在预处理的过程中在训练数据集语料上构建字符到数字的映射词典,其中每个数字都对应词嵌入矩阵中一个可学习词嵌入的索引。

def get_dict(data, filter_word_num):# 统计词频word_count = {}for sample in data:text = sample.get('originalText')for word in text:word_count[word] = word_count.get(word, 0) + 1# 过滤低频词word2id = {"PAD": 0, "UNK": 1}for word, count in word_count.items():if count >= filter_word_num:word2id[word] = len(word2id)print("Total %d tokens, filter count<%d tokens, save %d tokens."%(len(word_count)+2, filter_word_num, len(word2id)))with open("processed/word2id.json", "w", encoding="utf-8") as fp:json.dump(word2id, fp, ensure_ascii=False)return word2id

模型设计与实现

BiLSTM-CRF是NER任务的经典模型(模型架构图如下),该模型利用双向LSTM从正向和逆向来更好的捕获语料序列的上下文关系,然后利用CRF来添加规则约束,避免许多不合理的预测,从而使得预测更加准确。

BiLSTM-CRF

条件随机场

在早期,NER通常直接使用循环神经网络来对序列进行编码,然后利用MLP来独立地预测各个token属于各个类别的概率。这种方式并没有考虑序列级别的相关性。例如对于某预测序列的当前词,若其正确标签为B-Disease&Dianonsis,那么当前词的下一个词的正确标签极大概率为I-Disease&Dianonsis,而不可能是B-Inspection等等。而引入CRF便可以从序列级别来添加类似这种的规则约束,从而提升分类准确率。

x = { x 1 , x 2 , . . . , x T } \mathbf{x}=\{x_1, x_2, ..., x_T\} x={x1,x2,...,xT}表示输入序列, y = { y 1 , y 2 , . . . y T } \mathbf{y}=\{y_1,y_2,...y_T\} y={y1,y2,...yT}表示输入序列对应的真实标签序列, P ∈ R T × n P\in\mathbb{R}^{T\times n} PRT×n表示将 x \mathbf{x} x经过BiLSTM编码后经MLP分类的预测概率矩阵, P i , j P_{i,j} Pi,j表示将序列的第 i i i个词预测为类别 j j j的概率,其中 n n n表示类别数, T T T表示序列的长度。对于CRF而言,它需要学习一个转移概率矩阵 A ∈ R n × n A \in \mathbb{R}^{n \times n} ARn×n A i , j A_{i,j} Ai,j表示若当前词预测类别为 i i i,下一个词预测预测为类别 j j j的概率。CRF会对整个序列的预测结果进行打分,以输入序列与真实标签序列为例,其得分 S ( x , y ) S(\mathbf{x},\mathbf{y}) S(x,y)的计算公式为:
S ( x , y ) = ∑ i = 0 T A y i , y i + 1 + ∑ i = 1 T P i , y i S(\mathbf{x}, \mathbf{y})=\sum_{i=0}^T A_{y_i, y_{i+1}}+\sum_{i=1}^T P_{i, y_i} S(x,y)=i=0TAyi,yi+1+i=1TPi,yi

上述计算公式不仅考虑了每个词的概率,还考虑了词与词之间的转移概率。对于CRF,其优化目标便是最大化 S ( x , y ) S(\mathbf{x}, \mathbf{y}) S(x,y)在所有可能出现的预测序列中的概率:
p ( y ∣ x ) = e S ( x , y ) ∑ y ′ ∈ y e S ( x , y ′ ) p(\mathbf{y} \mid \mathbf{x})=\frac{e^{S(\mathbf{x}, \mathbf{y})}}{\sum_{y^{\prime} \in \mathbf{y}} e^{S\left(\mathbf{x}, \mathbf{y}^{\prime}\right)}} p(yx)=yyeS(x,y)eS(x,y)
其中 y ′ \mathbf{y}\prime y表示所有可能的预测序列。转化为损失函数便是最小化如下的损失函数:
L = − ln ⁡ ( p ( y ∣ x ) ) = ln ⁡ ∑ y ′ ∈ y e S ( x , y ′ ) − S ( x , y ) \mathcal{L}=-\ln\left(p(\mathbf{y} \mid \mathbf{x})\right) = \ln \sum_{y^{\prime} \in \mathbf{y}} e^{S\left(\mathbf{x}, \mathbf{y}^{\prime}\right)}-S(\mathbf{x}, \mathbf{y}) L=ln(p(yx))=lnyyeS(x,y)S(x,y)

模型实现

根据上述介绍,利用Pytorch实现的BiLSTM-CRF模型代码如下所示:

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchcrf import CRFclass BiLSTMCRF(nn.Module):def __init__(self,output_size,embed_size,num_layers,hidden_size,drop_prob,vocab_size,use_crf=False):super(BiLSTMCRF, self).__init__()self.output_size = output_sizeself.use_crf = use_crfself.vocab_size = vocab_sizeself.word_embs = nn.Embedding(self.vocab_size, embed_size)# 定义BiLSTM层self.bilstm = nn.LSTM(bidirectional=True,num_layers=num_layers,input_size=embed_size,hidden_size=hidden_size,batch_first=True,dropout=drop_prob)# 定义全连接层self.fc = nn.Linear(2 * hidden_size, output_size)# 定义CRF层if use_crf:self.crf = CRF(self.output_size, batch_first=True)def forward(self, x, y, mask=None):x = self.word_embs(x)lstmout, _ = self.bilstm(x)emissions = self.fc(lstmout)if self.use_crf:loss = -self.crf(emissions=emissions, tags=y, mask=mask)else:loss = F.cross_entropy(emissions.reshape(-1, self.output_size), y.reshape(-1))return lossdef predict(self, x, mask=None):x = self.word_embs(x)lstmout, _ = self.bilstm(x)emissions = self.fc(lstmout) if self.use_crf:preds = self.crf.decode(emissions, mask)else:preds = torch.argmax(emissions, dim=-1).detach().cpu().numpy()return predsif __name__ == "__main__":pass

实验

本文的实验的环境为:

操作系统: Win10
Python版本:
Pytorch版本: 1.8
主要依赖库: seqeval-1.2.2, pytorch-crf-0.7.2

实验参数设置为:

params = {"lr": 0.001,"batch_size": 128,"epochs": 50,"output_size": len(LABEL),"embed_size": 256,"hidden_size": 256,"num_layers": 2,"drop_prob": 0.5,"use_crf": True # 是否添加CRF
}

限于时间原因,并没有进行细致调参,仅随便设置了一组参数,然后对使用和不使用CRF的模型进行对比。下图为对应的实验结果,从结果可以看出,不管是单个独立的类别还是整体,添加了CRF的效果基本上都要比不加CRF要好,由此验证了CRF设计的有效性。

BiLSTM-CRF-exp1

结语

完整源代码:地址

参考资料:

  • Bidirectional LSTM-CRF for Named Entity Recognition

以上便是本文的全部内容,要是觉得不错的话,可以点个赞或关注一下博主,你们的支持是博主进步的不竭动力,当然要是有问题的话也敬请批评指正!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s 优雅监控jvm及dump heap的方案探讨

背景 k8s cluster 的健康检测失败会主动重启pod&#xff0c;而大部份情况下健康检测失败都是由full gc引起的。往往发生重启时已经没有条件dump heap排查full gc的原因。 如何监控 为了避免因健康检测失败而导致的pod重启&#xff0c;我们需要实施有效的监控策略&#xff0c;这…

TPM 2.0:安全固件的新标准

得益于可信计算组 ( TCG ) 推出的全新 TPM 2.0规范&#xff0c;联网设备可以更好地抵御网络攻击&#xff0c;并且不太可能受到错误的攻击。 制造商将可信平台模块 (TPM) 附加到设备上&#xff0c;以帮助用户和管理员验证其身份、生成和存储加密密钥以及确保平台完整性。 在 T…

ensp实验-vrrp多网关配置

一、交换机与路由的配置区别 1. 角色定义交换机&#xff1a; Master 或 Backup: 交换机通常作为 Master 或 Backup 设备参与 VRRP&#xff0c;负责在主设备故障时接替其工作。路由器&#xff1a; Master 或 Backup: 路由器同样可以作为 Master 或 Backup 设备…

黑盒测试方法

‌黑盒测试是一种软件测试方法&#xff0c;它通过向系统提供输入并检查输出结果来验证系统的功能是否符合需求。‌黑盒测试主要关注软件的功能性&#xff0c;而不是其内部结构或工作原理。以下是几种常见的黑盒测试顺序方法&#xff1a; 场景设计法‌&#xff1a; 通过模拟实际…

游戏引擎学习第38天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾上次的内容。 我们之前讨论了将精灵放在屏幕上&#xff0c;但颜色错误的问题。问题最终查明是因为使用了一个调整工具&#xff0c;导致文件的字节顺序发生了变化。重新运行“image magic”工具对一些大图像进行重新处理后&am…

TDengine 新功能 复合主键

1. 简介 从 TDengine 3.3.0.0 版本之后&#xff0c;新增了复合主键的功能。 TDengine 原来的时间列是不允许有重复时间戳的&#xff0c;有了复合主键功能后&#xff0c;时间列即允许有重复&#xff0c;重复后的时间戳按紧跟其后第二列主键列的值来确定唯一性。 此功能的常用…

aws(学习笔记第十六课) 使用负载均衡器(ELB)解耦webserver以及输出ELB的日志到S3

aws(学习笔记第十六课) 使用负载均衡器(ELB)以及输出ELB的日志到S3 学习内容&#xff1a; 使用负载均衡器(ELB)解耦web server输出ELB的日志到S3 1. 使用负载均衡器(ELB) 全体架构 使用ELB(Elastic Load Balancer)能够解耦外部internet访问和web server之间的耦合&#xff0c…

深入理解C#的TCPIP通信机制

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;在分布式系统和实时数据交换应用中&#xff0c;C#作为一种现代面向对象编程语言&#xff0c;利用其***命名空间下的Socket类&#xff0c;提供强大的TCP/IP通信功能。本文将探讨C#中TCP/IP通信的基本概念、使用方…

M9484C VXG 矢量信号发生器- 110GHz-

M9484C VXG 矢量信号发生器 - 110GHz- M9484C VXG 是一款矢量信号发生器&#xff0c;在每个通道上提供 2.5 GHz 调制带宽&#xff0c;能够生成高达 54 GHz 的信号。 这款 VXG 矢量信号发生器可以组成经过校准和同步的全方位综合解决方案&#xff0c;帮助您更快测试下一代无线…

高项 - 项目管理原则与项目绩效域

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 博文更新参考时间点&#xff1a;2024-12 高项 - 章节与知识点汇总&#xff1a;点击跳转 文章目录 高项 - 项目管理原则与项目绩效域项目管理12条原则原则1&#xff1a;成为勤勉、尊重和关心他人的管家 (p202)原则…

仿真技术助力高尔夫球打破传统设计局限,实现球杆强大的功能

Altair近日宣布与业内领先的高尔夫装备制造商 Cleveland Golf 开展合作&#xff0c;以设计新款 HiBore XL 球杆。借助 Altair 先进的仿真与设计技术&#xff0c;Cleveland Golf 不断刷新高尔夫装备的行业标准&#xff0c;并在球杆产品设计方面实现突破。 Cleveland Golf 借助 A…

python字符串处理基础操作总结

1.去掉空格或者特殊符号 input_str.strip() #去掉所有空格 input_str.lstrip() #去掉左边空格 input_str.rstrip() #去掉右边空格 def print_hi():input_str 今天天气不错&#xff0c;风和日丽 out input_str.strip()print(input_str)print(out)if __name__ __main__:print…

阿里云PolarDB 如何进行数据恢复,文档总结

PolarDB不同场景下的恢复方式文档介绍&#xff1a; PolarDB在不同误操作场景下如何恢复数据_云原生数据库 PolarDB(PolarDB)-阿里云帮助中心 1. 不管误删的是表还是数据库&#xff0c;通过快照或者pitr的方式恢复到一个新的集群 全量恢复1 - 从备份集恢复&#xff1a; 如何从…

C#请求https提示未能为 SSL/TLS 安全通道建立信任关系

System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 &#xff0c;这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因&#xff1a; 证书不受信任&#…

Trimble X9三维激光扫描仪高效应对化工厂复杂管道扫描测绘挑战【沪敖3D】

化工安全关系到国计民生&#xff0c;近年来随着化工厂数字化改革不断推进&#xff0c;数字工厂逐步成为工厂安全管理的重要手段。而化工管道作为工厂设施的重要组成部分&#xff0c;由于其数量多、种类繁杂&#xff0c;一直是企业管理的重点和难点。 传统的化工管廊往往缺乏详…

日志基础示例python和c++

文章目录 0. 引言1. python2. c 0. 引言 本文主要记录python版本和c版本常用的日志基础示例。 1. python python版本常用的是logging库&#xff0c;结合colorlog库&#xff0c;可根据不同日志级别打印不同颜色的日志&#xff0c;为了便于分析问题&#xff0c;还添加了日志保…

【Linux】openssl version mismatch. built against 30000010, you have 30200020

错误&#xff1a;openssl version mismatch. built against 30000010, you have 30200020 这个错误通常是因为系统中安装了不同版本的 OpenSSL 库&#xff0c;导致程序在编译时使用了一个版本的 OpenSSL&#xff0c;而运行时却加载了另一个版本的库。根据错误信息&#xff0c;您…

智能码二维码的应用如何与其他技术(如物联网)结合,以提高电动工具行业的效率?

智能码二维码与物联网等技术的结合&#xff0c;能够多方面提高电动工具行业的效率&#xff0c;以下是详细介绍&#xff1a; 生产管理环节 与物联网传感器结合实现生产数据实时采集&#xff1a;在电动工具生产线上&#xff0c;为生产设备安装物联网传感器&#xff0c;并将传感器…

【Linux】基础IO-----文件详解

目录 一、文件理解&#xff1a; 二、C语言的文件操作&#xff1a; 1、fopen&#xff1a; 什么是当前路径&#xff1a; 2、fclose&#xff1a; 3、fwrite&#xff1a; 4、默认打开的三个流&#xff1a; 三、系统文件&#xff1a; 1、open&#xff1a; 2、close&#xf…

实时数据开发|Flink异步IO--提升性能和吞吐量

在使用Flink处理流式数据的过程中&#xff0c;会经常和外部系统进行数据交互。通常情况下在 Flink 中可以创建外部数据库系统的Client连接&#xff0c;然后通过Client连接将数据元素写入外部存储系统中或者从外部存储系统中读取数据。考虑到连接外部系统的网络等因素&#xff0…