从规则到通用大模型:命名实体识别(NER)技术的演进之路与实战解析

引言:信息抽取的“锚点”

在自然语言处理(NLP)的浩瀚星海中,如果说大语言模型(LLM)是 recently 爆发的超新星,那么**命名实体识别(Named Entity Recognition, 简称 NER)**就是那颗稳定燃烧、为航海者指明方向的北极星。

NER 的任务非常明确:从非结构化的文本中识别出具有特定类别的实体,并将其分类到预定义的类别中,如人名(PER)、地名(LOC)、机构名(ORG)、时间、日期等。

举个简单的例子:

输入文本2023年马斯克收购了位于旧金山推特

NER 系统的输出通常是:

  • 2023年 -> 时间 (TIME)
  • 马斯克 -> 人物 (PER)
  • 旧金山 -> 地点 (LOC)
  • 推特 -> 机构 (ORG)

作为信息抽取、知识图谱构建、问答系统和机器翻译等高级 NLP 任务的底层基石,NER 技术的发展史就是一部微缩的 NLP 技术进化史。从早期的规则词典,到统计机器学习,再到深度学习的百花齐放,直至如今被大语言模型(LLM)重新定义。

今天,我们将深入剖析 NER 技术的演进之路,探讨其背后的核心算法,并结合现代工业界的标准实践,给出可落地的代码示例。


第一阶段:基于规则与词典的“刀耕火种”时代(1990s 初期)

在计算资源匮乏、语料库极度匮乏的年代,NLP 学者们主要依赖语言学家的先验知识。这一时期的 NER 系统主要由正则表达式领域词典构成。

核心思想

构建庞大的专有名词词典(如人名词典、地名库),配合前缀、后缀等启发式规则。例如:如果某个词出现在“总统”、“先生”之后,且存在于人名词典中,则标记为 PER

优点与缺点

  • 优点:在特定垂直领域(如医疗病历识别、特定航班号提取)准确率极高,几乎不需要标注数据。
  • 缺点:泛化能力极差,“一本词典走天下”在面对互联网海量生僻实体、新词(OOV,Out-of-Vocabulary)时彻底失效;维护成本高昂。

历史足迹:著名的 HASP/SUMMARS 系统就是基于规则的典范。直到今天,规则依然没有消亡,它们常常作为现代模型的“后处理”修正层而存在。


第二阶段:统计机器学习的“数据驱动”时代(1990s 末 - 2000s)

随着语料库的逐渐丰富,NLP 迎来了统计机器学习的春风。NER 任务被形式化为序列标注问题。这一时期的核心标签体系是 BIO(Begin, Inside, Outside)BIOES 标注法。

  • B-PER:人名的起始词
  • I-PER:人名的内部词
  • O:非实体

三大经典模型

  1. 隐马尔可夫模型(HMM)
    HMM 假设数据由一个隐含的马尔可夫链生成。它结合了“转移概率”(从标签 yt1y_{t-1} 转移到标签 yty_t 的概率)和“发射概率”(在标签 yty_t 下生成单词 xtx_t 的概率)。但由于其严格的独立性假设(当前输出仅依赖于当前状态),它难以捕捉长距离的上下文特征。
  2. 支持向量机(SVM)
    通过精心设计的特征工程(词性、词根、前后缀、大小写、窗口词特征等),多分类 SVM 在当时的 CoNLL 评测中取得了极高的准确率。
  3. 条件随机场(CRF)—— 时代的王者
    CRF 是一种判别式无向图模型。与 HMM 不同,CRF 打破了独立性假设,它在计算某个词的标签时,不仅考虑当前词的特征,还考虑整个序列的全局特征。通过维特比解码,CRF 能找到全局概率最大的标签序列。

痛点

机器学习模型的性能天花板被特征工程死死限制。为了让模型表现好一点,工程师需要消耗大量精力去写正则、提取词性特征、构建词表。这被称为“炼丹”的前化石时代。


第三阶段:深度学习的“端到端”狂飙(2010s)

