经验驱动。实体识别是信息抽取的第一步,也是搜索、知识图谱、风控的底层能力。本文用本机真实跑通的 bert4ner-base-chinese 讲清楚:模型怎么抽、真实输出长什么样、有哪些坑,以及一条能从”标注”走到”上线”的完整链路。

什么是 NER

命名实体识别(Named Entity Recognition)是从文本里找出实体并给它们分类,比如人名、机构名、地名、时间。它是序列标注任务:给每个 token 打标签。

最常用两套标注体系:

  • BIO:B-实体(开头)、I-实体(中间/结尾)、O(非实体)。例如 李/B-PER 明/I-PER。
  • BIOES:在 BIO 基础上加 E(结尾)、S(单字实体),边界更精确,评估时更不容易歧义。

中文 NER 比英文难在:没有空格分词,实体边界要靠模型自己学;还有大量未登录词(新公司名、英文名实体)。

真跑:用 bert4ner 抽实体

bert4ner-base-chinese 是基于 bert-base-chinese 的中文 NER 模型,标签体系是 B/I-PER、B/I-ORG、B/I-LOC、B/I-TIME、O。本机推理代码:

1
2
3
4
5
6
7
from transformers import pipeline
ner = pipeline("token-classification",
model="./models/bert4ner-base-chinese",
tokenizer="./models/bert4ner-base-chinese",
aggregation_strategy="simple")
text = "李明在北京大学参观了腾讯公司的总部。"
print(ner(text))

aggregation_strategy="simple" 会把同一个实体的子词自动合并成一个 span。

真实输出(本机,原样,含置信度)

1
2
3
4
5
6
7
8
9
10
11
SENT: 李明在北京大学参观了腾讯公司的总部。
ENTS: [('李 明', 'PER', 1.0), ('北 京 大 学', 'ORG', 0.997), ('腾 讯 公 司', 'ORG', 0.999)]

SENT: 阿里巴巴集团位于杭州,创始人是马云。
ENTS: [('阿 里 巴 巴 集 团', 'ORG', 0.999), ('杭 州', 'LOC', 0.999), ('马 云', 'PER', 0.999)]

SENT: 2023年世界杯在卡塔尔举行,梅西带领阿根廷队夺冠。
ENTS: [('2023 年', 'TIME', 0.824), ('卡 塔 尔', 'LOC', 0.991), ('梅 西', 'PER', 0.998), ('阿 根 廷 队', 'ORG', 0.997)]

SENT: 上海市政府与特斯拉合作建设超级工厂。
ENTS: [('上 海 市 政 府', 'ORG', 0.995)]

真实踩坑(这些才是面试能讲的东西)

1. “北京大学”被标成 ORG 而不是 LOC。

按常识北大是地点,但模型给的是 ORG(0.997)。原因:训练数据里”大学/学院/医院”这类常被标注为机构,模型学到了”机构优先”。上线的教训:实体类型定义要和你的业务一致,必要时在自有数据上继续微调,别直接信通用模型的类型划分。

2. TIME 置信度明显偏低(0.824)。

“2023年”被识别为 TIME 但置信度只有 0.824,远低于其他实体的 0.99。时间表达式变化多(”去年””下周三””2023年Q3”),模型泛化弱。上线的教训:时间类实体要单独补规则或词典(正则 + 候选日历)兜底,不能只靠模型。

3. “特斯拉”被漏召回。

第四句只抽出”上海市政府”,**”特斯拉”完全没识别,更别说”超级工厂”。这是未登录词 + 英文实体的典型失效。上线的教训:对产品名、英文名实体要做词典/别名词典增强,或接入一个实体链接(entity linking)环节。**

4. 输出带空格分词(”李 明”)。

BERT 中文是按字切的,聚合后字段里带空格,要后处理拼回原词、并和原文 offset 对齐,否则展示会错位。

从标注到上线的完整链路

  1. 定标注规范:选 BIO 还是 BIOES;定实体类型(PER/ORG/LOC/TIME/…),写标注指南,避免”北大算机构还是地点”这类歧义。
  2. 标数据:小样本用 doccano 等工具标注;中文可用 CLUENER、MSRA 等公开语料冷启动。
  3. 训练:用 transformers 的 Trainer + AutoModelForTokenClassification,num_labels 按标签数设,loss 用默认的 cross-entropy(序列标注通常不上 CRF 也能work,bge/bert4ner 都是直接 softmax)。
  4. 评估:必须用 entity-level(span 级)指标,不是 token-level。用 seqeval 直接算实体级别的 P/R/F1,因为它要求类型和边界都对齐才算对。
  5. 服务化:用 FastAPI 包成 /ner 接口,输入文本、输出实体列表;加后处理(拼接子词、过滤置信度 < 阈值、按类型分组)。
  6. 兜底增强:时间/数字用正则,产品名/英文名用语义词典,低置信实体走人工复核队列。

面试常考点

  • BIO vs BIOES:BIOES 边界更清晰,评估更稳;BIO 标注成本低。
  • 为什么评估用 entity-level:token-level 会让”标错一个字但整体对”被惩罚过重,且无法反映真实抽取质量;seqeval 是标准做法。
  • 序列标注 vs span-based(如 SpanBERT):序列标注简单成熟;span-based 直接预测片段,长实体更友好但计算量大。
  • CRF 还有没有必要:现代预训练模型 + softmax 往往够用,CRF 在标签强约束场景(如嵌套实体)仍有价值。

小结

NER 不是一个 pipeline 调用就结束的活。本机真跑让我看清了通用模型的三个真实短板(类型偏差、时间弱、未登录词漏召),这些恰恰是决定它能不能上线的关键。标注规范 + 实体级评估 + 兜底增强,才是从 demo 到生产的差距。