当前位置: 首页 > news >正文

【Transformers实战篇2】练习之命名实体识别

文章目录

  • 一、命名实体识别简介
    • 1.1 数据标注体系
    • 1.2 IOB2标注体系
    • 1.3 IOBES标注体系
  • 二、代码实战
    • 2.1 导入相关包
    • 2.2 加载数据集
    • 2.3 数据集预处理
      • 2.3.1 借助word_idx实现标签映射
    • 2.4 创建模型
    • 2.5 创建评估函数
    • 2.6 配置训练参数
    • 2.7 创建训练器
    • 2.8 模型训练
    • 2.9 模型预测


本文为 https://space.bilibili.com/21060026/channel/collectiondetail?sid=1357748的视频学习笔记

项目地址为:https://github.com/zyds/transformers-code


一、命名实体识别简介

  • 命名实体识别(Named Entity Recognition, 简称NER)是指识别文本中具有特定意义的实体,主要包括人名、地名、机构名、专有名词等。 通常包括两部分:① 实体边界识别 ② 确定实体类别(人名、地名、机构名或其他)
    例:“小明在北京上班”
实体类别实体
地点北京
人物小明

1.1 数据标注体系

  • 数据标注体系:IOB1、IOB2、IOE1、IOE2、IOBES、BILOU

1.2 IOB2标注体系

  • I 表示实体内部
  • O 表示实体外部
  • B 表示实体开始, 如B/I-xxx, XXX表示具体的类别。如下表格:
标记说明
B-Person人名开始
I-Person人名中间
B-Organization组织名开始
I-Organization组织名中间
O非命名实体

1.3 IOBES标注体系

  • I 表示实体内部
  • O 表示实体外部
  • B 表示实体开始
  • E 表示实体结束
  • S 表示一个词单独形成一个命名实体
  • 有时也会用M来代替I

二、代码实战

2.1 导入相关包

import evaluate
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForTokenClassification, TrainingArguments, Trainer, DataCollatorForTokenClassification, AutoModel

2.2 加载数据集

# 如果可以联网,直接使用load_dataset进行加载
#ner_datasets = load_dataset("peoples_daily_ner", cache_dir="./data")
# 如果无法联网,则使用下面的方式加载数据集
from datasets import DatasetDict
ner_datasets = DatasetDict.load_from_disk("ner_data")

先看一下数据集,发现tokens是由多个单个字token组成,是一个字一个字的。
ner_tags 是标签。ner_tags的长度和tokens的长度是对应的

ner_datasets["train"][0]
# 查看数据集的属性,其中ner_tags 也是一个序列
ner_datasets["train"].features

输出如下:
在这里插入图片描述

#%%
# 获取 ner_tags 中的 labels
label_list = ner_datasets["train"].features["ner_tags"].feature.names
label_list

输入如下:O表示非命名实体,B-PER表示人名开始。
在这里插入图片描述

2.3 数据集预处理

# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained("../../models/hfl/chinese-macbert-base")

这里注意:
如果直接tokenizer,会将每个拆分好的token,也就是每一个字都当成一个句子。因此,要指定is_split_into_words参数为True

# 如果直接tokens,会将每个拆分好的token,都当成一个句子
#tokenizer(ner_datasets["train"][0]["tokens"])  # 对于已经做好tokenize的数据,要指定is_split_into_words参数为True
# is_split_into_words=True 则当成整个句子
tokenizer(ner_datasets["train"][0]["tokens"], is_split_into_words=True)   # 对于已经做好tokenize的数据,要指定is_split_into_words参数为True

考虑到一个字可能会分成几个子字,如:interesting就被分成了4个子词,因此我们还需要对标签进行特殊的处理。

# tokenizer子词处理,拆出来了5个token
res = tokenizer("interesting word a")
res.word_ids()

2.3.1 借助word_idx实现标签映射

