【传知代码】命名实体识别(论文复现)

前言:命名实体识别,作为自然语言处理(NLP)领域中的一项关键技术,近年来受到了广泛的关注和研究。它旨在从文本中自动识别和分类出具有特定意义的实体,如人名、地名、组织名、日期、时间等。这些实体不仅是文本信息的重要组成部分,更是许多自然语言处理任务的关键输入,如关系抽取、情感分析、问答系统等,想象一下,当我们阅读一篇新闻报道时,如果能够自动识别和标注出其中的人名、地名、事件等关键信息,那么我们就能更加迅速地把握文章的核心内容,甚至可以对这些信息进行进一步的分析和挖掘。

本文所涉及所有资源均在传知代码平台可获取

目录

概述

演示效果

核心代码

写在最后


概述

        在自然语言处理(NLP)领域,实体识别任务(Named Entity Recognition,简称NER)被视为一个核心任务,其主要目的是从文本资料中进行实体的识别和分类命名。命名实体一般都是由专有名词组成的,例如人名,地名和组织名。

下面的图示展示了一个基础的实体提取任务,该任务从句子中提取了阿里巴巴(组织名)、马云(人名)以及杭州(地名)这三个不同的实体:

NER 的主要目标是找到文本中有意义的实体,并将其归类到预定义的类别中。以下是一些常见的类别:

人名(Person):例如“乔布斯”、“马云”。
地名(Location):例如“纽约”、“长城”。
组织名(Organization):例如“微软”、“联合国”。

命名实体识别是自然语言处理领域的一个重要的任务,它在很多具体任务上有着自己的应用:

信息抽取:从大量文档中自动提取有价值的信息。
问答系统:帮助系统更准确地理解问题并返回相关答案。
文本摘要:在生成文本摘要时识别出关键实体以保留重要信息。
推荐系统:通过识别用户偏好的实体来提供个性化推荐。

本文的工作启发于另一篇 地址 ,具体如下图所示:

接下来对实现的技术方法进行一个简单的介绍:

BERT编码:首先,将输入的中文文本通过预训练的 BERT 模型进行编码,生成每个字的上下文表示。BERT模型通过其双向Transformer架构,能够捕捉文本中每个字与其前后文之间的复杂关系,从而生成高质量的字级别表示,有助于后续的特征提取和实体识别。

BiLSTM特征提取:接下来,将 BERT 输出的特征向量输入到双向长短时记忆网络(BiLSTM)中,以捕捉序列中的前后依赖关系。BiLSTM网络能够从两个方向处理序列数据,即从前向后和从后向前。使得模型可以充分利用上下文信息,对每个字在整个序列中的位置和角色进行更准确的建模,从而提取出更丰富的特征表示。

注意力机制:在 BiLSTM 层之后,引入注意力机制,以便模型能够聚焦于更相关的特征。注意力机制通过计算序列中各个字之间的相关性权重,使模型能够动态地调整对不同位置的字的关注程度。

CRF标注:最后,将经过注意力机制处理的特征向量输入CRF层,进行全局序列标注,输出最终的实体识别结果。CRF是一种用于序列标注的概率图模体型,它考虑了标注序列的全局依赖关系,从而在预测每个字的标签时,不仅依赖于当前字的特征,还综合考虑其邻近字的标注情况。

论文提出的BERT-BiLSTM-Att-CRF模型在中文数据集上取得了较好的识别效果。结合论文提出的框架,本文新增了一个LoRA层,用来优化模型,如下:

        神经网络包含许多密集层执行矩阵乘法。这些层中的权重矩阵通常是满秩的。当适应特定下游任务时,研究表明:预训练语言模型拥有较低的内在维度,也就是说,存在一个极低维度的参数,对它进行微调,和在全参数空间中进行微调,训练效果是相近的。受此启发,在参数更新过程中,应当也存在一个相对较低的“本征秩”。对于预训练的权重矩阵,通过低秩分解来约束其更新。在涉及到矩阵相乘的模块,增加一个新的通路,通过前后两个矩阵A,B相乘,第一个矩阵A负责降维,第二个矩阵B负责升维,中间层维度为r,从而来模拟本征秩。

本文所用的训练数据是MSRA-NER数据集,MSRA-NER是由微软亚洲研究院标注的新闻领域的实体识别数据集。该数据集包含5万多条中文实体识别标注数据,实体类别分为人物、地点、机构三类,数据集包含训练集46364个句子,验证集4365个句子,格式举例如下:

