从头开始训练一个 NER 标注器

从头开始训练一个 NER 标注器

NER 标注的中文名为命名实体识别,与词性标注一样是自然语言处理的技术基础之一。NER 标注是指对现实世界中某个对象的名称的识别,例如法国、Donald Trump 或者微信。在这些词汇中法国是一个国家,标识为 GPE(地缘整治实体),Donald Trump 标识为 PER(人名),微信是一家公司,因此被标识为 ORG(组织)。

在spaCy的模块中常见的实体类型有:
在这里插入图片描述

NER标注的作用:
1)显而易见最主要的是通过模型可以识别出文本中需要的实体。
2)可以推导出实体之间的关系;例如,Rome is the capital of Italy,可以根据实体识别可以判断出 Rome 是意大利的城市而不是 R&B 艺术家,这项工作叫实体消岐(NED);

NED的使用场景可以在医学研究中消除词语歧义鉴定基因和基因产物,写作风格分析等。

接下来开始 spaCy 训练 NER 标注器。

注:本文使用 spaCy 3.0 代码实现。



一、自定义模型


1、导入所需要的包与模块
from __future__ import unicode_literals, print_function
import plac
import random
from pathlib import Path
import spacy
from spacy.training import Example
from spacy.tokens import Doc
2、导入训练样本

实体标注的索引从 0 开始 17 是最后一字符的索引 +1 ,索引参考python索引方法

# training data
TRAIN_DATA = [
    ('Who is Shaka Khan?', {
        'entities': [(7, 17, 'PERSON')] 
    }),
    ('I like London and Berlin.', {
        'entities': [(7, 13, 'LOC'), (18, 24, 'LOC')]
    })
]

虽然示例中的训练样本数量不多,但是具有代表性。



二、训练模型


1、对现有的模型进行优化
if model is not None:
        nlp = spacy.load(model)  # 加载存在的模型  
        print("Loaded model '%s'" % model)
    else:
        nlp = spacy.blank('en')  # 创建空白模型
        print("Created blank 'en' model")
2、创建内置管道组件

使用 add_pipeline函数创建流水线

if 'ner' not in nlp.pipe_names:
        ner = nlp.create_pipe('ner')
        nlp.add_pipe('ner', last=True)
    else:
        ner = nlp.get_pipe('ner')
3、添加train data的标签
for _, annotations in TRAIN_DATA:
        for ent in annotations.get('entities'):
            ner.add_label(ent[2])
4、构建模型

训练过程本身很简单,nlp.update()方法为我们抽象了所有内容,由 spaCy 处理实际的机器学习和训练过程。

# 禁用流水线中所有其他组件,以便只训练/更新NER标注器
other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'ner']
    with nlp.disable_pipes(*other_pipes):  # 仅训练我们标注的标签,假如没有则会对所有的标签训练,
        for itn in range(n_iter):
            random.shuffle(TRAIN_DATA)     # 训练数据每次迭代打乱顺序
            losses = {}                    # 定义损失函数
            for text, annotations in TRAIN_DATA:
                # 对数据进行整理成新模型需要的数据
                example = Example.from_dict(nlp.make_doc(text), annotations)    
                print("example:",example)
                nlp.update(
                    [example],  # 批注
                    drop=0.5,
                    sgd=optimizer,  # 更新权重
                    losses=losses)
            print(losses)
5、模型保存
if output_dir is not None:
        output_dir = Path(output_dir)
        if not output_dir.exists():
            output_dir.mkdir()
        nlp.to_disk(output_dir)
        print("Saved model to", output_dir)


三、模型测试

def load_model_test(path,text):
    nlp = spacy.load(path)
    print("Loading from", path)
    doc = nlp(text)
    for i in doc.ents:
        print(i.text,i.label_)

if __name__ == "__main__":
    path = "./model/"
    text = "Who is Shaka Khan"
    load_model_test(path,text)

模型的效果如下

Loading from ./model/
Shaka Khan PERSON

可以的到 Shaka Khan 标注为 PERSON,即人名。



参考

【法】巴格夫·斯里尼瓦萨-德西坎.《自然语言处理与计算语言学》.人民邮电出版社

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
BERT(Bidirectional Encoder Representations from Transformers,双向编码表示转换模型)是一种用于预训练自然语言处理任务的深度双向Transformer模型。NER(Named Entity Recognition,命名实体识别)是自然语言处理中的一个重要任务,旨在从文本中识别并分类命名实体,如人名、地名、组织机构名等。 BERT NER对抗训练是指在NER任务中使用BERT模型,并通过对抗训练方法来提高NER模型的性能和鲁棒性。对抗训练是一种训练方法,通过对抗性样本生成和模型训练来提高模型的泛化能力。 对抗训练中的样本生成阶段,首先利用BERT模型生成一些原始样本。然后,对这些样本进行扰动,比如替换、删除或插入一些单词,生成对抗样本。这些对抗样本具有较高的复杂性和困惑性,能够对NER模型产生挑战。 在对抗训练的模型训练阶段,使用BERT模型作为NER模型的编码,并将NER模型的输出与对抗样本进行比对。如果NER模型能够准确地标注对抗样本中的命名实体,说明NER模型对于复杂样本的鲁棒性较高。如果NER模型无法正确标注对抗样本中的命名实体,将利用反向传播方法更新NER模型的参数,使其能够更好地适应对抗样本的特点。 通过对抗训练,在NER任务中使用BERT模型可以帮助提高NER模型的性能和鲁棒性。对抗样本的生成能够使NER模型更好地理解和处理复杂样本,而模型的对抗训练能够增强模型的泛化能力和鲁棒性,使其在不同领域和真实场景中都能取得良好的性能表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值