命名实体识别(NER)

命名实体识别(NER)简介

命名实体识别(Named Entity Recognition, NER)是自然语言处理(NLP)中的一项核心任务,旨在从文本中识别和分类命名实体,如人名(Person)、组织(Organization)、地点(Location)、时间(Date)等。NER 是信息提取、问答系统、知识图谱构建等应用的基础。本教程基于 2025 年 10 月的最新技术和 Python 生态(Python 3.10+),介绍 NER 的原理、方法、工具和代码示例,涵盖传统方法和深度学习方法,适合初学者和中级开发者。


1. NER 的核心概念

  • 定义:从非结构化文本中提取命名实体,并标注其类别。
  • 常见实体类型
  • 人名(PER):如 “Elon Musk”。
  • 组织(ORG):如 “Apple”、”xAI”。
  • 地点(GPE):如 “San Francisco”、”China”。
  • 时间(DATE/TIME):如 “October 22, 2025″。
  • 其他:产品(PRODUCT)、货币(MONEY)等。
  • 任务类型
  • 序列标注:为每个词标注实体标签(如 B-PER、I-PER、O)。
  • 嵌套实体:处理实体嵌套(如 “University of California” 既是 ORG 又是 GPE)。
  • 流程
  1. 数据准备:收集带实体标签的文本数据。
  2. 预处理:分词、清洗文本。
  3. 模型训练:使用规则、机器学习或深度学习模型。
  4. 评估:使用精确率(Precision)、召回率(Recall)、F1 分数。

2. 常用工具

以下是 2025 年主流的 Python 库,适合 NER:

  • spaCy:工业级 NLP 库,高效支持多语言 NER。
  • NLTK:提供基础 NER 功能,适合教学。
  • Transformers (Hugging Face):基于 BERT 等模型的高性能 NER。
  • Flair:专为序列标注设计的框架,性能优异。
  • Stanford NLP:经典工具,支持多语言 NER。

安装命令

pip install spacy transformers flair nltk
python -m spacy download en_core_web_sm  # 英语模型
python -m spacy download zh_core_web_sm  # 中文模型

3. 传统方法

传统 NER 方法依赖规则或条件随机场(CRF),结合特征工程。

3.1 示例代码:spaCy NER

spaCy 提供预训练模型,适合快速实现 NER。


import spacy

加载英语模型

nlp = spacy.load(“en_core_web_sm”)

测试文本

text = “Apple is launching iPhone 16 in San Francisco on October 22, 2025.”
doc = nlp(text)

提取实体

for ent in doc.ents:
print(f”实体: {ent.text}, 类型: {ent.label_}”)

输出示例

实体: Apple, 类型: ORG
实体: iPhone 16, 类型: PRODUCT
实体: San Francisco, 类型: GPE
实体: October 22, 2025, 类型: DATE

说明

  • 模型en_core_web_sm 是 spaCy 的小型英语模型,包含预训练 NER。
  • 优势:开箱即用,速度快,适合快速原型。
  • 局限:小型模型精度较低,需大型模型(如 en_core_web_lg)或微调。

3.2 中文 NER

中文 NER 需要专用模型,如 zh_core_web_sm


import spacy

加载中文模型

nlp = spacy.load(“zh_core_web_sm”)

测试文本

text = “苹果公司将于2025年10月22日在旧金山推出iPhone 16。”
doc = nlp(text)

提取实体

for ent in doc.ents:
print(f”实体: {ent.text}, 类型: {ent.label_}”)

输出示例

实体: 苹果公司, 类型: ORG
实体: 旧金山, 类型: GPE
实体: 2025年10月22日, 类型: DATE
实体: iPhone 16, 类型: PRODUCT

说明:中文 NER 依赖精确分词,spaCy 的中文模型内置了分词和 NER 功能。


4. 深度学习方法(基于 Transformers)

基于 Transformer 的模型(如 BERT)通过上下文嵌入显著提升 NER 性能,适合复杂场景。

4.1 示例代码:BERT NER(预训练)

使用 Hugging Face 的 pipeline 进行 NER。


from transformers import pipeline

加载预训练 NER 模型

ner = pipeline(“ner”, model=”dslim/bert-base-NER”, grouped_entities=True)

测试文本

text = “Apple is launching iPhone 16 in San Francisco on October 22, 2025.”
results = ner(text)

提取实体

for entity in results:
print(f”实体: {entity[‘word’]}, 类型: {entity[‘entity_group’]}, 置信度: {entity[‘score’]:.4f}”)

输出示例

实体: Apple, 类型: ORG, 置信度: 0.9992
实体: iPhone 16, 类型: PRODUCT, 置信度: 0.9987
实体: San Francisco, 类型: LOC, 置信度: 0.9995
实体: October 22 2025, 类型: DATE, 置信度: 0.9978

说明

  • 模型dslim/bert-base-NER 是 Hugging Face 社区的预训练 NER 模型。
  • pipeline:自动处理分词和实体分组。
  • 优势:高精度,捕捉上下文。

4.2 微调 BERT NER

对于特定领域(如医疗、法律),需微调 BERT 模型。


from transformers import BertTokenizerFast, BertForTokenClassification
from transformers import Trainer, TrainingArguments
import torch
from torch.utils.data import Dataset

示例数据集(BIO 格式)