中 共 中 央 致 中 国 致 公 党 十 一 大 的 贺 词 各 位 代 表 、 各 位 同 志 : 在 中 国 致 公 党 第 十 一 次 全 国 代 表 大 会 隆 重 召 开 之 际 , 中 国 共 产 党 中 央 委 员 会 谨 向 大 会 表 示 热 烈 的 祝 贺 , 向 致 公 党 的 同 志 们 致 以 亲 切 的 问 候 !
B-ORG I-ORG I-ORG I-ORG O B-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG O O O O O O O O O O O O O O B-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG O O O O O O O B-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG I-ORG O O O O O O O O O O O O O B-ORG I-ORG I-ORG O O O O O O O O O O O O

采用BIO标注方式对获得的文本句子进行标注,BIO数据标注方式是命名实体识别(NER)任务中常用的一种标注方法。BIO代表三种标签:B(Begin),I(Inside)和O(Outside),用于标记文本中每个词属于某个命名实体的开头、内部或外部。以下是对BIO标注方式的详细介绍:

B(Begin):表示命名实体的开始。一个实体的第一个词标注为B-<实体类型>。
I(Inside):表示命名实体的内部。属于同一个实体的后续词标注为I-<实体类型>。
O(Outside):表示不属于任何命名实体的词。

例如,B-ORG表示组织实体的开头,I-ORG表示组织实体的内部。下图展示了一个标注好的例子,其中未标注的字段都是无实体(O):

演示效果

首先下载Bert预训练模型,然后收集自己要训练的数据集,放入文件中,修改源码中的路径名称,运行train.py函数,开始训练,可以自行调整训练中的epoch等参数,其中训练的时候会调用测试函数进行输出,如下可以看到模型开始训练,在模型训练结束后,会根据测试集的结果生成测试的结果:

           precision    recall  f1-score   support
    B-LOC     0.9257    0.8245    0.8721      2871
    I-LOC     0.8894    0.8796    0.8845      4370
    B-ORG     0.8625    0.7800    0.8192      1327
    B-PER     0.9513    0.9021    0.9261      1972
    I-PER     0.9254    0.9521    0.9386      3845
        O     0.9913    0.9917    0.9915    150935
    I-ORG     0.8631    0.9255    0.8932      5640
avg/total     0.9804    0.9803    0.9802    170960

运行demo.py可以根据输入的句子,进行实体识别,例如:

sentence = "在 唐 胜 利 康 复 回 乡 前 一 天 , 北 京 博 爱 医 院 院 长 吴 弦 光 代 表 医 院 向 唐 胜 利 及 其 父 亲 赠 送 编 织 机 。"
output =[['<START>', 'O', 'B-PER', 'I-PER', 'I-PER', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-LOC', 'B-ORG', 'B-ORG', 'B-ORG', 'B-ORG', 'B-ORG', 'O', 'O', 'B-PER', 'I-ORG', 'I-ORG', 'O', 'O', 'B-LOC', 'B-ORG', 'O', 'B-PER', 'I-PER', 'I-PER', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', '<END>']]

可以看出,模型能识别句子中的实体,并按照BIO标注返回结果

核心代码

        自定义attention层,在pytorch库中调用bert模型,LSTM模型和CRF模型等相关模型并利用BERT预先训练好的语言模型在字符级上编码输入文本,首先获取了动态词向量,接着利用双向长短期记忆(BiLSTM)网络来抽取全局的语义特性,并采用注意力机制来分配相应的权重,为了更精确地捕获关键特性,我们最终采用条件随机场(CRFs)来输出一个全局最优的标记序列。

如下代码实现了一个基于BERT预训练模型、双向LSTM、自注意力机制和条件随机场(CRF)的命名实体识别(NER)模型。下面是它的实现逻辑:

1)Self_Attention 类:这是一个自定义的自注意力机制模块,用于提取输入序列中的重要信息。在初始化时,它接受输入维度 input_dim,以及查询、键和值的维度 dim_k 和 dim_v。它包含三个线性层,分别用于计算查询(Q)、键(K)和值(V)的表示。在前向传播中,它计算了注意力权重并将其应用于值向量,以生成最终的自注意力输出。

2)BERT_BiLSTM_ATT_CRF 类:这是主要的模型类,它包含了BERT模型、双向LSTM、自注意力机制和CRF层。在初始化时,它接受BERT模型名称、隐藏层的dropout概率、标签数量和隐藏维度作为参数。在前向传播过程中,它首先使用BERT模型对输入进行编码,然后将编码后的序列输入到双向LSTM中,以获取更好的上下文表示。接着,通过自注意力机制对LSTM的输出进行加权平均,以捕获序列中的关键信息。最后,将加权平均后的表示传递给线性层,以将其映射到标签空间,并使用CRF层对标签序列进行建模。

