NLP命名实体识别

news2024/11/27 5:31:40

命名实体识别(Named Entity Recognition, NER)是指在文本中识别出特殊对象,如人、地点、组织机构等。

命名实体识别方法概述

基于规则的方法:利用专家手工制订的规则进行命名实体识别。举例:“赵某出生于山东省菏泽市曹县……于 11 月 22 日将刘某诉至菏泽市曹县人民法院”,构建规则,满足“地名+人民法院”的词认定为组织机构。
基于传统机器学习的方法:基于传统机器学习的方法又可分为有监督和无监督的方式。有监督的方法将 NER 转换为多分类或序列标记任务。根据标注好的数据,人工构建特征工程,然后应用机器学习算法训练模型使其对数据的模式进行学习。例如隐马尔可夫模型(HMM)、支持向量机(SVM)和条件随机场(CRF)等。
基于深度学习的方法:以端到端的方式自动检测对应输入语料中的实体类别,通过深度学习的方式自动发现隐藏的特征,抽取与实体相对应的语义信息,是现在主流的做法。

粗粒度命名实体识别

标注形式

粗粒度命名实体识别对实体类别的划分比较简单,通常只是把实体划分为人名、地名、 组织机构和其他四种类型。
● PER,即 Person,表示人物,如 Michael Jordan、姚明。
● ORG,即 Organization,表示机构,如 World Health Organization、市政府。
● LOC,即 Location,表示地点,如 New York、北京。
● MISC,即 Miscellaneous,表示其他实体,需要区分于标注 O,如“东京奥运会”是一个其他实体,而O表示不属于实体的其他词。

IOBES 标注方式为例 :
● B,即 Begin,表示实体开头。
● I,即 Intermediate,表示实体中间。
● E,即 End,表示实体结尾。
● S,即 Single,表示单个词构成的实体。
● O,即 Other,表示其他,用于标记无关单词及字符。
举例:Michael Jordan visited Mars 被标注为 B-PER, E-PER, O, S-LOC。
除此之外,有IOB、BIO等标注方式。

基于LSTM的命名实体识别

命名实体识别任务的一个经典的解决方法是 :BiLSTM-CRF 模型。它由双向的 LSTM 网络后叠加一个 CRF 层组成,其结构如图所示:
在这里插入图片描述
案例分析:
以 CoNLL2003英语语料库数据集为例, 该数据集采用 BIO 标注法,实体被分为四种类型:人物(PER),地名(LOC),组织(ORG), 其他实体(MISC),即共 9 种标签,下图为数据集的一个例子。
在这里插入图片描述

class Conll03Reader: # 定义一个数据集读取类。
    def read(self, data_path): # 用于读取训练集、验证集和测试集。
        data_parts = ['train', 'valid', 'test']
        dataset = {}
        for data_part in tqdm(data_parts):
            dataset[data_part] = self.read_file(str(os.path.join(data_path, data_part+’txt’)))
        return dataset

	def read_file(self, file_path): # 用于从数据集中获取第一列的词,和第四列的实体标注。
        samples, tokens, tags = [], [], []
        with open(file_path,'r', encoding='utf-8') as fb:
            for line in fb:
                line = line.strip('\n’)
                if line == '-DOCSTART- -X- -X- O':  # 去除数据头
                    pass
                elif line ==‘’: # 每当一句话结束,将这句话中,词和对应标注的元组构成列表添加到samples中。
                    if len(tokens) != 0:
                        samples.append((tokens, tags))
                        tokens = []
                        tags = []
                else:         # 数据分割,只要开头的词和最后一个实体标注。
                    contents = line.split(' ')
                    tokens.append(contents[0])
                    tags.append(contents[-1])
        return samples


# 定义网络模型
class BiLSTM_CRF(nn.Module):
    def __init__(self, vocab_size, tag_to_ix, embedding_dim, hidden_dim):
    # 定义类初始化函数
        super(BiLSTM_CRF, self).__init__()
        self.embedding_dim = embedding_dim
        self.hidden_dim = hidden_dim
        self.vocab_size = vocab_size
        self.tag_to_ix = tag_to_ix
        self.tagset_size = len(tag_to_ix)

        self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim // 2,
                            num_layers=1, bidirectional=True)
        self.hidden2tag = nn.Linear(hidden_dim, self.tagset_size)
        # 转移矩阵,transaction[i][j]表示从label_j转移到label_i的概率,虽然是随机生成的,但是后面会迭代更新
        self.transitions = nn.Parameter(torch.randn(self.tagset_size, self.tagset_size))
        # 设置任何标签都不可能转移到开始标签,而结束标签不可能转移到其他任何标签
        self.transitions.data[tag_to_ix[START_TAG], :] = -10000
        self.transitions.data[:, tag_to_ix[STOP_TAG]] = -10000
        # 随机初始化lstm的输入(h_0,c_0)
        self.hidden = self.init_hidden()
	
	# 获取LSTM的输出
    def _get_lstm_features(self, sentence):
        # 输入:id化的自然语言序列
        # 输出:序列中每个字符的发射分数
        self.hidden = self.init_hidden()
        embeds = self.word_embeds(sentence).view(len(sentence), 1, -1)
        # lstm模型的输出矩阵维度为(seq_len,batch,num_direction*hidden_dim)
        lstm_out, self.hidden = self.lstm(embeds, self.hidden)
        # 把batch维度去掉,以便接入全连接层
        lstm_out = lstm_out.view(len(sentence), self.hidden_dim)
        # 用一个全连接层将其转换为(seq_len,tag_size)维度,才能生成最后的发射分数
        lstm_feats = self.hidden2tag(lstm_out)
        return lstm_feats

    # 前向传播,得到一个最佳的路径以及路径得分
    def forward(self, sentence):
        # 先输入BiLSTM模型中得到它的发射分数
        lstm_feats = self._get_lstm_features(sentence)
        # 使用维特比解码得到最大概率的标注路径,作为标注序列。
        score, tag_seq = self._viterbi_decode(lstm_feats)
        return score, tag_seq

