Skip to content

Latest commit

 

History

History
319 lines (254 loc) · 23.5 KB

File metadata and controls

319 lines (254 loc) · 23.5 KB

第一节 命名实体识别概要

一、命名实体识别简介

在上一章节中,我们学习了如何对整个文本进行分类,这是一种对文本的宏观理解。现在,我们将从宏观走向微观,深入文本内部,学习如何精准识别出句子中的人名、地名等具有特定意义的词语或短语,这就是理论部分多次提到的 命名实体识别 (Named Entity Recognition, NER)。作为信息抽取、知识图谱构建、智能问答等众多高级应用的 关键环节,NER的目标是从非结构化文本中,精准地定位并分类出业务所关心的实体对象。

1.1 什么是命名实体?

简单来说,命名实体就是现实世界中事物的名称,是文本中那些指向特定对象、具有可识别性和唯一性的词语或短语。NER 的任务就是将这些“名字”找出来,并贴上预先定义好的标签。

常见的实体类型包括:

  • 人名 (PER): 姚明, 雷军
  • 地名 (LOC): 北京, 故宫
  • 组织机构名 (ORG): 阿里巴巴, 英伟达
  • 产品名 (PROD): 黑神话:悟空, Blackwell 芯片
  • 作品名 (WORK): 三体, 流浪地球
  • 其他/杂项 (MISC): 含义依数据集而异(如民族、语言、事件等)
  • 时间 (TIME): 昨天, 2025年

一个词是否被视为实体,以及它属于哪种实体,完全由业务场景的需求来决定。例如,在通用的场景下,“苹果”可能只是一个水果;但在数码产品的讨论中,它很可能需要被识别为一个“组织机构名”或“品牌名”。

不同数据集的实体类型定义差异较大(如 CoNLL 2003 仅含 PER/ORG/LOC/MISC;OntoNotes 5 则包含 PERSON、GPE、ORG、FAC、PRODUCT、EVENT、WORK_OF_ART 等更细类别)。实际项目应先明确标签集合。

1.2 NER 的应用价值

如果说 文本分类 是让计算机理解一段话的 主旨大意(比如判断情感是积极还是消极),那么 NER 就是让它更进一步,学会从文本中**“抓住重点”**,精准地找出谁(Who)、在哪(Where)、做了什么(What)等关键信息。它使得机器能够“抓住”文本中的关键信息,是许多更高级NLP任务的基础:

  • 知识图谱构建: 从海量文本中抽取出实体及其关系,是构建知识图谱的第一步。
  • 信息抽取: 帮助机器从无结构的文本中,整理出结构化的信息。
  • 搜索引擎优化: 通过识别查询中的实体,提供更精准、更结构化的搜索结果。
  • 智能问答/对话系统: 理解用户意图,从用户的提问中抽取出关键实体,给出准确回答。

以医疗领域为例,NER可以从电子病历、医学文献等海量文本中,像专业医生一样抽取出关键信息,例如:

  • 疾病诊断: "II型糖尿病"
  • 症状描述: "多饮", "多食"
  • 检查方式: "血糖检测"
  • 治疗方案: "二甲双胍口服"

通过这些抽取出的实体,可以高效地构建医疗知识图谱,为辅助诊断系统、临床研究等提供强大的数据支持。

二、命名实体识别的应用场景

2.1 智能搜索

每当你在搜索引擎中输入问题并立即得到结构化的“知识卡片”时,背后就有 NER 技术在默默工作。一个典型的流程如下:

  1. 用户输入 Query:例如,“姚明的身高是多少?”。
  2. Query 理解:后台对 Query 进行一系列处理,尝试“读懂”用户的真实意图。
    • 基础处理:分词、词性标注、纠错等。
    • 深度理解
      • 意图识别:首先判断 Query 属于哪种意图,例如“属性查询”、“汇率转换”、“单位换算”等。
      • 命名实体识别:根据识别出的意图,有针对性地抽取相应的实体。
        • 属性查询 ("姚明的身高是多少?"):抽取“主体”(姚明)和“属性类型”(身高)。
        • 汇率转换 ("50欧元等于多少日元"):抽取“源汇率金额”(50)、“源汇率类型”(欧元)、“目标汇率类型”(日元)。
        • 单位换算 ("5英尺等于多少厘米"):抽取“源度量值”(5)、“源单位”(英尺)、“目标单位”(厘米)。
  3. 信息检索:根据理解结果,从庞大的知识图谱或索引库中精准匹配答案。
  4. 结果排序与呈现:将最相关的结果排序后,以结构化的方式优先呈现给用户。