# 借助word_ids 实现标签映射
def process_function(examples):tokenized_exmaples = tokenizer(examples["tokens"], max_length=128, truncation=True, is_split_into_words=True)labels = []for i, label in enumerate(examples["ner_tags"]):word_ids = tokenized_exmaples.word_ids(batch_index=i)label_ids = []for word_id in word_ids:if word_id is None:label_ids.append(-100) # -100 指不会被交叉熵用上来else:label_ids.append(label[word_id])labels.append(label_ids)tokenized_exmaples["labels"] = labelsreturn tokenized_exmaples
#%%
tokenized_datasets = ner_datasets.map(process_function, batched=True)

2.4 创建模型

一定要设置num_labels

# 对于所有的非二分类任务,切记要指定num_labels,否则就会device错误
model = AutoModelForTokenClassification.from_pretrained("../../models/hfl/chinese-macbert-base", num_labels=len(label_list))

2.5 创建评估函数

#%%
# 这里方便大家加载,替换成了本地的加载方式,无需额外下载
seqeval = evaluate.load("seqeval_metric.py")
import numpy as npdef eval_metric(pred):predictions, labels = predpredictions = np.argmax(predictions, axis=-1)# 将id转换为原始的字符串类型的标签true_predictions = [[label_list[p] for p, l in zip(prediction, label) if l != -100]for prediction, label in zip(predictions, labels) ]true_labels = [[label_list[l] for p, l in zip(prediction, label) if l != -100]for prediction, label in zip(predictions, labels) ]result = seqeval.compute(predictions=true_predictions, references=true_labels, mode="strict", scheme="IOB2")return {"f1": result["overall_f1"]}

2.6 配置训练参数

args = TrainingArguments(output_dir="models_for_ner",per_device_train_batch_size=64,per_device_eval_batch_size=128,eval_strategy="epoch",save_strategy="epoch",metric_for_best_model="f1",load_best_model_at_end=True,logging_steps=50,num_train_epochs=1,save_safetensors=False
)

2.7 创建训练器

trainer = Trainer(model=model,args=args,tokenizer=tokenizer,train_dataset=tokenized_datasets["train"],eval_dataset=tokenized_datasets["validation"],compute_metrics=eval_metric,data_collator=DataCollatorForTokenClassification(tokenizer=tokenizer)
)

2.8 模型训练

trainer.train()

2.9 模型预测

from transformers import pipeline
# 使用pipeline进行推理,要指定id2label
model.config.id2label = {idx: label for idx, label in enumerate(label_list)}
# 如果模型是基于GPU训练的,那么推理时要指定device
# 对于NER任务,可以指定aggregation_strategy为simple,得到具体的实体的结果,而不是token的结果
ner_pipe = pipeline("token-classification", model=model, tokenizer=tokenizer, device=0, aggregation_strategy="simple")
res = ner_pipe("小明在北京上班")
# 根据start和end取实际的结果
ner_result = {}
x = "小明在北京上班"
for r in res:if r["entity_group"] not in ner_result:ner_result[r["entity_group"]] = []ner_result[r["entity_group"]].append(x[r["start"]: r["end"]])ner_result

输出:
在这里插入图片描述


http://www.mrgr.cn/news/37713.html

相关文章:

  • Elixir求解螺旋矩阵问题
  • 如何伪装一台直播设备的网络信息在其他地区
  • C++:采用模板封装顺序表,栈,队列
  • 【数据结构】堆(Heap)详解
  • 校园外卖系统SpringBoot免费分享
  • QT 获取视频帧Opencv获取清晰度
  • 【工具分享】FenixLocker勒索病毒解密工具
  • 宝塔面板部署雷池社区版教程
  • 理解:基础地理实体相关概述
  • 企业安全策略制定
  • TDengine 签约青山钢铁,实现冶金全流程质量管控智能化
  • 长效ip的特征除了稳定还有什么
  • 深圳龙链科技:全球区块链开发先锋,领航Web3生态未来
  • 硕博论文写作如何完成一篇符合学术诚信的优秀论文
  • 数据库事务
  • Java/Spring项目中包名以“com”开头的原因分析
  • 代码随想录算法训练营Day13
  • SSL证书自动申请脚本
  • java 生成.h文件,java调用c语言dll动态链接库流程
  • Power Platform开发小技巧,一天一个APP, 如何快速搭建二维码识别器