Word2Vec 的提出和 GPU 计算能力的爆发,正式拉开了深度学习在 NLP 中的帷幕。NER 终于摆脱了繁杂的人工特征工程,迎来了“端到端”的黄金时代。

经典架构:BiLSTM-CRF

2015年左右,Bidirectional LSTM + CRF 成为了 NER 领域无可争议的 State-of-the-Art (SOTA)。

  • Embedding 层:将离散的词汇映射为稠密的词向量(如 Word2Vec, GloVe)。
  • BiLSTM 层:双向长短期记忆网络。前向 LSTM 捕捉历史信息,后向 LSTM 捕捉未来信息。两者结合,使得模型能够深刻理解当前词汇在整个句子中的上下文语义。
  • CRF 层:为什么在 BiLSTM 后面还要加一层 CRF?
    因为 BiLSTM 只能独立预测每个位置的最佳标签,它可能会输出不合逻辑的序列(比如 B-PER 后面跟着 I-LOC)。CRF 层通过学习标签之间的转移矩阵(如 B-PERI-PER 的概率很高,到 O 的概率极低),从全局层面约束最终输出的合法性。

BiLSTM-CRF 的 PyTorch 代码骨架示例

在现代深度学习框架中,构建这样一个模型已经非常简洁。以下是使用 PyTorch 的核心逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import torch
import torch.nn as nn
from torchcrf import CRF

class BiLSTM_CRF(nn.Module):
def __init__(self, vocab_size, tagset_size, embedding_dim, hidden_dim):
super(BiLSTM_CRF, self).__init__()
self.embedding_dim = embedding_dim
self.hidden_dim = hidden_dim
self.vocab_size = vocab_size
self.tagset_size = tagset_size

# 词嵌入层
self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
# 双向 LSTM 层
self.lstm = nn.LSTM(embedding_dim, hidden_dim // 2,
num_layers=1, bidirectional=True, batch_first=True)
# 将 LSTM 的输出映射到标签空间
self.hidden2tag = nn.Linear(hidden_dim, tagset_size)
# CRF 层
self.crf = CRF(tagset_size, batch_first=True)

def forward(self, sentence, tags, mask=None):
# 1. 获取词向量
embeds = self.word_embeds(sentence)
# 2. LSTM 提取上下文特征
lstm_out, _ = self.lstm(embeds)
# 3. 线性层获取发射分数
lstm_feats = self.hidden2tag(lstm_out)

# 4. 计算 CRF 的负对数似然损失
# CRF 会自动结合发射分数和转移分数计算全局最优路径
loss = -self.crf(lstm_feats, tags, mask=mask, reduction='mean')
return loss

def decode(self, sentence, mask=None):
# 推理阶段:使用维特比算法解码最优标签序列
embeds = self.word_embeds(sentence)
lstm_out, _ = self.lstm(embeds)
lstm_feats = self.hidden2tag(lstm_out)

# 返回最佳标签路径
best_path = self.crf.decode(lstm_feats, mask=mask)
return best_path

第四阶段:预训练语言模型的“降维打击”(2018 - 2021)

如果说 BiLSTM-CRF 是巅峰之作,那么 Transformer 架构的诞生和 BERT (Bidirectional Encoder Representations from Transformers) 的横空出世,则直接对传统深度学习进行了降维打击。

范式转移

基于大规模无监督语料预训练+下游任务微调的范式彻底改变了 NLP。BERT 通过自注意力机制,能够无缝捕捉任意距离的词间依赖。

在 NER 任务中,BERT + Linear / BERT + CRF 成为了新的标配。对于大多数应用场景,仅仅在 BERT 模型之上加上一个简单的线性分类层,就能在 CoNLL-2003 等公开数据集上达到超越人类标注者的一致性水平。

为什么现在 CRF 有时显得不那么必须了?

因为 BERT 极其强大的上下文表征能力,使得它输出的每个 token 的隐状态已经包含极强的全局信息。Softmax 激活函数配合 Cross-Entropy Loss 在很多业务场景下已经足够优秀,而去掉了复杂的 CRF 层,模型推理速度会大幅提升。