2.2 聊天机器人与智能辅助诊断

在金融、医疗等特定领域的对话系统中,NER 同样扮演着重要角色。

  • 智能客服:在电商场景下,用户可能会用多种方式咨询同一个问题,例如:
    • "我的快递到哪了?"
    • "查一下我的订单"
    • "我买的东西发货了吗?" 系统无需理解每句话的细微差别,只需通过NER准确识别出用户的核心意图实体“物流信息”,结合用户信息,即可调用订单查询服务,返回最新的物流状态。
  • 智能辅助诊断系统:这是一个多技术融合场景。
    • 计算机视觉(CV): 负责处理CT、B超等影像图片,进行病灶识别。
    • 自然语言处理(NLP): 医生输入病人的文本描述(查体信息),NLP 模块进行处理:
      1. NER: 从文本中抽取症状既往病史等实体。
      2. 关系抽取/查询: 结合知识库进行推理,辅助医生决策:
        • [症状 A, 症状 B] => 建议检查 [项目 X]
        • [项目 X 的结果] => 得出 [结论 Y]
        • [症状 A, 症状 B, 结论 Y] => 高概率诊断 [疾病 Z]
        • [疾病 Z, 既往病史 P] => 推荐 [疗法 Q]

三、NER的数据标注

与大多数深度学习任务一样,NER 模型也需要“吃”大量的数据才能学到知识。

3.1 标注的重要性

数据质量在很大程度上决定了模型性能的上限。标注的过程,本质上就是人类在手把手地“教”模型:在给定的文本中,哪些词或短语是什么类型的实体。一份高质量的标注数据集是训练出优秀模型的前提。

3.2 标注方法

  • 人工标注:
    • 优点: 质量高,可靠。
    • 缺点: 成本高,耗时长,是典型的人力密集型工作。
    • 工具: 可以使用简单的Excel,也可以开发专门的前端标注平台来提高效率。
  • 大语言模型辅助标注:
    • 流程: 先使用LLM对数据进行预标注,然后由人工进行校对和修正。
    • 优点: 可以显著提高标注效率,将人的角色从“从零创造”变为“审核修正”。
    • 缺点: LLM的输出质量不稳定,仍需人工审核以保证数据质量。
  • 半监督/迭代式标注:
    • 流程:
      1. 先人工标注一小部分数据,训练一个“学生”模型。
      2. 用这个“学生”模型去预测大量未标注的数据。
      3. 人工检查和修正模型的预测结果(通常比从零标注快得多)。
      4. 将修正后的数据加入训练集,训练出更强的“学生”模型。
      5. 重复以上过程,不断迭代优化。

四、命名实体识别的实现方法

实现命名实体识别的技术路径多种多样,从简单高效的规则匹配到复杂强大的深度学习模型。选择哪种方法,往往需要在项目初期的效果、成本和开发周期之间做出权衡。下面我们来探讨几种主流的实现方案。

4.1 方法一:基于字典和规则匹配

这是最传统和简单的方法。通过维护一个包含各种实体词汇的字典(例如,一个巨大的地名词典),然后在文本中进行字符串匹配。

  • 优点: 实现简单、速度快,对于特定、封闭领域的实体,准确率可能很高。
  • 缺点: 泛化能力差,无法识别字典外的新词(新出现的人名、公司名等);规则的维护成本极高。

4.2 方法二:序列标注模型

目前常见的 NER 实现方式1。它将 NER 任务转化为了一个 序列标注 问题——即为文本序列中的每一个 token(通常是字或词)打上一个预定义的标签。

4.2.1 方案一:Token 级别标签预测 (BMES/BIO)

