3. 实体识别基础:命名实体识别(NER)的概念与常用方法

做知识图谱的人,早晚都要面对同一个问题:怎么从一堆乱七八糟的文本里把“人、地、组织”这些东西拎出来?

这活儿就叫命名实体识别(Named Entity Recognition,NER)。说白了,就是让计算机看懂文本里哪些词是专有名词,并且给它们打上标签。

我记得刚开始接触这个任务时,想法很简单——不就是找人名地名嘛。结果被现实狠狠教育了一顿:同一家企业在不同新闻里可能叫“阿里巴巴”、“阿里”、“Alibaba”、“淘宝母公司”,甚至“BABA”。你光靠词典匹配,根本兜不住。

所以这一章,我们就好好聊聊NER到底在干什么,以及哪些方法真正能用。

3.1 什么是命名实体识别

命名实体识别是信息抽取的基础任务。它从文本中识别出具有特定意义的实体,并分类到预定义的类别里,比如人名、地名、机构名、时间、金额等。

举个例子,输入句子:

昨日,华为技术有限公司在深圳总部发布了新款MatePad,售价3999元起。

一个合格的NER系统应该输出:

华为技术有限公司 -> ORG(机构)
深圳 -> LOC(地点)
MatePad -> PRODUCT(产品)
3999元 -> MONEY(金额)

实体标签集可以根据场景扩展,金融领域可能要识别“股票代码”、“债券期限”,医疗领域要识别“疾病名”、“药品名”。你想想看,不同的业务场景,实体类别是不一样的。

核心观点:NER 不是简单的“匹配”,而是“理解”。上下文直接影响实体的边界和类别。

我在做金融风控项目时遇到过一个问题:

“贵州茅台今日上涨3.8%,报收于2056元。”  
系统把“贵州茅台”识别为LOC+PRODUCT,但实际应该是ORG(上市公司名称)。

这就是上下文没有利用好的典型。

3.2 NER的常用方法

NER 的方法演进经历了三代:规则方法、统计方法、深度学习方法。现在主流是深度学习,但老方法在某些场景下仍然有用。

下面这张图展示了NER处理的通用流程:

命名实体识别通用流程 输入文本 预处理 分词/分句/去噪 特征提取 词向量/字符特征/上下文 模型预测 CRF/BiLSTM/Transformer 实体序列输出 B-ORG I-ORG O ... 常用实现方法 规则方法 统计方法 深度学习方法 预训练+微调

实际经验:如果你刚开始搭建NER系统,我建议先从预训练模型(比如BERT+CRF)入手,效果稳定。但如果是中小规模项目,考虑用spaCy的整串管道,省去很多特征工程的麻烦。

下面详细拆解三种方法:

3.2.1 基于规则的方法

早年间没有机器学习,就靠人工写规则。典型做法:

  • 词典匹配:准备一个实体词典,在文本里逐词匹配。缺点——新词覆盖不了。
  • 正则表达式:比如匹配电话号码、身份证号、邮箱等固定模式。
  • 句法模式:“<某机构>宣布…”、“<某人>担任…”之类的模板。

我曾经给一个合同审核系统写过300多条正则规则,识别合同甲方乙方。效果还行,但维护起来简直是噩梦。新增一种合同格式就得改规则,而且容易冲突。

适用场景:领域封闭、实体格式固定(比如邮件地址、车牌号)、冷启动阶段快速出原型。

3.2.2 统计机器学习方法

规则太僵硬,那就用统计模型。经典组合是特征工程 + 条件随机场(CRF)。

常用的特征包括:

特征类型说明示例
词特征当前词及其N-gram“华为” -> unigram;“深圳总部” -> bigram
词性标注词的语法角色“华为(NNP)”“发布(VB)”
上下文窗口前后若干位置的词前一词“在”、后一词“发布”
边界特征是否大写、是否数字、是否特定字符首字母大写 -> 人名假设
词典特征是否出现在预定义词典中“深圳”匹配地名词典

训练时用标注好的语料(格式如 CoNLL-2003),喂给CRF模型。CRF会学习相邻标签之间的转移概率,自动约束序列合法性(比如“B-ORG”后面不可能紧跟“I-PER”)。

我个人习惯在特征工程阶段先跑一个简单的baseline,看看哪些特征贡献大。否则一股脑把所有特征堆进去,模型可能会被噪音干扰。

3.2.3 深度学习方法

现在基本都用深度学习,端到端训练,不用手工特征。

主流结构就几种:

  • LSTM/GRU + CRF:双向LSTM提取序列特征,CRF做标签解码。这是2015-2019年的标配。
  • Transformer + CRF:用BERT/RoBERTa等预训练模型替换LSTM,效果大幅提升。
  • 基于Span的方法:直接预测实体的起止位置,适合嵌套实体场景(比如“北京大学”既是ORG也是LOC的子串)。

