人工智能之语言领域 自然语言处理 第七章 命名实体识别

人工智能之语言领域

第七章 命名实体识别


文章目录

  • 人工智能之语言领域
  • [前言 命名实体识别(NER)](#前言 命名实体识别(NER))
    • [7.1 NER任务概述](#7.1 NER任务概述)
      • [7.1.1 实体类型](#7.1.1 实体类型)
      • [7.1.2 NER的评价指标](#7.1.2 NER的评价指标)
    • [7.2 传统NER方法](#7.2 传统NER方法)
    • [7.3 深度学习NER方法](#7.3 深度学习NER方法)
      • [7.3.1 RNN+CRF模型:序列标注经典架构](#7.3.1 RNN+CRF模型:序列标注经典架构)
      • [7.3.2 BERT+CRF模型:上下文感知的实体识别](#7.3.2 BERT+CRF模型:上下文感知的实体识别)
    • [7.4 低资源与跨领域NER](#7.4 低资源与跨领域NER)
      • [7.4.1 迁移学习在NER中的应用](#7.4.1 迁移学习在NER中的应用)
      • [7.4.2 少样本NER方法](#7.4.2 少样本NER方法)
    • [7.5 实战案例:医疗领域实体(疾病、药物)识别](#7.5 实战案例:医疗领域实体(疾病、药物)识别)
    • [补充:NER 系统架构对比](#补充:NER 系统架构对比)
    • 小结
  • 资料关注

前言 命名实体识别(NER)

命名实体识别(Named Entity Recognition, NER)是自然语言处理(NLP)中一项基础而关键的信息抽取任务,其目标是从非结构化文本中自动识别并分类预定义类型的实体,如人名、地名、组织机构等。NER 是构建知识图谱、智能问答、信息检索等系统的基石。本章将系统介绍 NER 的任务定义、传统与深度学习方法、低资源场景策略,并通过医疗领域实体识别实战案例完整演示端到端流程。


7.1 NER任务概述

7.1.1 实体类型

NER 通常识别以下标准实体类型(以 CoNLL-2003中文 MSRA 数据集为例):

类型 英文缩写 示例
人名 PER 马云、爱因斯坦
地名 LOC 北京、太平洋
机构名 ORG 阿里巴巴、联合国
时间 TIME 2025年3月、昨天
数字/货币/百分比 NUM/MONEY/PCT 100元、50%

📌 中文特殊性

  • 无空格分隔,需先分词或字符级标注
  • 实体边界模糊(如"北京大学" vs "北京 大学")
  • 领域实体丰富(如医疗:"阿莫西林"、"高血压")

标注格式(BIO 标注):

  • B-:实体开始(Begin)
  • I-:实体内部(Inside)
  • O:非实体(Outside)

🌰 示例:

文本:马云 创立了 阿里巴巴

标注:B-PER O B-ORG
原始文本
分词/字符切分
BIO 标注序列
B-PER, O, B-ORG


7.1.2 NER的评价指标

NER 是序列标注任务 ,评估需考虑实体边界和类型是否完全匹配。

  • 精确率(Precision) = 正确预测的实体数 / 所有预测的实体数
  • 召回率(Recall) = 正确预测的实体数 / 所有真实实体数
  • F1值 = 2 × (Prec × Rec) / (Prec + Rec)

⚠️ 注意:

  • "马云" 被标为 "B-PER I-PER" → 正确
  • "马云" 被标为 "B-PER B-PER" → 错误(边界错)
  • "马云" 被标为 "B-ORG" → 错误(类型错)

常用工具:seqeval(专为序列标注设计)

python 复制代码
from seqeval.metrics import classification_report

y_true = [['B-PER', 'I-PER', 'O', 'B-ORG']]
y_pred = [['B-PER', 'I-PER', 'O', 'B-ORG']]

print(classification_report(y_true, y_pred))
# 输出按实体类型统计的 Precision/Recall/F1

7.2 传统NER方法

7.2.1 基于规则与词典的方法

原理:利用人工编写的规则或外部词典匹配实体。

  • 规则:正则表达式匹配日期、电话、邮箱
  • 词典:加载人名库(如公安部姓氏库)、地名库(GeoNames)
python 复制代码
import re

# 规则示例:匹配日期
text = "会议定于2025年3月10日举行"
date_pattern = r'\d{4}年\d{1,2}月\d{1,2}日'
matches = re.findall(date_pattern, text)
print("识别到日期:", matches)  # ['2025年3月10日']

✅ 优点:准确率高(对规则覆盖部分)

❌ 缺点:泛化能力差,维护成本高,无法处理未登录词


7.2.2 基于统计学习的方法:HMM、CRF

隐马尔可夫模型(HMM)
  • 将 NER 视为序列标注问题
  • 假设当前标签只依赖前一标签(马尔可夫性)
  • 使用维特比算法解码最可能标签序列
条件随机场(CRF)
  • 全局归一化,避免标签偏置问题
  • 可加入丰富特征(词形、前后缀、词性等)
  • 曾是 NER 的 SOTA 方法(2010s)
python 复制代码
# 使用 sklearn-crfsuite 实现 CRF(需先提取特征)
import sklearn_crfsuite
from sklearn_crfsuite import scorers, metrics

def word2features(sent, i):
    word = sent[i][0]
    features = {
        'word': word,
        'word.lower()': word.lower(),
        'word[-3:]': word[-3:],
        'word[-2:]': word[-2:],
        'word.isupper()': word.isupper(),
        'word.isdigit()': word.isdigit(),
    }
    if i > 0:
        features['prev_word'] = sent[i-1][0]
    else:
        features['BOS'] = True
    if i < len(sent)-1:
        features['next_word'] = sent[i+1][0]
    else:
        features['EOS'] = True
    return features

def sent2features(sent):
    return [word2features(sent, i) for i in range(len(sent))]

# 假设 train_sents 是 [(word, tag), ...] 的列表
X_train = [sent2features(s) for s in train_sents]
y_train = [sent2labels(s) for s in train_sents]

crf = sklearn_crfsuite.CRF(
    algorithm='lbfgs',
    c1=0.1,
    c2=0.1,
    max_iterations=100,
    all_possible_transitions=True
)
crf.fit(X_train, y_train)

💡 中文实践:需先分词,并将每个词作为单元输入。


7.3 深度学习NER方法

7.3.1 RNN+CRF模型:序列标注经典架构

架构流程

  1. 词嵌入(Word Embedding)
  2. 双向 LSTM 编码上下文
  3. CRF 解码器保证标签合法性(如 I-PER 不能跟在 O 后)

词序列
Embedding Layer
BiLSTM Encoder
CRF Decoder
BIO 标签序列

python 复制代码
import torch
import torch.nn as nn
from torchcrf import CRF

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

        self.word_embeds = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim // 2,
                            num_layers=1, bidirectional=True)
        self.hidden2tag = nn.Linear(hidden_dim, self.tagset_size)
        self.crf = CRF(self.tagset_size, batch_first=True)

    def forward(self, x, tags=None):
        # x: [batch, seq_len]
        embeds = self.word_embeds(x)  # [B, L, D]
        lstm_out, _ = self.lstm(embeds)  # [B, L, H]
        emissions = self.hidden2tag(lstm_out)  # [B, L, num_tags]

        if tags is not None:
            # 训练:返回 loss
            loss = -self.crf(emissions, tags, reduction='mean')
            return loss
        else:
            # 推理:返回预测标签
            return self.crf.decode(emissions)

✅ 优势:端到端训练,自动学习特征

❌ 劣势:依赖分词质量,长距离依赖有限


7.3.2 BERT+CRF模型:上下文感知的实体识别

核心思想 :用 BERT 替代 BiLSTM 作为编码器,提供上下文相关词表示

  • 输入:字符序列(中文无需分词)
  • 输出:每个 token 的向量 → 线性层 → CRF
python 复制代码
from transformers import BertModel, BertPreTrainedModel
from torchcrf import CRF

class BertCRF(BertPreTrainedModel):
    def __init__(self, config, num_labels):
        super().__init__(config)
        self.bert = BertModel(config)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        self.classifier = nn.Linear(config.hidden_size, num_labels)
        self.crf = CRF(num_labels, batch_first=True)

    def forward(self, input_ids, attention_mask=None, labels=None):
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
        sequence_output = outputs[0]  # [B, L, 768]
        sequence_output = self.dropout(sequence_output)
        logits = self.classifier(sequence_output)  # [B, L, num_labels]

        if labels is not None:
            loss = -self.crf(logits, labels, mask=attention_mask.bool(), reduction='mean')
            return loss
        else:
            decoded = self.crf.decode(logits, mask=attention_mask.bool())
            return decoded

🌐 中文推荐模型:bert-base-chinesehfl/chinese-bert-wwm-ext


7.4 低资源与跨领域NER

7.4.1 迁移学习在NER中的应用

场景:目标领域(如医疗)标注数据少,但有大量通用领域数据(如新闻)。

策略

  1. 在通用 NER 数据集(如 MSRA)上预训练模型
  2. 在医疗 NER 数据上微调
python 复制代码
# Step 1: 加载在 MSRA 上训练好的中文 BERT-NER 模型
# model = BertCRF.from_pretrained("your-msra-ner-model")

# Step 2: 在医疗数据上继续微调
# trainer.train()

✅ 效果:通常比从头训练提升 5--15% F1


7.4.2 少样本NER方法

当每类实体只有几个标注样本时:

方法 原理
Prompt-based NER 将 NER 转为填空任务(如"马云是 [MASK]" → "人名")
原型网络(Prototypical Networks) 计算 token 向量到各类原型的距离
远程监督(Distant Supervision) 用知识库(如 UMLS)自动标注

🔮 前沿方向:结合大语言模型(LLM)进行零样本/少样本 NER。


7.5 实战案例:医疗领域实体(疾病、药物)识别

任务描述

  • 输入 :电子病历或医学文献片段 "患者诊断为2型糖尿病,处方二甲双胍500mg每日两次。"
  • 输出
    • 疾病:B-DIS I-DIS I-DIS(2型糖尿病)
    • 药物:B-DRUG I-DRUG(二甲双胍)

数据集

使用公开中文医疗 NER 数据集 CMeEE(Chinese Medical Entity Extraction)。

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

python 复制代码
# Step 1: 安装依赖
# pip install transformers datasets torch seqeval torchcrf

# Step 2: 加载 CMeEE 数据(简化版)
from datasets import load_dataset
dataset = load_dataset("liushiqi/CMeEE")  # 或自行下载

# Step 3: 定义标签
label_list = ["O", "B-dis", "I-dis", "B-sym", "I-sym", "B-dru", "I-dru", ...]
label_to_id = {l: i for i, l in enumerate(label_list)}

# Step 4: Tokenize(字符级)
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("hfl/chinese-bert-wwm-ext")

def tokenize_and_align_labels(examples):
    tokenized_inputs = tokenizer(
        examples["text"],
        truncation=True,
        padding=True,
        max_length=128,
        is_split_into_words=False  # 输入为字符串
    )
    labels = []
    for i, label in enumerate(examples["labels"]):
        word_ids = tokenized_inputs.word_ids(batch_index=i)
        previous_word_idx = None
        label_ids = []
        for word_idx in word_ids:
            if word_idx is None:
                label_ids.append(-100)  # 忽略 special tokens
            elif word_idx != previous_word_idx:
                label_ids.append(label_to_id[label[word_idx]])
            else:
                label_ids.append(-100)  # 子词标签忽略
            previous_word_idx = word_idx
        labels.append(label_ids)
    tokenized_inputs["labels"] = labels
    return tokenized_inputs

tokenized_datasets = dataset.map(tokenize_and_align_labels, batched=True)

# Step 5: 加载模型(BERT+CRF)
model = BertCRF.from_pretrained("hfl/chinese-bert-wwm-ext", num_labels=len(label_list))

# Step 6: 训练(使用 Trainer)
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(
    output_dir="./medical-ner",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    num_train_epochs=5,
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    tokenizer=tokenizer,
)

trainer.train()

# Step 7: 预测与评估
from seqeval.metrics import classification_report

predictions = trainer.predict(tokenized_datasets["test"])
y_pred = [[label_list[p] for p in pred if p != -100] for pred in predictions.predictions]
y_true = [[label_list[l] for l in label if l != -100] for label in predictions.label_ids]

print(classification_report(y_true, y_pred))

预期结果

  • 疾病识别 F1:>85%
  • 药物识别 F1:>80%

💡 若无标注数据,可先用 LTPHanLP 的通用 NER 模型抽取,再人工校验。


补充:NER 系统架构对比

规则/词典
中小数据
大数据
追求SOTA
输入文本
方法选择
正则+词典匹配
CRF + 手工特征
BiLSTM-CRF
BERT-CRF
输出实体


小结

命名实体识别从早期的规则系统发展到今天的预训练语言模型,已成为 NLP 中成熟而活跃的研究方向。BERT+CRF 架构目前是工业界主流方案,尤其适合中文等复杂语言。在医疗、金融、法律等专业领域,领域自适应少样本学习 是突破数据瓶颈的关键。未来,NER 将与大语言模型知识图谱多模态理解深度融合,迈向更精准、更智能的信息抽取。


资料关注

咚咚王

《Python 编程:从入门到实践》

《利用 Python 进行数据分析》

《算法导论中文第三版》

《概率论与数理统计(第四版) (盛骤) 》

《程序员的数学》

《线性代数应该这样学第 3 版》

《微积分和数学分析引论》

《(西瓜书)周志华-机器学习》

《TensorFlow 机器学习实战指南》

《Sklearn 与 TensorFlow 机器学习实用指南》

《模式识别(第四版)》

《深度学习 deep learning》伊恩·古德费洛著 花书

《Python 深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》

《深入浅出神经网络与深度学习 +(迈克尔·尼尔森(Michael+Nielsen)》

《自然语言处理综论 第 2 版》

《Natural-Language-Processing-with-PyTorch》

《计算机视觉-算法与应用(中文版)》

《Learning OpenCV 4》

《AIGC:智能创作时代》杜雨 +&+ 张孜铭

《AIGC 原理与实践:零基础学大语言模型、扩散模型和多模态模型》

《从零构建大语言模型(中文版)》

《实战 AI 大模型》

《AI 3.0》

相关推荐
Dev7z2 小时前
面向健身与康复训练的基于深度学习的人体姿态检测与动作纠正系统
人工智能·深度学习·健身·康复训练·人体姿态检测·动作纠正系统
我材不敲代码2 小时前
计算机视觉基础——opencv的基础操作
人工智能·opencv·计算机视觉
搬砖者(视觉算法工程师)2 小时前
用直白语言讲透 Transformer
人工智能
VALENIAN瓦伦尼安教学设备2 小时前
便携式蒸汽阀门漏气检测仪作用
人工智能·嵌入式硬件·算法
成都它思科技有限公司2 小时前
语音识别错误率是多少,我们认为错误率是多少?
人工智能·语音识别
Cx330❀2 小时前
Linux ELF格式与可执行程序加载全解析:从磁盘文件到运行进程
linux·运维·服务器·人工智能·科技
杜子不疼.2 小时前
2026年AI Agent实战:从玩具到生产力的落地手册(附源码)
人工智能
科技快报2 小时前
华为发布AI数据平台,重塑数据基座,加速企业AI应用落地
大数据·人工智能·华为
智塑未来2 小时前
哪些GEO服务商有自研AI监测工具?2026年AI品牌监测平台深度对比
人工智能