texts = [“Apple is launching iPhone 16 in San Francisco.”]
labels = [[[“O”, “B-ORG”, “O”, “O”, “B-PRODUCT”, “I-PRODUCT”, “O”, “B-GPE”, “I-GPE”, “O”]]]

标签映射

label_list = [“O”, “B-PER”, “I-PER”, “B-ORG”, “I-ORG”, “B-GPE”, “I-GPE”, “B-PRODUCT”, “I-PRODUCT”]
label2id = {label: idx for idx, label in enumerate(label_list)}
id2label = {idx: label for label, idx in label2id.items()}

自定义数据集

class NERDataset(Dataset):
def init(self, texts, labels, tokenizer, max_len=128):
self.texts = texts
self.labels = labels
self.tokenizer = tokenizer
self.max_len = max_len

def __len__(self):
    return len(self.texts)

def __getitem__(self, idx):
    text = self.texts[idx]
    label = self.labels[idx][0]  # 假设每句一个标签序列

    # 分词并对齐标签
    encoding = self.tokenizer(text, truncation=True, padding='max_length', max_length=self.max_len, return_offsets_mapping=True)
    aligned_labels = [-100] * self.max_len  # -100 忽略损失计算
    tokens = self.tokenizer.convert_ids_to_tokens(encoding['input_ids'])

    # 简单对齐(实际需更复杂处理)
    token_idx = 0
    for i, (offset, token) in enumerate(zip(encoding['offset_mapping'], tokens)):
        if token_idx < len(label) and offset[0] == 0 and offset[1] != 0:  # 有效 token
            aligned_labels[i] = label2id[label[token_idx]]
            token_idx += 1

    return {
        'input_ids': torch.tensor(encoding['input_ids'], dtype=torch.long),
        'attention_mask': torch.tensor(encoding['attention_mask'], dtype=torch.long),
        'labels': torch.tensor(aligned_labels, dtype=torch.long)
    }

加载分词器和模型

tokenizer = BertTokenizerFast.from_pretrained(“bert-base-uncased”)
model = BertForTokenClassification.from_pretrained(“bert-base-uncased”, num_labels=len(label_list), id2label=id2label, label2id=label2id)

创建数据集

dataset = NERDataset(texts, labels, tokenizer)

训练参数

training_args = TrainingArguments(
output_dir=”./ner_results”,
num_train_epochs=3,
per_device_train_batch_size=8,
logging_steps=10,
save_steps=100,
)

训练

trainer = Trainer(model=model, args=training_args, train_dataset=dataset)
trainer.train()

测试

test_text = “Apple is launching iPhone 16 in San Francisco.”
inputs = tokenizer(test_text, return_tensors=”pt”, truncation=True, padding=True)
outputs = model(**inputs)
predictions = torch.argmax(outputs.logits, dim=2)[0]
tokens = tokenizer.convert_ids_to_tokens(inputs[“input_ids”][0])
for token, pred in zip(tokens, predictions):
if pred != 0: # 忽略 O 标签
print(f”Token: {token}, 实体: {id2label[pred.item()]}”)

说明

  • 数据集:示例使用简单 BIO 标签(Begin, Inside, Outside),实际需标准数据集(如 CoNLL-2003)。
  • 微调:需要 GPU,处理复杂标签对齐(如子词问题)。
  • 评估:使用 seqeval 库计算精确率、召回率。

5. 性能优化技巧

  • spaCy
  • 批量处理:使用 nlp.pipe(texts) 提高推理速度。
  • 缓存模型:加载一次模型,复用推理。
  • Transformers
  • 轻量模型:使用 distilbert-base-uncasedtinybert
  • 批量推理:设置 batch_size=32
  • GPU 加速:确保 PyTorch 支持 CUDA(pip install torch --index-url https://download.pytorch.org/whl/cu118)。
  • 量化:使用 ONNX 或 torch.quantization 优化推理。
  • 数据优化
  • 清洗文本:移除无关字符(参考文本预处理教程)。
  • 缓存预处理结果:保存 token 和标签。

6. 注意事项

  • 数据质量
  • 确保数据集包含足够实体类型(如 CoNLL-2003、OntoNotes)。
  • 处理不平衡标签(如 O 标签过多)。
  • 语言支持
  • 英文:丰富模型(如 dslim/bert-base-NER)。
  • 中文:使用 bert-base-chinesehfl/chinese-roberta-wwm-ext
  • 模型选择
  • 小型任务:spaCy 的预训练模型。
  • 复杂任务:微调 BERT 或 Flair。
  • 评估指标
  • 使用精确率、召回率、F1 分数(推荐 seqeval 库)。

7. 进阶学习建议

  • 领域特定 NER:微调模型处理医疗(如 BioNLP)、法律文本。
  • 多语言 NER:使用 xlm-roberta-base 支持多语言。
  • 嵌套 NER:尝试 Flair 或定制 CRF 层。
  • 资源
  • Hugging Face NER:BERT NER 指南。
  • spaCy NER:预训练模型教程。
  • Flair 文档:高性能 NER。
  • CSDN NER 教程:中文案例。

如果你需要针对特定任务(如中文 NER、医疗实体提取)或更复杂的实现(如嵌套 NER),请告诉我,我可以提供详细代码和指导!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注