第五阶段:大模型时代的“重塑”与“统一”(2022 - 至今)

ChatGPT 的出现,让我们重新审视了 NER 任务。在千亿参数的大语言模型(LLM)面前,传统的序列标注范式正在发生根本性的转变:从“Token级别的分类”走向“生成式的信息抽取”

生成式 NER (Generative NER)

在 LLM 中,我们不再需要训练复杂的 BiLSTM 或微调整个 BERT 模型。NER 被转化为一个 Text-to-Text 的任务。我们只需要设计合适的 Prompt(提示词),模型就能直接输出结构化的结果。

使用通用大模型进行 NER 的 Prompt 示例

系统提示词:

1
2
3
4
5
你是一个专业的高级信息抽取专家。你的任务是从给定的文本中提取命名实体。
请以严格的 JSON 格式输出结果。需要提取的实体类别包括:
- Person (人物)
- Location (地点)
- Organization (组织机构)

用户输入:

1
请提取以下文本中的实体:苹果公司现任CEO蒂姆·库克在加利福尼亚州的库比蒂诺发表了主题演讲。

大模型输出 (LLM Output):

1
2
3
4
5
{
"Person": ["蒂姆·库克"],
"Location": ["加利福尼亚州的库比蒂诺"],
"Organization": ["苹果公司"]
}

LLM 时代 NER 的挑战与对策

尽管大模型效果惊艳,但在工业级 NER 应用中仍面临三大挑战:

  1. 幻觉问题:模型可能凭空捏造实体。
  2. 输出格式不稳定:难以保证每次都生成 100% 严格合规的 JSON。
  3. 推理成本过高:使用千亿参数模型去提取简单的人名,无异于“大炮打蚊子”。

为了解决这些问题,现代工业界通常采用以下策略:

  • 约束解码:在推理时,通过有限状态机(FSM)限制 LLM 的输出必须符合 JSON 语法(如 JSON Schema)。
  • 通用信息抽取微调:使用如 LLaMA、Qwen 等较小参数(7B/14B)的开源模型,在大量 NER/RE 数据集上进行指令微调,打造专门针对信息抽取的小型模型(如 UIE、InstructUIE)。

实战演练:基于现代 Hugging Face 生态的工业级 NER

在当前的常规业务场景下,如果既没有条件部署庞大的 LLM,又需要极高的准确率和推理速度,基于预训练模型微调(如 BERT / RoBERTa)依然是首选方案

下面我们通过一段完整的 Python 代码,展示如何使用 Hugging Face 的 transformers 库,快速实现一个基于现代预训练模型的中文 NER 系统。

环境准备

1
pip install transformers torch datasets seqeval

完整代码实现(基于 PyTorch + Transformers)

我们将使用一个基础的中文 BERT 模型 (bert-base-chinese),配合最简单的 BertForTokenClassification 进行序列标注。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import torch
from transformers import AutoTokenizer, AutoModelForTokenClassification, Trainer, TrainingArguments
from datasets import load_dataset
import numpy as np
from seqeval.metrics import classification_report

# 1. 定义标签体系 (BIO格式)
label_list = ["O", "B-PER", "I-PER", "B-ORG", "I-ORG", "B-LOC", "I-LOC"]
label2id = {label: i for i, label in enumerate(label_list)}
id2label = {i: label for i, label in enumerate(label_list)}

# 2. 加载预训练模型和分词器
model_checkpoint = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = AutoModelForTokenClassification.from_pretrained(
model_checkpoint,
num_labels=len(label_list),
id2label=id2label,
label2id=label2id
)

# 3. 模拟数据预处理 (实际应用中应从 load_dataset 加载真实数据集)
# 假设我们有一句中文:"张三在北京大学读书"
sentence = "张三在北京大学读书"
tokens = list(sentence) # 中文按字切分
# 对应的人工标注标签
tags = ["B-PER", "I-PER", "O", "B-ORG", "I-ORG", "I-ORG", "I-ORG", "O", "O"]