总体而言,这个模型利用了BERT的预训练能力和自注意力机制的特性,结合了双向LSTM和CRF来解决命名实体识别任务,能够有效地捕获上下文信息和序列之间的依赖关系,从而提高了NER任务的性能。

import torch.nn as nn
from transformers import BertPreTrainedModel, BertModel, BertConfig
from torchcrf import CRF
import math
import torch


class Self_Attention(nn.Module):
    def __init__(self, input_dim, dim_k, dim_v):
        super(Self_Attention, self).__init__()
        self.q = nn.Linear(input_dim, dim_k)
        self.k = nn.Linear(input_dim, dim_k)
        self.v = nn.Linear(input_dim, dim_v)
        self._norm_fact = 1 / math.sqrt(dim_k)

    def forward(self, x):
        Q = self.q(x)  
        K = self.k(x) 
        V = self.v(x) 
        atten = torch.bmm(Q, K.permute(0, 2, 1)) * self._norm_fact  # Q * K.T()
        atten = nn.Softmax(dim=-1)(atten)
        output = torch.bmm(atten, V)  
        return output


class BERT_BiLSTM_ATT_CRF(nn.Module):
    def __init__(self, bert_model, hidden_dropout_prob, num_labels, hidden_dim=128):
        super(BERT_BiLSTM_ATT_CRF, self).__init__()
        self.bert = BertModel.from_pretrained(bert_model)
        bert_config = BertConfig.from_pretrained(bert_model)
        self.dropout = nn.Dropout(hidden_dropout_prob)

        self.bilstm = nn.LSTM(input_size=bert_config.hidden_size, hidden_size=hidden_dim, num_layers=1, bidirectional=True, batch_first=True)
        out_dim = hidden_dim* 2

        self.hidden2tag = nn.Linear(in_features=out_dim, out_features=num_labels)
        self.attention = Self_Attention(128, 128, 128)
        self.crf = CRF(num_tags=num_labels, batch_first=True)

    def forward(self, input_ids, tags, token_type_ids=None, attention_mask=None):
        outputs = self.bert(input_ids, token_type_ids=token_type_ids, attention_mask=attention_mask)
        sequence_output = outputs[0]  
        sequence_output, _ = self.bilstm(sequence_output)  
        sequence_output = self.dropout(sequence_output)
        sequence_output = self.attention(sequence_output)
        sequence_output = self.hidden2tag(sequence_output) 
        outputs = self.crf(sequence_output , tags, mask=attention_mask.byte())
        
        return outputs

        其中,为了优化模型的算法,在Bert的encoder模块加入了LoRA方法,使得模型的训练速度得到提高,训练效果得到提高。原则上,可以将LoRA应用到神经网络中,以减少可训练参数的数量。在Transformer结构中,自注意力模块有四个权重矩阵(Wq,Wk,Wv,Wo)(Wq​,Wk​,Wv​,Wo​),MLP模块有两个权重矩阵。通常来说,将LoRA添加到WqWq​和WkWk​两个模块中,效果是比较好的。因此,在Q(query)和K(key)模块,插入LoRA层。

    for layer in model.bert.encoder.bert_layer_groups:
        layer.bert_layers[0].attention.query = LinearLora(layer.bert_layers[0].attention.query,rank=8,alpha=16)
        layer.bert_layers[0].attention.key = LinearLora(layer.bert_layers[0].attention.key,rank=8,alpha=16)
       
    model.to(device)

写在最后

        命名实体识别技术还将与更多领域深度融合,产生更加广泛的应用。在医疗领域,它可以帮助医生更准确地诊断疾病、制定治疗方案;在金融领域,它可以帮助分析师更快速地识别市场趋势、做出投资决策;在智能客服领域,它可以帮助机器人更自然地与人类交流、解决问题。这些应用场景的实现,将让命名实体识别技术的价值得到更加充分的体现。因此,我们有理由相信,命名实体识别技术将在未来继续发光发热,成为推动人工智能发展的重要力量。让我们共同期待这一天的到来,并为此付出不懈的努力和探索。在这个充满无限可能的时代里,让我们携手前行,共同开启命名实体识别技术的新篇章!

详细复现过程的项目源码、数据和预训练好的模型可从该文章下方附件获取

【传知科技】关注有礼     公众号、抖音号、视频号

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦世凡华、

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值