这里给一个使用spaCy训练自定义NER模型的代码片段:

import spacy
from spacy.tokens import DocBin
from spacy.training import Example

nlp = spacy.blank("zh")
ner = nlp.add_pipe("ner")

# 添加实体标签
ner.add_label("ORG")
ner.add_label("PERSON")
ner.add_label("LOC")

# 准备训练数据(示例)
TRAIN_DATA = [
    ("华为在深圳设立研发中心", {"entities": [(0,2,"ORG"), (3,5,"LOC")]}),
    ("李想担任理想汽车CEO", {"entities": [(0,2,"PERSON"), (3,8,"ORG")]})
]

# 转换训练数据
docbin = DocBin()
for text, annotations in TRAIN_DATA:
    doc = nlp.make_doc(text)
    ents = []
    for start, end, label in annotations["entities"]:
        span = doc.char_span(start, end, label=label)
        if span is not None:
            ents.append(span)
    doc.ents = ents
    docbin.add(doc)

# 训练(简化流程)
optimizer = nlp.begin_training()
for epoch in range(10):
    for batch in spacy.util.minibatch(TRAIN_DATA, size=4):
        for text, annotations in batch:
            example = Example.from_dict(nlp.make_doc(text), annotations)
            nlp.update([example], sgd=optimizer)

# 保存模型
nlp.to_disk("./my_ner_model")

避坑指南:我曾经直接用预训练BERT做NER,发现推理速度慢得离谱。后来改成用轻量级模型(比如 DistilBERT + CRF),在精度损失不到1%的情况下,速度提升了3倍。如果你的应用是实时在线服务,务必做量化或蒸馏。

3.3 NER在知识图谱中的角色

知识图谱构建的第一步就是实体抽取。有了实体节点,才能谈关系抽取和属性填充。

很多同学以为NER只要识别出实体就行,其实还有几个关键点要注意:

  • 实体消歧:“苹果”是水果还是公司?需要结合上下文或图谱上下文判断。
  • 实体链接:识别出的字符串“阿里”要映射到知识图谱中具体哪个节点(阿里巴巴集团 vs 阿里巴巴影业)。
  • 嵌套实体:“北京师范大学”中“北京”是LOC,“北京师范大学”是ORG。学术界有专门的数据集(如 ACE 2005)用来评估嵌套NER。

我在做一个企业知识图谱时,遇到了一个典型案例:

原文:“腾讯云在2018年推出了云开发平台。”
我们当时只识别出“腾讯云”作为ORG,却漏掉了“云开发平台”这个产品实体。导致的后果是后面的事件抽取全部跑偏。

关键经验:企业图谱的实体粒度要结合业务定义。有时候粗粒度(公司整体)就够了,有时候需要细粒度(子公司、事业部、产品线)。NER的标签设计应当与图谱schema对齐。

3.4 常用的评估指标

评估NER模型好坏,最常用的就是精确率(Precision)、召回率(Recall)和F1值。注意是实体级别的评估,不是词级别的。一个实体只有边界和类别完全正确才算对。

指标计算公式说明
精确率 (P)正确识别的实体数 / 模型识别的总实体数模型识别出的实体中有多少是正确的
召回率 (R)正确识别的实体数 / 真实实体总数真实实体中有多少被模型找到了
F1值2 * P * R / (P + R)综合平衡指标,通常作为主要标准

举个例子,假设真实有3个实体,模型识别出4个,但只正确识别了2个。那么P=2/4=0.5,R=2/3≈0.666,F1≈0.571。嗯,这个分数说明模型还有改进空间。

个人习惯:我一般会用$O(n^2)$的启发式匹配(比如先剔除标点,再用最长公共子序列判断边界是否一致),而不是严格的精确匹配,这样能容忍一些微小的边界偏移(比如多了一个空格)。在工业场景下,这种宽松的评估方式更接近实际可用性。

3.5 工具与资源推荐

如果你不想从零写代码,可以直接用这些开源工具:

  • spaCy:工业级NLP库,支持自定义训练,中文模型可用 zh_core_web_trf(基于Transformer)。
  • Stanford CoreNLP:经典工具包,支持多种语言,但速度一般。
  • HanLP:专注于中文的NLP工具包,内置多种NER模型。
  • Hugging Face Transformers:提供大量预训练模型,可配合pipeline做NER推理。

预训练数据集(用于基准):

  • CoNLL-2003(英文,新闻语料)
  • OntoNotes 5.0(多语言,多种实体类型)
  • MSRA NER(中文,1998年人民日报语料,免费可用)

好了,这一章的内容就到这。实体识别是整个知识图谱流水线的第一道关口,这里出问题,后面全跟着歪。所以建议你在项目早期就花时间把NER调稳,哪怕多用几种方法交叉验证也不亏。