这种方法为每个 Token 预测其在实体中扮演的角色,是序列标注最经典的思想。

  • 标注体系:
    • BMES: B(Begin), M(Middle), E(End), S(Single)
    • BIO: B(Begin), I(Inside), O(Outside)
  • 示例:
    • 文本 (x): 西 安 的 大 雁 塔 门 票 多 少 钱
    • BMES 体系 (y): B-LOC E-LOC O B-LOC M-LOC E-LOC B-ATTR E-ATTR O O O
    • BIO 体系 (y): B-LOC I-LOC O B-LOC I-LOC I-LOC B-ATTR I-ATTR O O O

    上例中,LOC 代表“地点”(Location),如“西安”和“大雁塔”;ATTR 代表“属性”(Attribute),此处指“门票”。

  • 模型结构: Token Embedding层 -> 序列模型层 -> Token分类层
    • Token Embedding/Encoder 表示: 可以是静态的 nn.Embedding;更常见的是直接使用预训练 Encoder(如 BERT/RoBERTa/DeBERTa 等)的上下文表示。
    • Token Classify:
      • Softmax: 对每个Token独立分类,类别总数为 1 (非实体) + 实体类别数 * 4 (以BMES为例)。
      • CRF: 在 Softmax 基础上,额外学习标签之间的转移概率(如 B-LOC 后更可能是 M-LOC),对整个序列进行全局最优解码。对 RNN/CNN 等编码器通常有效;但在强大的预训练 Encoder(如 BERT)上收益在不少数据集上已变小,是否采用以实验为准。
  • 缺点: 无法解决实体嵌套问题。例如,对于文本“他就读于北京大学”,这种方法很难同时识别出“北京”(地名)和“北京大学”(组织机构名)这两个存在包含关系的实体。一个更理想的嵌套实体示例如下:
    {
        "token": ["", "", "", "", "", "", "", ""],
        "span": [
            {"type": "LOC", "start": 4, "end": 5},
            {"type": "ORG", "start": 4, "end": 7}
        ]
    }

4.2.2 方案二:指针网络与片段网络

这类方法主要是为了解决实体嵌套问题,是当前处理复杂 NER 场景的主流方案之一。

  • 片段网络23:
    • 思路: “暴力美学”——枚举出文本中所有可能的连续片段,然后用一个分类器去判断每一个片段属于哪个实体类型(或是“非实体”)。
    • 示例: 对于文本 “美式咖啡”,片段网络会进行如下操作:
      1. 枚举所有候选片段:
        • 长度为 1: , , ,
        • 长度为 2: 美式, 式咖, 咖啡
        • 长度为 3: 美式咖, 式咖啡
        • 长度为 4: 美式咖啡
      2. 对每个片段进行分类:
        • 美式 -> PROD
        • 咖啡 -> PROD
        • 美式咖啡 -> PROD
        • (所有其他片段) -> O (非实体)
    • 优点: 理论上可以解决实体嵌套问题。
    • 缺点:
      1. 计算量大: 候选片段数量随文本长度平方级增长(如上例,4个字的文本就产生了10个候选片段)。
      2. 样本不均衡: 绝大多数片段都是非实体,导致正负样本严重失衡,训练困难。
  • 指针网络4:
    • 思路: 与其为每个 token 打一个固定的 BMES 标签,指针网络的思想是为每个 token 训练多个独立的二分类器,分别判断它是否是“某类实体的开头”以及“某类实体的结尾”。这种方式非常适合作为生成候选片段的第一步。
    • 示例: 对于句子 “来一杯星巴克的美式咖啡”,如果我们想同时识别出“星巴克”(机构名)以及嵌套的“美式”、“咖啡”、“美式咖啡”(产品名),指针网络的输出会是这样:
      Token is_ORG_start is_ORG_end is_PROD_start is_PROD_end ...
      0 0 0 0 ...
      0 0 0 0 ...
      0 0 0 0 ...
      1 0 0 0 ...
      0 0 0 0 ...
      0 1 0 0 ...
      0 0 0 0 ...
      0 0 1 0 ...
      0 0 0 1 ...
      0 0 1 0 ...
      0 0 0 1 ...
    • 候选生成: 得到预测后,后处理程序会按实体类型分别进行“开头-结尾”配对:
      • ORG 类型: (start) + (end) => 星巴克
      • PROD 类型:
        • (start) + (end) => 美式
        • (start) + (end) => 咖啡
        • (start) + (end) => 美式咖啡

    通过这种“判断边界,再组合配对”的方式,指针网络巧妙地生成了所有可能的实体片段(包括嵌套的),为后续的分类环节提供了高质量的候选。

  • 指针网络 + 片段网络5:
    • 思路: 结合两者的长处,形成一个高效的两阶段流程。
    1. 候选生成 (指针网络): 先使用指针网络高效地预测出所有可能的实体“开头”和“结尾”。
    2. 候选组合: 将所有合法的“开头-结尾”配对,组合成候选实体片段。这个过程极大地减少了候选片段的数量,过滤掉了绝大多数无意义的组合。
    3. 候选分类 (片段网络): 再使用片段网络对这些数量大大减少的 候选片段 进行分类。
    • 优点: 既能解决嵌套问题,又有效降低了计算量,是解决复杂 NER 问题的有效方案。