# 将标签映射到数字类别便于计算
tag_to_ix = {"B-PER": 0, "I-PER": 1,"B-ORG":2,"I-ORG":3,"B-LOC":4,"I-LOC":5,"B-MISC":6,"I-MISC":7, "O": 8, START_TAG: 9, STOP_TAG: 10}
# 训练过程,文本序列输入模型,对应的标注序列转化为张量。
for epoch in range(EPOCH):
    for sentence, tags in training_data:
        # 训练前将梯度清零
        optimizer.zero_grad()
        # 准备输入
        sentence_in = prepare_sequence(sentence, word_to_ix)
        targets = torch.tensor([tag_to_ix[t] for t in tags], dtype=torch.long)
        # 前向传播,计算损失函数
        loss = model.neg_log_likelihood(sentence_in, targets)# 将文本序列输入模型,得到标注路径和路径得分,并同时计算正确标注序列的路径得分,从而计算loss。
        # 反向传播计算loss的梯度
        loss.backward()
        # 通过梯度来更新模型参数
        optimizer.step()

    # 损失函数
    def neg_log_likelihood(self, sentence, tags):
        feats = self._get_lstm_features(sentence)
        # 预测路径得分        
        forward_score = self._forward_alg(feats)
        # 正确路径得分
        gold_score = self._score_sentence(feats, tags)
        # 原本CRF是要最大化gold_score - forward_score,但深度学习一般都最小化损失函数,使得模型收敛,所以给该式子取反。
        return forward_score - gold_score

CRF需要维护两个矩阵,发射矩阵和转移矩阵。发射矩阵由BiLSTM的输出得到,转移矩阵则预先定义并随机初始化,在计算过程中迭代更新。
在这里插入图片描述

细粒度命名实体识别

细粒度命名实体识别是将实体识别并划分为更多的类型。细粒度命名实体识别往往对应着复杂的实体类别体系,实体类别体系可以构建树形层次结构。
在这里插入图片描述
FIGER 和 OntoNotes 是细粒度实体分类常用的数据集。其他细粒度命名实体识别数据集:TypeNet 拥有1080个类别,UFET 拥有10000多个细分类别。
在这里插入图片描述

存在的问题及解决方法

(1)类别体系不统一、标注难度大。
即便存在详细的标注标准,细粒度实体类别体系依然没有达成统一。当类别划分不清楚时,会很难指导标注人员去标注数据。
解决方案:基于当前已有的通用知识模型(Free base 等)实现类别界定。利用大规模知识图谱等进行远程监督标注。
(2)远程监督的噪声干扰。
该方法忽视了实体的上下文内容信息,导致引入了包含上下文无关的类别噪声。解决方案:基于启发的方法把有冲突的类型的mention给删掉。
(3)实体标注少、标签不平衡。
解决方案:迁移学习方法、小样本方法。
(4)实体标签有层次。
解决方案:利用层次信息提高识别效率,比如迁移学习等。
(5)实体边界嵌套。
比如‘北京大学”,“北京”,“大学”,采用序列标注方法很难奏效。
解决方案:可以尝试机器阅读理解等方法。

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

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

相关文章

【动态规划】独立任务最优调度问题

1.题目描述 2.算法思路 我认为做动态规划题的关键是找到一个合适的dp数组,确定它dp[i][j]的含义,用它和题目的最优子结构性质结合求解。具体思路如下: (笔记些许潦草hhh…) 1.dp[i][j]表示第i个作业在第j(0-A,1-B)台…

Keil setting issue

