ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于 AI-For-Beginners 课程实战命名实体识别(NER):从 BIO 标注到 LSTM/BERT 实现

2026/9/30 6:35:48 拓冰建站 浏览量
基于 AI-For-Beginners 课程实战命名实体识别(NER):从 BIO 标注到 LSTM/BERT 实现 教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载命名实体识别NER是自然语言处理中与文本分类并列的核心任务之一它需要在句子中找出人名、地名、时间、化学式、疾病名等实体并标注其类别。本指南以 AI-For-Beginners 课程19-NER一节为主线先讲清楚为什么需要 NER聊天机器人意图参数抽取与N ER 的建模方式把 NER 视为令牌分类问题并用 BIO 标注再结合课程自带的 NER-TF.ipynb 逐行拆解如何用 Keras 训练双向 LSTM 完成令牌分类最后给出基于 PubMedBERT 的医疗实体识别进阶路线。读完本文你将能够把一个原始文本数据集转换为 BIO 编码搭建并训练一个 NER 神经网络并理解如何在真实医学文献语料上落地。图为课程配图Image by the author用户话语 What is the temperature in Moscow today? 中Moscowlocation、todaydatetime、temperaturemeasurement被识别为实体并填入对应参数槽从而让聊天机器人触发 Weather 意图。图片来源 bot-ner.png。NER 为什么重要聊天机器人与意图-槽位Intent-Slot范式智能聊天机器人类似 Amazon Alexa 或 Google Assistant工作的核心方式是对用户输入句子做文本分类判断用户想干什么这个分类结果被称为intent意图它决定了机器人下一步该执行什么动作。但仅有意图是不够的。用户在表达需求时往往附带参数例如询问天气时可能指定地点或日期句子What is the temperature in Moscow today?意图Weather查询天气需要填写的参数槽地点 Moscow、时间 today、测量量 temperature机器人必须能把这些实体从句子中抽取出来并在执行动作前填入对应的参数槽parameter slots。这正是 NER 的用武之地。✅ 另一个典型场景是科学医学论文分析。在分析大量医学文献时我们需要定位疾病名、药物名、化学物质等专有医学名词。少部分疾病可以通过子串搜索substring search简单抽取但像化合物、药物名称这类复杂实体子串匹配远远不够必须依赖 NER 模型。在课程仓库中19-NER 课程的作业 正是要求用 NER 处理医疗语料——训练一个能识别疾病Disease和化学物质Chemical实体的模型。可见 NER 在真实业务中既是理解用户输入的关键环节也是从非结构化文本中提取结构化知识的核心工具。NER 的本质令牌分类Token ClassificationNER 模型本质上是一个令牌分类模型token classification model对输入的每一个 token我们需要判断它是否属于某个实体以及属于哪一类实体。以论文标题为例Tricuspid valve regurgitationandlithium carbonatetoxicityin a newborn infant.其中的实体包括Tricuspid valve regurgitation三尖瓣反流——疾病DISLithium carbonate碳酸锂——化学物质CHEMToxicity毒性——疾病DISBIOIOB标注解决跨 token 实体与相邻实体注意到两点一个实体可能跨越多个 token如 Tricuspid valve regurgitation 由三个 token 组成两个实体可能紧挨着如 lithium carbonate 与 toxicity。因此仅用一个实体类别标签无法区分实体的开头 token和实体的后续 token。课程采用业界标准的BIO tagging即 IOB 标注Inside–Outside–BeginningB-前缀beginning表示实体的第一个 token如B-DISI-前缀inner表示实体的后续/内部 token如I-DISO表示所有其他outside不属于任何实体的 token。对上述标题做 BIO 标注后每个 token 对应的标签如下TokenTagTricuspidB-DISvalveI-DISregurgitationI-DISandOlithiumB-CHEMcarbonateI-CHEMtoxicityB-DISinOaOnewbornOinfantO.O为什么用多对多的 RNN 架构令牌与类别之间是一一对应关系因此我们可以训练一个**多对多many-to-many**的循环神经网络模型。课程文档引用了 Andrej Karpathy 的经典博文The Unreasonable Effectiveness of Recurrent Neural Networks中的示意图图中最右侧的many-to-many架构即输入序列与输出序列长度一致、每个时间步都产生一个输出的结构正是 NER 令牌分类模型所对应的网络形态原文参考图。简言之输入是一个 token 序列输出是等长的 tag 序列网络在每个时间步对当前 token 做出分类决策。用 Keras 训练 NER 模型双层双向 LSTM 实战课程文档指出既然 NER 本质是令牌分类我们完全可以复用前面章节熟悉的 RNN 技术此时循环网络每个时间步block都会输出该 token 的类别 ID。课程为此提供了完整的实战 NotebookNER-TF.ipynb使用 TensorFlow/Keras 实现。1. 数据准备读取 Kaggle 实体标注语料Notebook 使用的数据集是 Kaggle 上的Annotated Corpus for Named Entity Recognition文件ner_dataset.csv需先下载到当前目录。读取并查看数据import pandas as pd from tensorflow import keras import numpy as np df pd.read_csv(ner_dataset.csv, encodingunicode-escape)数据集的典型结构如下每行一个 token按句子分组Sentence #WordPOSTagSentence: 1ThousandsNNSONaNofINONaNdemonstratorsNNSONaNhaveVBPO字段含义Sentence #为句子编号同一句内的后续行用 NaN 表示延续、Word为词、POS为词性标注、Tag为 NER 标签即我们要预测的目标。2. 构建词表与标签表课程指出为简单起见构建词表时不考虑词频而在真实项目中建议使用 Keras 的向量化器vectorizer并限制词表大小。Notebook 中的做法如下tags df.Tag.unique() # 所有 NER 标签含 B-*/I-*/O id2tag dict(enumerate(tags)) # 标签 ID - 标签名 tag2id { v : k for k,v in id2tag.items() } vocab set(df[Word].apply(lambda x: x.lower())) id2word { i1 : v for i,v in enumerate(vocab) } vocab.add(UNK) # 预留未知词占位符 word2id { v : k for k,v in id2word.items() }注意这里id2word从 1 开始编号为UNK未知词留出了位置这样测试阶段遇到词表外的词也能正常向量化。3. 按句重组从词-标签表到句子序列因为ner_dataset.csv是按行存储的需要把属于同一句的 token 聚合为句子序列X, Y [], [] s, t [], [] for i, row in df[[Sentence #, Word, Tag]].iterrows(): if pd.isna(row[Sentence #]): s.append(row[Word]) t.append(row[Tag]) else: if len(s) 0: # 上一句结束保存 X.append(s) Y.append(t) s, t [row[Word]], [row[Tag]] X.append(s) Y.append(t)随后定义两个映射函数把词序列和标签序列分别转为 ID 序列def vectorize(seq): return [word2id[x.lower()] for x in seq] def tagify(seq): return [tag2id[x] for x in seq] Xv list(map(vectorize, X)) Yv list(map(tagify, Y))4. 序列填充Padding不同句子统一长度句子长度不一需要填充到同一长度。Notebook 使用pad_sequences并指定paddingpost在序列尾部补零X_data keras.preprocessing.sequence.pad_sequences(Xv, paddingpost) Y_data keras.preprocessing.sequence.pad_sequences(Yv, paddingpost)注意Y_data的填充值同样是 0。由于后面使用sparse_categorical_crossentropy作为损失函数填充位置对应的标签 ID 0 会被计入损失——这在教学示例中是可接受的简化在正式工程中通常需要借助 mask 机制排除 padding 位置。随后maxlen X_data.shape[1] # 序列最大长度 num_tags len(tags) # 标签类别数 vocab_size len(vocab) # 词表大小5. 搭建双层双向 LSTMTimeDistributed 实现多对多这是本节最核心的代码。为了对 LSTM 每个时间步的输出都施加一个稠密分类器Keras 使用TimeDistributed包装Dense层从而把同一个全连接层复制到序列的每一步正是多对多架构的框架级实现model keras.models.Sequential([ keras.layers.Embedding(vocab_size, 300, input_lengthmaxlen), keras.layers.Bidirectional(keras.layers.LSTM(units100, activationtanh, return_sequencesTrue)), keras.layers.Bidirectional(keras.layers.LSTM(units100, activationtanh, return_sequencesTrue)), keras.layers.TimeDistributed(keras.layers.Dense(num_tags, activationsoftmax)) ]) model.compile(losssparse_categorical_crossentropy, optimizeradam, metrics[acc])要点解析对应 Notebook 中的模型概要输出Embedding 层词表大小 × 300 维的词向量输入长度固定为maxlen。从源码结构看词向量随训练一起学习两层双向 LSTM每层 100 个单元、tanh激活return_sequencesTrue保证每个时间步都输出隐藏状态这是做令牌分类的前提双向Bidirectional使模型能同时利用每个 token 的前后文信息TimeDistributed Dense对序列每一步分别做 softmax 分类输出维度为num_tags即每个 token 在所有标签上的概率分布损失函数sparse_categorical_crossentropy标签以整数 ID 给出 Adam 优化器指标为准确率。Notebook 特别提醒这里显式指定了maxlen如果希望网络支持变长序列需要在定义网络时更精细地处理例如不固定input_length并使用 mask。6. 训练与推理训练一行即可完成model.fit(X_data, Y_data)推理阶段把输入句子分词后同样走word2idpad_sequences注意要用与训练一致的maxlen再送入模型取 argmax 得到每个 token 的标签words sent.lower().split() v keras.preprocessing.sequence.pad_sequences( [[word2id[x] for x in words]], paddingpost, maxlenmaxlen) pred model.predict(v)7. 局限性为什么还要上 BERTNotebook 的结论部分给出明确指引即使是简单的 LSTM 模型在 NER 上也能得到合理的结果但要想获得显著更好的效果应使用大规模预训练语言模型如 BERT并用 Hugging Face Transformers 库对 BERT 做 NER 微调。这正是接下来课程作业的进阶方向。进阶实战基于 PubMedBERT 的医疗实体识别课程作业课程的 Lab 作业说明 要求训练一个医疗术语 NER 模型并给出了完整技术路线。数据集BC5CDR作业使用BC5CDR 数据集BioCreative V Track 3 CDR其中包含来自 1500 篇论文的疾病Disease与化学物质Chemical标注实体。数据格式如下6794356|t|Tricuspid valve regurgitation and lithium carbonate toxicity in a newborn infant. 6794356|a|A newborn with massive tricuspid regurgitation, atrial flutter, congestive heart failure, and a high serum lithium level is described. ... 6794356 0 29 Tricuspid valve regurgitation Disease D014262 6794356 34 51 lithium carbonate Chemical D016651 6794356 52 60 toxicity Disease D064420 ...数据说明见 lab/README.md前两行是论文标题|t|和摘要|a|随后每一行是一个实体论文ID 起始位置 结束位置 实体文本 实体类型 医学本体ID起止位置是相对于标题摘要整块文本的偏移量除实体类型外还给出了该实体在某个医学本体中的本体 ID如D014262。你需要自行编写 Python 代码把这种位置标注格式转换为前面介绍的BIO 编码。模型选型为什么用 PubMedBERT作业明确指出在 NLP 任务中Transformer 架构尤其是BERT 语言模型效果远好于传统 RNN。预训练 BERT 已经理解语言的通用结构可以用相对较小的数据集与计算成本微调到具体任务。由于应用场景是医疗领域使用在医学文本上训练过的 BERT是更合理的选择。Microsoft Research 发布了在 PubMed 文献库上微调得到的PubMedBERT模型社区将其托管在 Hugging Face 生态中。微调代码Hugging Face Transformers 三行起步Hugging Face Transformers 是训练 Transformer 模型的事实标准库其中包含社区维护的预训练模型库含 PubMedBERT。加载并使用的核心代码极其简洁model_name microsoft/BiomedNLP-PubMedBERT-base-uncased-abstract classes ... # number of classes: 2*entities1 tokenizer AutoTokenizer.from_pretrained(model_name) model BertForTokenClassification.from_pretrained(model_name, classes)参数说明见 lab/README.mdmodel_nameHugging Face 上的 PubMedBERT 预训练权重标识classes分类类别数其计算公式为2 * 实体类别数 1每个实体对应B-、I-两个标签再加一个O标签——这与前文 BIO 标注的类别体系完全一致tokenizer用于把输入文本切分为 token注意 BERT 使用子词subword分词与单词级分词不同因此把数据集转换为 BIO 格式时必须把 PubMedBERT 的 tokenization 纳入考量model为令牌分类任务构建的 BERT 模型输出classes个类别的分类结果。作业还建议参考一段将标注数据按 BERT 分词对齐为 BIO 格式的 Python 代码片段作为灵感。落地价值把 NER 用在 COVID 文献语料上作业的 Takeaway 部分强调这个任务非常接近你在真实场景中可能遇到的需求——从大量自然语言文本中挖掘洞见。例如可以把训练好的模型应用到 **COVID 相关论文数据集CORD-19**上识别论文中的疾病、药物、化学物质等实体再结合图分析等手段发现规律。课程的示例曾演示过对医学论文语料做实体识别后利用共现网络如实体-实体关系网络得到疾病、化学物质与治疗手段之间的关联洞察展示了 NER 在文献计量分析中的完整闭环价值。小结与自测课程文档的结论可以总结为一句NER 模型就是令牌分类模型它解决的是从文本中识别地点、人名、日期等实体这一 NLP 高频任务。掌握它需要三个层次概念层理解 BIO/IOB 标注体系、多对多 RNN 架构与令牌分类的关系工程层能够把位置式/逐词式标注数据转换为 BIO 序列用 Keras 完成填充、Embedding 双向 LSTM TimeDistributed 分类的端到端训练进阶层认识 BERT 类预训练模型尤其领域预训练模型如 PubMedBERT在 NER 上的压倒性优势掌握 Hugging Face 微调范式。课后练习19-NER 课程作业要求你先按本课方式训练 LSTM 医疗实体识别模型再改用 BERTPubMedBERT微调对比效果最后换一个不同数据集验证模型的泛化能力。推荐进一步精读 Karpathy 的The Unreasonable Effectiveness of Recurrent Neural Networks博客及其 Further Reading 部分深化对序列建模的理解。赞分享教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载相关推荐PyCaret与Google Coral边缘ML加速的终极指南PyCaret与Google Coral边缘ML加速的终极指南 PyCaret是一个开源的低代码机器学习库它极大简化了机器学习工作流程而Google CoAI for Beginners 实战用 PubMedBERT 微调医学命名实体识别NER模型AI for Beginners 实战用 PubMedBERT 微调医学命名实体识别NER模型 导读 本文对应 AI for Beginners http教程人工智能机器学习深度学习BERT-NER基于Transformer的命名实体识别完整指南BERT NER是一个基于Google BERT模型的命名实体识别工具它利用Transformer架构的双向编码能力为文本中的实体识别任务提供了强大的解决方上一篇NVIDIA NeMo-Aligner高效模型对齐的利器下一篇探索高级魔法Advanced Alchemy 开源项目推荐创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考