# Tokenizer 处理 (注意处理 subword 带来的标签对齐问题)
inputs = tokenizer(tokens, truncation=True, is_split_into_words=True, return_tensors="pt")
labels = [label2id[tag] for tag in tags]

# 对于特殊的 [CLS] 和 [SEP] token,通常将其标签设为 -100,计算 Loss 时忽略
labels = [-100] + labels + [-100]
labels = torch.tensor([labels])

# 4. 前向传播测试 (演示模型如何运作)
outputs = model(**inputs, labels=labels)
print(f"当前 Batch 的 Loss: {outputs.loss.item():.4f}")

# 5. 推理演示
model.eval()
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits
predictions = torch.argmax(logits, dim=-1).squeeze().tolist()

# 将预测的 ID 映射回标签,并过滤掉 [CLS] 和 [SEP]
predicted_labels = [id2label[pred] for pred in predictions[1:-1]]

print("\n--- 实体识别结果 ---")
for token, pred_label in zip(tokens, predicted_labels):
print(f"Token: {token}\t Predicted Label: {pred_label}")

# 6. 模型训练配置 (如果在真实数据集上训练)
"""
training_args = TrainingArguments(
output_dir="./ner_model",
evaluation_strategy="epoch",
learning_rate=2e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=16,
num_train_epochs=3,
weight_decay=0.01,
)

trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset, # 需要提前准备好的 Dataset 对象
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)

trainer.train()
"""

代码解析

  1. Tokenizer 对齐:这是基于 Transformer 做 NER 时最容易踩坑的地方。因为 BERT 使用 WordPiece 分词,一个中文字可能会被切分为几个 Token。我们在构造 labels 时,必须用 -100 填充那些被切分出的多余 Token 以及 [CLS][SEP],以确保预测标签与原始字符一一对应。
  2. 模型选择BertForTokenClassification 在内部实际上就是在 BERT 输出之上加了一个 nn.Linear(hidden_size, num_labels)。如果你的业务对边界要求极高,可以尝试引入 torchcrf 替换默认的交叉熵损失。

总结与展望:NER 将走向何方?

回顾 NER 技术的演进历程,我们可以清晰地看到一条从简单到复杂,从局部到全局,从特定任务到通用智能的发展脉络:

  1. 规则与词典:死板但可解释,至今仍是不可替代的后处理手段。
  2. HMM 与 CRF:引入概率图模型,奠定了序列标注的理论基石。
  3. BiLSTM-CRF:深度学习与传统图模型的完美结合,摆脱了繁杂的特征工程。
  4. BERT:自注意力机制的大一统,预训练+微调成为工业界标准。
  5. LLM (大语言模型):将 NER 彻底重构为生成式任务,零样本能力达到前所未有的高度。

在未来,NER 技术会呈现以下几个明显趋势:

  • 细粒度与嵌套 NER(Nested NER):真实世界的实体往往是嵌套的(例如“北京大学人民医院”中,“北京大学”是 ORG,而整体也是 ORG)。未来的模型架构和 Prompt 设计将更侧重于解决这种复杂的图结构。
  • 多模态实体识别:结合文本、图像、甚至音频信息来抽取实体。比如在社交媒体中,通过图片辅助理解用户的发文意图和指代实体。
  • 极低资源下的快速适配:虽然 LLM 零样本能力强,但在极度专业的领域(如罕见病的医学病历提取),如何利用大模型提取伪标签结合小模型(如基于 LLaMA 架构的微调模型)进行知识蒸馏,将是工业界落地的研究热点。

NER 这颗 NLP 领域的北极星,不仅没有因为大模型的出现而黯淡,反而以更加灵活、更加强大的形态(信息抽取),继续照亮着人类迈向通用人工智能(AGI)的道路。无论技术如何更迭,理解其背后的序列建模思想,将是我们作为技术人员最宝贵的财富。