1, data type default issue caused enter “hard fault during debug” void HardFault_Handler(void) { /* if Hard Fault exception occurs, go to infinite loop */ if(CoreDebug->DHCSR & 1) {//check c DEBUGEN 1 -> Debugger connected __breakpoint(0); //…

小迪-day12(SQL注入简要概述)

1、相关sql函数、语句 1.1 count() 1.1.1 count(column_name) ​ count(column_name)是计算数据库表中指定列有多少行, ​ 例: SELECT COUNT(column_name) FROM table_name1.1.2 count(*) 可以计算表中有多少行(有多少条数据&#xff0…

基于 docker 搭建 grafana+prometheus 监控资源之mysql+docker+alertmanager配置(二)(超详细版)

先去看第一篇(基础部署篇),看完后,才能接上本篇。 基于 docker 搭建 grafanaprometheus 监控资源之mysqldockeralertmanager配置(二)环境信息服务基本信息一、安装Mysqld_exporter1.1 标准启动1.2 docker-c…

1554_AURIX_TC275_时钟监控功能以及时钟紧急行为

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 这部分还是前面CCU寄存器的一些延续,寄存器支持模块的禁用、禁用状态的查询以及是否支持休眠的控制。 1. 时钟监控是时钟进行安全设计需要考虑的一个手段,支持两种锁…

历史性突破,200层以上存储芯片率先量产,领先国外芯片巨头

近日,中企芯片技术迎来历史性突破,200层以上存储芯片率先量产,领先国外存储芯片巨头,或将成为全球行业领导者。后起之秀,鱼跃龙门 众所周知,存储芯片的生产,不仅需要高端技术,还需要…

MySQL之MVCC

多版本并发控制MVCC,也就是Copy on Write思想。MVCC除了支持读和读并行,还支持读和写并行、写和读并行,但为了保持数据一致性,写和写是无法并行的。 ​ 如下图,在事务1写的时候会copy一个记录的副本,其他事…

编译器做了这么多,你知道吗?

编译器做了什么 从最直观的角度来讲,编译器就是将高级语言翻译成机器语言的一个工具。比如我们用C/C语言写的一个程序可以使用编译器将其翻译成机器可以执行的指令及数据。我们前面也提到了,使用机器指令或汇编语言编写程序是十分费事及乏味的事情&…

LabVIEW编程LabVIEW开发ITECH IT6000D系列电源例程与相关资料

LabVIEW编程LabVIEW开发ITECH IT6000D系列电源例程与相关资料 ​IT6000D系列大功率可编程直流电源可支持多种规格的输出能力,以满足高电流、低电压或高电压、低电流等多种测试需求。同时,相同型号的整机间可并联工作,以实现更强大的输出能力…

settings.py配置文件(详解)

文章目录settings.py配置文件1. settings.py文件介绍1) BASE_DIR2) SECRET_KEY3) DEBUG4) ALLOWED_HOSTS5) INSTALLED_APPS6) MIDDLEWARE7) ROOT_URLCONF8) TEMPLATES9) WSGI_APPLICATION10) DATABASES11) AUTH_PASSWORD_VALIDATORS12) LANGUAGE_CODE和TIME_ZONE13) USE_118N和…

Cy7 Tyramide,Tyramide-Cy7,花青素Cy7 酪酰胺,Cy7酪胺

●外观以及性质: Cy7酪胺含有明亮的Cy7,可以使用标准的Cy7滤波片组轻松检测到。酪胺信号放大(TSA)是一种特别通用且功能强大的酶扩增技术,具有更高的检测灵敏度。西安凯新生物科技有限公司​为了实现大IHC检测&#xf…

排序算法总结

排序算法 排序算法可以分为内部排序和外部排序 内部排序是数据记录在内存中进行排序 外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并…

Qt-OpenCV学习笔记--人脸识别

前言 本人从事机械设计12年,业余时间自学编程。 2022年4月6日,开始学习C#, 2022年9月7日,开始学习c和Qt, 2022年10月28日,开始学习OpenCV, 今天终于搞定了传说中的 人脸识别 ,在…

spirngcloud的基本介绍与服务注册

1. 应用系统架构的演变 单应用架构 -> 应用服务器和数据库服务器分离 -> 应用服务器集群 -> 数据库压力变大,数据库读写分离 -> 引入缓存机制缓解数据库的压力 -> 数据库的水平/垂直拆分(数据库分库分表) -> 应用的拆分(微服务&…

[附源码]计算机毕业设计绿色生活交流社区网站Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

GitLab搭建

以docker方式运行gitlab docker run --detach \--hostname gitlab.mczaiyun.top \--publish 8443:443 --publish 8090:80 --publish 8022:22 \--name gitlab \--restart always \--volume /root/gitlab/config:/etc/gitlab \--volume /root/gitlab/logs:/var/log/gitlab \--vo…

Elasticsearch入门(二)基本操作(索引、文档、映射)

数据格式 Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解,我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比ES 里的 Index 可以看做一个库,而 Types 相当于表&#x…

【在Vue脚手架项目中使用qs框架】

目录 1. 安装qs框架 2. 在main.js中添加配置 1. 安装qs框架 在前端项目中,可以使用qs框架,实现“将对象转换为FormData格式的数据”。 首先,安装此框架: 如果没有权限进入C盘找到cmd的执行软件,用管理员启动&…

练习题(12-06)

目录 1.最小数 2.数天数 3.非常特殊的数 4.最大值路径 5.拆分质数 6.文件拷贝 7.除去重复单词 8.变成回文字符串 1.最小数 题目描述 请找到一个大于2022的最小数,这个最小的数转换成二进制后,最低的6个二进制全为0. 思路:枚举即…

[附源码]Python计算机毕业设计Django物业管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…