一文速通:命名实体识别(NER)训练方案与标注方法全解析
本文介绍了命名实体识别(NER)的三种实现方案及数据标注方法。方案一使用深度学习模型(Bert-CRF),适合数据充足的特定领域;方案二通过大模型微调(Qwen),平衡效果与成本;方案三Prompt驱动大模型(GPT-4),适合零标注成本的快速迭代。在数据标注方面,详细说明了实体类型定义、BIO/BIOES标注体系以及JSON/XML格式的处理方法。建议根据具体场景选择方案,并采用兼容大模型和深度
文章目录
最近因为业务需要,研究了一下命名实体识别,之前没见过这样的训练数据,刚开始弄的时候不知道如何下手,谨以此博客作为记录
1.命名实体识别
命名实体识别(Named Entity Recognition, NER)是一种自然语言处理(NLP)任务,旨在从文本中识别出具有特定意义的实体。
NER的目标是将文本中的这些“命名实体”提取出来,并将其分类到预定义的类别中。其核心任务可以分为两个部分:
- 识别实体:找到文本中的命名实体
- 分类实体:为识别出的实体分配类别
2. NER实现方案
方案一:训练深度学习NER模型(如Bert-CRF)
优点:
- 可控性强:模型结构和训练流程可完全自定义,适合特定领域(如医疗、金融)的定制化需求。
- 推理速度快:轻量级模型(如ALBERT、DistilBERT)在部署后推理延迟低,适合实时场景。
- 数据效率高:若标注数据质量高,即使数据量中等(千级样本)也能达到较好效果。
- 可解释性:可通过注意力权重或CRF转移矩阵分析错误原因。
缺点:
- 依赖标注数据:需要领域专家标注,成本高(尤其嵌套实体、不连续实体等复杂情况)。
- 迁移能力差:跨领域需重新标注和训练(如从新闻迁移到社交媒体文本)。
- 长尾实体效果差:低频实体或新类型实体识别性能下降。
- 超参数敏感:学习率、batch size等需调优,对工程师经验要求较高。
方案二:大模型微调(如Qwen)
优点:
- 零样本/少样本能力强:通过few-shot learning(如10个示例)即可适配新实体类型。
- 跨领域泛化好:大模型已蕴含通用语言知识,对领域术语的迁移能力优于小模型。
- 支持复杂任务:可同时处理嵌套实体、关系抽取等关联任务(通过联合标注)。
- 自动化调优:超参数敏感性低,微调时通常仅需调整学习率和epoch数。
缺点:
- 计算资源昂贵:全参数微调需GPU(如A100),LoRA等PEFT技术虽降低资源但效果略逊。
- 灾难性遗忘风险:微调可能损害大模型原有通用能力(尤其数据量较大时)。
- 输出不稳定:大模型可能生成超出标注方案的自由文本(如“北京”→“中国首都北京”)。
- 长文本处理受限:多数大模型有最大长度限制(如512/4096 tokens),长文档需滑动窗口。
方案三:Prompt驱动大模型(如GPT-4)
优点:
- 零标注成本:无需训练,直接通过prompt描述实体类型和规则(如“提取所有人名和机构”)。
- 快速迭代:修改prompt即可适配新需求(如新增“疾病”实体类型)。
- 上下文学习:支持动态示例(in-context learning),通过prompt中插入3-5个示例提升效果。
- 多语言支持:大模型天然支持跨语言NER(如中英文混合文本)。
缺点:
- 可控性差:可能遗漏实体或产生幻觉(如虚构不存在的“苹果公司CEO张三”)。
- 格式不稳定:输出可能不符合结构化要求(如JSON格式混乱),需后处理正则清洗。
- 成本随调用量线性增长:API按token计费,大规模数据成本高于本地模型。
领域知识不足:对高度专业化术语(如医学ICD-10编码)识别精度低,需复杂prompt补救。
之前的实现方式主要以机器学习、深度学习网络为主,大模型出来以后,用大模型做实体提取听说效果更好~
不过还是要具体场景具体分析,比如:
- 数据充足+领域固定 → 方案一(如医疗病历NER)
- 数据稀缺+需快速上线 → 方案三(如临时分析社交媒体突发事件)
- 平衡效果与成本 → 方案二(PEFT微调+LoRA,如金融报告NER)
可进一步通过方案三→方案二的渐进策略:先用prompt验证需求,积累伪标注数据后微调专用模型
3. 数据标注与构建
模型训练的话现成的代码和框架很多,重点还是在数据的获取和标注上,我们一起来看一下~
(1)确定实体类型
在标注之前首先要确定你所在的这个场景中涉及哪些实体类型
比如,我们要识别句子中的人物和地方,就需要定义两个实体类型:
① 人物(PERSON)
② 地方(ARE)
比如“小红和小明今天去北京饭店吃饭”,涉及的实体有:
- 小红:PERSON
- 小明:PERSON
- 北京饭店:ARE
(2)BIO或BIOES标注体系
传统的深度学习模型通常使用BIO或BIOES标注体系:
- BIO: B-实体开始,I-实体内部,O-非实体
- BIOES: 增加E(实体结束)和S(单字实体)
每个 token 都会被赋予一个标签,由两部分组成:
位置标记(B/I/O 或 B/I/E/S/O)
实体类别(PERSON / ARE)
比如:
| 字/词 | BIO 标签 |
|---|---|
| 小 | B-PERSON |
| 红 | I-PERSON |
| 和 | O |
| 小 | B-PERSON |
| 明 | I-PERSON |
| 今 | O |
| 天 | O |
| 去 | O |
| 北 | B-ARE |
| 京 | I-ARE |
| 饭 | I-ARE |
| 店 | I-ARE |
| 吃 | O |
| 饭 | O |
(3)JSON/XML格式
使用标注工具进行实体标注导出来的一般是JSON/XML格式,比如:
{
"text": "小红和小明今天去北京饭店吃饭",
"entities": [
{"start": 0, "end": 1, "label": "PERSON", "text": "小红"},
{"start": 3, "end": 4, "label": "PERSON", "text": "小明"},
{"start": 8, "end": 11, "label": "ARE", "text": "北京饭店"}
]
}
这种格式可以进行适当的后处理,处理成我们想要的训练格式
这里给大家贴一个我自己部署过的一个标注工具:doccano
(4)大模型标注格式
-
在句子中添加标签
比如 “小红和小明今天去北京饭店吃饭” 改写为 :
“< PERSON>小红< /PERSON>和< PERSON>小明</ PERSON>今天去< ARE>北京饭店</ ARE>吃饭”
这种方式的好处是能够从结果推断出实体的具体位置 -
json格式
比如 “小红和小明今天去北京饭店吃饭” 输出:
{“entity_text”: “小红”, “entity_type”: “PERSON”},
{“entity_text”: “小明”, “entity_type”: “PERSON”},
{“entity_text”: “北京饭店”, “entity_type”: “ARE”}
这种方式输出的 json 字符串可能会有重复的. 因为句子中可能会有两个一样的实体 -
实体类型 - 实体原始字符串
比如 “小红和小明今天去北京饭店吃饭” 输出:
PERSON: 小红,
PERSON: 小明,
ARE: 北京饭店
这种方式输出的实体, 每行文本以 实体类型 开始, 冒号 : 后面接实体原始字符串。如果 实体原始字符串 中有重复的, 会去重复。
个人建议是,如果要兼容大模型训练和主流的深度模型训练,可以考虑在原文本中加入标签或者使用标注工具进行标注导出来json格式这两种标注方式,进行后处理比较方便~
训练的话内容很多,暂时未整理,如果有需要的朋友可以留言~
更多推荐


所有评论(0)