4.2.3 方案三:基于分词的分类

  • 思路: 将 NER 任务分解为两步:先调用一个现成的分词模型将文本切分成词语,然后对每个 词语 进行分类。
  • 示例:
    • 原始文本: 西安的大雁塔门票多少钱
    • 分词结果: 西安, , 大雁塔, 门票, 多少,
    • 分类结果: LOC, O, LOC, ATTR, O, O
  • 缺点: 效果高度依赖上游分词模型的质量。如果分词出错(例如,将“大雁塔”错分成“大雁”和“塔”),实体识别基本不可能正确,可谓“一步错,步步错”。

4.3 方法三:生成式模型

随着大语言模型的发展,也可以将 NER 任务统一到生成框架下,通过精心设计的 Prompt 来“指令”模型完成任务。

  • 思路: 将原始文本作为输入的一部分,让模型直接生成包含实体信息的结构化文本。
  • 实现方式: 核心思路是通过设计不同的输入输出格式(Prompt 工程),将 NER 任务转化为一个序列到序列(Seq2Seq)的生成任务。
    • 方式一:标准 Encoder-Decoder 模式
      • 思路: 将原始文本喂给 Encoder,然后训练 Decoder 生成格式化的实体字符串。
      • 训练细节:
        • Encoder 输入 (x): 西安的大雁塔门票多少钱
        • Decoder 输入 (y_in): [START] 地点实体:西安[SEP]大雁塔[SEP];属性实体:门票
        • Decoder 目标 (y_out): 地点实体:西安[SEP]大雁塔[SEP];属性实体:门票 [END]
    • 方式二:带“实体清单”提示的 Encoder-Decoder
      • 思路: 在原始文本后附加上下文提示(Context Prompting),明确告知模型需要关注哪些实体类型,以约束模型的输出空间,提高准确性。
      • Encoder 输入 (x): 西安的大雁塔门票多少钱 | 可选实体列表为:[地点实体, 属性实体, ...]
      • Decoder 目标 (y_out): 地点实体:西安[SEP]大雁塔[SEP];属性实体:门票 [END]
    • 方式三:续写式生成 (Decoder-Only)
      • 思路: 将输入和输出拼接成一个完整的字符串,训练一个 GPT 风格的自回归模型来“续写”出实体部分。
      • 统一输入输出: 西安的大雁塔门票多少钱 | 可选实体列表为:[地点实体, 属性实体, ...] | 地点实体:西安[SEP]大雁塔[SEP];属性实体:门票 [END]
      • 训练: 将整段文本作为模型的输入进行训练,但 只计算 模型在预测“|”符号之后内容时的损失。前面的部分作为已知上下文,不计入损失。
      • 推理: 只提供前半部分(... | 之前的内容),让模型续写出后面的实体。
  • 优缺点:
    • 优点:
      • 统一的生成框架: 将实体抽取任务完全转化为一个“文本到文本”的任务,单个模型就能直接生成包含复杂结构(如实体嵌套)的结果,输出形式非常灵活。
      • Few-shot/Zero-shot: 强大的LLMs能极大减少数据标注成本,在很多场景下无需训练就能获得不错的效果。
    • 缺点:
      • 输出不稳定: 结果格式可能不统一,需要额外的后处理逻辑来解析。
      • 幻觉问题: 可能生成文本中不存在的实体。

五、项目实现思路

在第七章中,我们已经学习并实践了文本分类任务,并了解了 NLP 项目的通用流程。命名实体识别作为另一项 NLP 任务,其项目实现思路在宏观上遵循着相同的流程。在深入探讨具体代码实现之前,本章将再次遵循 数据处理 -> 模型构建 -> 训练、评估与持久化 这套标准流程,勾勒出一个标准 NER 项目的实现思路。

5.1 数据处理与增强

作为模型训练的起点,数据质量在很大程度上决定了模型性能的上限。

  • 主要流程:

    1. 分词/分Token: 将原始文本切分为Token序列。
    2. Token与ID映射: 构建词表,将每个Token映射为一个唯一的数字ID。
    3. 标签与ID映射: 构建标签表,将B-LOC, I-LOC等标签也映射为唯一的数字ID。
  • 数据增强: 在标注数据有限的情况下,可以通过代码“创造”一些新的、合理的数据,以提升模型的泛化能力和鲁棒性。

    • 实体替换: 准备同类型实体的词典(如地名词典、时间词典、天气现象词典),随机替换原始文本中的实体。
      • 示例: “查一下北京明天会下雨吗” -> “查一下深圳明天会下雨吗”
      • 说明: 这种方式能教会模型学习 上下文语境,而不是死记硬背具体的实体词。
    • 引入噪声: 模拟真实输入数据中的错误,随机地对文本进行微小改动。
      • 示例: “查一下北京明天会下雨吗” -> “查一下北京明天汇下雨吗” (同音字替换)。
    • 随机遮盖:
      • 方法: 在训练时,随机地将文本中的一小部分(非实体)词元替换为<UNK>(未知)标记。
      • 示例: “查一下北京明天会下雨吗” -> “查一下北京<UNK>天会下雨吗”
      • 目的: 这种方式会强制模型在部分信息缺失的情况下,更多地依赖上下文来做出判断,从而有效降低过拟合风险,提升模型的泛化能力。
    • 拼音替换: 将少量中文词替换为拼音,模拟弱规范输入。
      • 示例: “查一下北京明天会下雨吗” -> “cha yi xia bei jing ming tian hui xia yu ma”

