命名实体识别(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)。
- 流程:
- 数据准备:收集带实体标签的文本数据。
- 预处理:分词、清洗文本。
- 模型训练:使用规则、机器学习或深度学习模型。
- 评估:使用精确率(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-uncased或tinybert。 - 批量推理:设置
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-chinese或hfl/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),请告诉我,我可以提供详细代码和指导!