#命名实体识别 (NER):从文本中抽取人名、地名、机构名
📂 所属阶段:第四阶段 — 预训练模型与迁移学习(应用篇)
🔗 相关章节:Hugging Face 实战 · Prompt Engineering 基础
#1. NER 概述
#1.1 什么是 NER?
NER = Named Entity Recognition
任务:从文本中识别出特定类型的实体
常见实体类型:
├── PER(人名):小明、Alice、张三
├── LOC(地名):北京、上海
├── ORG(机构):清华大学、阿里巴巴
├── TIME(时间):2024年、昨天
└── MONEY(金额):100元、$100
应用场景:
├── 搜索引擎(关键词高亮)
├── 知识图谱(实体抽取)
├── 智能客服(提取用户意图中的实体)
└── 金融风控(识别公司名、金额)
"""#2. BIO 标注法
#2.1 BIO 规则
"""
BIO 标注法:
B-xxx:实体的开始(Begin)
I-xxx:实体的中间/结尾(Inside)
O:非实体(Outside)
示例:
小明在北京大学读书。
PER LOC ORG
→ B-PER I-PER B-LOC I-ORG O
B-PER + I-PER + I-PER = 一个人名实体:小明
B-LOC + I-ORG = 一个地名+机构:清华大学
"""#2.2 标注数据集
# conll格式示例(NER 标准格式):
小明 B-PER
在 O
北京 B-LOC
大学 I-ORG
读 O
书 O
# 转换为 JSON
ner_data = [
{"tokens": ["小明", "在", "北京", "大学", "读", "书"],
"labels": ["B-PER", "O", "B-LOC", "I-ORG", "O", "O"]},
]#3. BERT NER 实现
from transformers import AutoTokenizer, AutoModelForTokenClassification, Trainer
from datasets import load_dataset, load_metric
import torch
# 加载中文 BERT + NER 模型
model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 直接用中文 NER 预训练模型
model = AutoModelForTokenClassification.from_pretrained(
"bert-base-chinese", num_labels=6 # 调整标签数
)
# 使用预训练的中文 NER 模型
from transformers import pipeline
ner_pipeline = pipeline(
"ner",
model="bert-base-chinese", # 或用 fine-tuned 的中文 NER 模型
aggregation_strategy="simple"
)
result = ner_pipeline("小明在北京大学读书")
print(result)
# [{'entity_group': 'PER', 'word': '小明', 'score': 0.99},
# {'entity_group': 'ORG', 'word': '北京大学', 'score': 0.97}]#4. 微调 NER 模型
# fine_tune_ner.py
from transformers import AutoTokenizer, AutoModelForTokenClassification, TrainingArguments
from datasets import load_dataset
import numpy as np
def align_labels_with_tokens(labels, word_ids):
"""将词级别标签对齐到 token 级别"""
aligned_labels = []
current_word = None
for word_id in word_ids:
if word_id is None:
aligned_labels.append(-100) # 特殊 token 忽略
elif word_id != current_word:
aligned_labels.append(labels[word_id]) # 新词的第一个 token
current_word = word_id
else:
aligned_labels.append(labels[word_id]) # 续 token 用 I-
return aligned_labels
def tokenize_and_align_labels(examples):
tokenized = tokenizer(
examples["tokens"],
is_split_into_words=True,
truncation=True,
max_length=128,
)
aligned = []
for labels, word_ids in zip(examples["labels"], tokenized.word_ids()):
aligned.append(align_labels_labels_with_tokens(labels, word_ids))
tokenized["labels"] = aligned
return tokenized
# 微调代码与分类器类似,只是:
# 1. 模型换成 AutoModelForTokenClassification
# 2. 评估指标换成 seqeval#5. 小结
# NER 速查
# 预训练 NER pipeline
ner = pipeline("ner", aggregation_strategy="simple")
result = ner("文本")
# 标注类型
B-PER # 人名开始
I-PER # 人名中间
B-LOC # 地名开始
I-LOC # 地名中间
B-ORG # 机构开始
I-ORG # 机构中间
O # 非实体💡 实践建议:中文 NER 推荐用
bert-base-chinese微调,或直接用 Hugging Face Hub 上的中文 NER 模型(如ctext/biaobiao)。
🔗 扩展阅读