在医疗等强约束领域做“实体替换”时,应确保替换后的样本不破坏实体间的真实语义关系(如疾病-症状-药物的搭配约束),否则可能引入反效果。

5.2 模型构建与迁移学习

  • 经典组合: Embedding层 + 动态词向量编码器 (如BERT, Bi-LSTM等) + Token分类层 (如全连接层+Softmax/CRF)

  • 输入与输出:

    • 模型输入: 形状通常为 [N, T] 的Tensor,其中N是批次大小 (Batch Size),T是序列长度 (Sequence Length),内容是Token ID。
    • 模型输出: 形状为 [N, T, num_classes] 的Tensor,代表每个Token在所有 num_classes 个类别上的置信度得分。
  • 迁移学习与微调: 在实践中,通常使用在通用领域预训练好的模型(如BERT)作为初始化参数,然后进行微调。

    • 策略一:冻结参数
      • 将迁移过来的预训练模型参数冻结 (requires_grad = False),只训练自己新增的分类层。速度快,但效果可能受限。
    • 策略二:同等处理
      • 将迁移过来的参数和新增的参数视为一体,使用相同的学习率和更新逻辑进行训练。
    • 策略三:差分学习率微调
      • 为迁移过来的参数设置一个非常小的学习率,进行“微调”,使其在保留通用知识的基础上,向新任务的领域知识“稍稍靠近”;同时为新增的、随机初始化的参数设置一个正常的学习率,使其能快速收敛。
    • 策略四:分层冻结 / 部分冻结
      • 例如仅冻结 BERT 的前若干层,让后几层与分类头共同更新;在算力有限或数据较少时,常是较好的折中。

5.3 训练、评估与持久化

这是连接数据和模型,产出最终模型的重要循环。

  • 训练循环: 迭代train_dataloader,在每个批次上执行模型前向传播、计算损失、反向传播和参数更新。
  • 评估循环与指标:
    • 迭代eval_dataloader,计算模型在验证集上的性能。
    • Token级别指标: 计算Token分类的准确率、F1值等,用于监控训练过程。
    • 实体级别指标 (核心): 计算实体片段的精确率 (Precision)、召回率 (Recall) 和 F1值。这是衡量模型最终效果的核心标准。
  • 标签序列 -> 实体片段 解码要点(以 BMES/BIO 为例):
    1. 从左到右扫描标签序列,遇到 B-T 开始一个新片段(类型 T)。
    2. 在 BMES 中,M-T 继续片段,E-T 结束片段;S-T 表示单字实体;O 表示非实体。
    3. 在 BIO 中,I-T 继续片段,遇到类型不一致或 O 时关闭当前片段。
    4. 记录每个片段的 (start, end, type) 边界与类型,用于与标注集对齐计算 P/R/F1。
  • 持久化: 在评估过程中,根据 实体级别 的评估指标结果(如验证集F1值达到新高),决定是否将当前模型的参数保存到磁盘。

参考文献

Footnotes

  1. [Lample, G., Ballesteros, M., Subramanian, S., Kawakami, K., & Dyer, C. (2016). Neural Architectures for Named Entity Recognition.] (https://arxiv.org/abs/1603.01360)

  2. [Sohrab, M. G., & Miwa, M. (2018). Deep Exhaustive Model for Nested Named Entity Recognition.] (https://arxiv.org/abs/1810.12148)

  3. [Eberts, M., & Ulges, A. (2019). Span-based Joint Entity and Relation Extraction with Transformer Pre-training (SpERT).] (https://arxiv.org/abs/1909.07755)

  4. [Vinyals, O., Fortunato, M., & Jaitly, N. (2015). Pointer Networks.] (https://arxiv.org/abs/1506.03134)

  5. [Shen, Y., Ma, X., Tan, Z., Zhang, S., Wang, W., & Lu, W. (2021). Locate and Label: A Two-stage Identifier for Nested Named Entity Recognition.] (https://arxiv.org/abs/2105.06804)