医疗命名实体识别代码解读

发布于 2024-09-13  89 次阅读


这是一篇私人文章,用来解读徐凤娇学姐的医疗命名实体识别代码。

 

CBMA文件夹

里面有bam.py , cbam.py , model_resnet.py三个文件,是CNNradical.py的import CBAM需要的一个额外包。但据学姐所说后面这东西效果不好,没有使用了

data文件夹

bert文件夹

这个文件夹里存的是google发布的bert_base_chinese模型,是一个基于中文文本的预训练模型,直接导入使用的

dataset文件夹

放的是数据集,只有NER是本次实验的数据集,其他的是原LEBERT模型自带的。NER文件里有chip,cck,resume数据集。

embedding文件夹

最重量级的文件夹,里面放了21G大小的embedding.txt文件

log文件夹

用来存放tensorboard日志文件,还有一个label_result文件夹,用来存放在验证集和测试集上的结果(包括准确率,召回率和f1值)

result文件夹

用来存放验证集和测试集的预测标签的结果。还有一个best_model用来存放模型

feature文件夹

task_dataset.py

该文件 `task_dataset.py` 是一个 PyTorch 数据集类,用于处理和加载特定格式的数据。以下是对文件内容的详细解读:该文件主要用于定义一个自定义的数据集类 `TaskDataset`,它可以从指定的文件加载数据,并进行必要的预处理,以便在模型训练中使用。

 主要组成部分

1. 导入模块
– 导入了必要的库,如 `os`, `json`, `random`, `torch`, `numpy` 等。
– 从 `function.preprocess` 导入了 `sent_to_matched_words_boundaries` 函数,用于处理文本数据。

2. 类 `TaskDataset`
– 继承自 `torch.utils.data.Dataset`,允许该类与 PyTorch 的数据加载器兼容。

3. 构造函数 `__init__`
– 接受文件路径 `file` 和一些参数 `params`。
– 初始化一些属性,如最大单词数、tokenizer、词汇表、标签等。
– 根据给定的参数构建一个保存的 NumPy 文件路径,尝试加载已存在的 NumPy 数据集以提高读取速度。

4. 数据集初始化 `init_np_dataset`
– 检查是否存在预处理后的 NumPy 文件:
– 如果存在,直接加载数据。
– 如果不存在,读取原始文件,进行数据预处理,包括:
– 文本和标签的截断。
– 使用 tokenizer 转换文本为 ID。
– 生成必要的数组(输入 ID、段 ID、注意力掩码、匹配单词 ID 等)。
– 该过程还会将处理后的数据保存为 NumPy 格式,供后续使用。

5. 方法 `__len__` 和 `__getitem__`
– `__len__` 方法返回数据集的大小。
– `__getitem__` 方法根据给定索引返回相应的数据项,数据项以张量形式返回,方便模型训练。

6. 辅助函数 `get_head_tail_label`
– 用于从标签中提取头部和尾部信息,返回两个列表指示每个标签是头部还是尾部。

该文件的作用是提供一个高效的数据加载和预处理机制,支持从 JSON 文件中读取数据,进行必要的预处理,并支持 PyTorch 数据加载器的使用。通过将处理后的数据保存为 NumPy 格式,可以显著提高数据加载速度,适用于需要频繁读取相同数据的训练过程。

vacab.py

是一个用于构建和管理词汇表的 Python 模块,主要用于将词或标签映射到对应的 ID,以及反向映射。

BIO2BIOES.py文件:

这个脚本实现了BIO格式转BMES格式的功能:

– BIO2BMES函数实现了具体的转换逻辑:
– 读取BIO格式文件每行词汇和标签
– 根据标签类型(B、I等)判断词汇属于开始、中间、结束等状态
– 输出对应的BMES格式标签

– Trans函数实现了保留换行不进行转换的功能:
– 读取原文件每行
– 如果是换行,直接写入结果文件
– 否则进行词汇标签提取,并写入结果文件

主要流程是:

1. 读取BIO格式输入文件每行
2. 提取词汇和标签
3. 根据标签类型判断词汇在实体中的位置(开始、中间、结束)
4. 输出对应的BMES格式标签替换原标签
5. 添加换行输出到结果文件

它实现了BIO转BMES的核心逻辑,同时支持不对换行进行转换,方便针对不同格式文件的处理。

整体实现清晰,功能完整,可以很好地实现NER标注文件的格式转换工作。

conlleval.py

这个conlleval.py文件实现了命名体识别(NER)模型评估的功能。

整体流程为:

1. 解析模型预测结果和ground truth文件,提取标签信息。

2. 对预测结果和ground truth进行対比,统计 true positive、false positive、false negative 等数值。

3. 根据这些指标计算常用的NER指标 Precision、Recall、F1 score。

4. 给出整体和每个类型的评估指标结果。

具体模块功能:

– evaluate():主要对比函数,遍历文件对预测结果和ground truth进行匹配,记录指标数据。

– metrics():根据记录的指标数据计算Precision、Recall、F1等指标。

– report():输出评估结果,包括整体和每个类型的指标 numerically 和文本描述形式。

– report_notprint():只返回结果不输出,用于其他处理。

– utils函数:解析输入文件、计算指标、统计类型等工具函数。

所以这个py文件实现了NER模型常见的CoNLL格式评估任务,可以对模型在测试集上进行自动化评估,并给出每个类型和整体的评价指标,是NER模型开发和比较的重要工具。

data_transfer.py

这个python文件主要目的是将不同来源和格式的命名实体识别数据集,转换为统一的数据格式。

总体来说,这个py文件主要完成以下工作:

1. 将不同来源的数据集,如人民日报数据集、微软数据集等,转换为项目统一数据格式。

2. 处理不同标注样式的数据集,如BIO、BMES等标注转换为统一样式。

3. 提取标注文本中的实体信息,生成标准数据结构。

4. 输出转换后的数据集到指定文件。

5. 统计转换数据集中实体类型和数量。

主要模块功能:

1. transfer_dataX函数:实现不同数据集的转换,处理不同来源和格式的数据集。

2. 分词、词性标注、实体提取:处理原始文本,识别并提取句子和实体信息。

3. 实体类型统一:如地址->地址实体等给实体类型赋予统一命名。

4. 输出:将转换后数据按行写入文件。

5. 统计:统计转换数据集中实体类型和数量。

通过这个py文件,可以方便地对不同格式和来源的NER数据集进行预处理,输出到统一格式的文件中,为后续模型训练和测试提供便利。它实现了NER不同数据集的自动转换处理。

demo.py

这个Python文件主要实现了基于Transformer的自注意力机制模型。

总体来说,这个py文件完成以下工作:

1. 定义了Star-Transformer网络中的编码器层结构StarEncoderLayer,实现了星型结构中的节点更新。

2. 实现了位置编码PositionalEncoding,为模型输入文本添加位置信息。

3. 实现基于self-attention计算注意力权重的网络层Self_Attention。

4. 使用正弦位置编码实现了内置式位置编码。

各个模块功能:

1. StarEncoderLayer:定义星型Transformer编码器层,实现卫星节点和中继节点的更新。

2. PositionalEncoding:为模型输入添加位置编码,注入位置信息。

3. Self_Attention:采用查询 key value 计算注意力,输出weighted sum结果。

4. 正弦位置编码:生成内置式位置编码矩阵,作为参数学习。

5. 相关计算模块:定义查询、键值项目、归一化等计算模块。

通过定义这些组件,实现了基于自注意力的Transformer编码器结构。它对Transformer模型进行了扩展,实现了星型结构模型的关键层StarEncoderLayer。能对Transformer有更深入的了解。

entitylenth.py

这个Python文件主要是统计和可视化不同来源NER数据集中的实体长度和类别分布情况。

总体来说,这个py文件实现了以下功能:

1. 统计weibo数据集中实体长度的分布,统计数量。

2. 统计resume数据集中不同实体类型的长度分布,统计数量。

3. 统计labels中各个实体类型的计数。

4. 绘制柱状图可视化实体长度分布。

5. 绘制柱状图可视化不同实体类型的数量分布。

具体实现:

1. 读取数据,统计实体长度,统计小于5、5-10、大于10的数量。

2. 读取数据,统计不同实体类型的实体长度,统计长度小于7和大于等于7的数量。

3. 使用Counter从labels中统计各个实体类型的计数。

4. 使用matplotlib定义画布大小,绘制不同情况下的柱状图。

5. 设置 titles、labels、xticks对齐标签,设置横纵轴名称。

6. 保存图片,提供可视化结果。

7. 绘制不同实体类别数量分布的柱状图。

通过统计NER数据集的长度和类别分布,可以更好地了解和处理数据集的特点,为后续模型训练和预测提供参考。它实现了NER数据集分析的自动化。

focalloss.py

这个Python文件实现了一种损失函数-Focal Loss,用于解决分类问题中的不平衡数据问题。

总体来说,这个py文件完成以下工作:

1. 定义了一个FocalLoss类,用于计算Focal Loss。

2. 实现了Focal Loss的前向计算过程。

具体来说:

1. FocalLoss类继承了nn.Module,实现了一个可以作为模型损失函数的Module。

2. 在构造函数__init__()中,定义两个超参数gamma和weight。

3. 前向计算forward函数:

– 首先使用nn.CrossEntropyLoss计算交叉熵损失ce_loss,其中可以输入权重weight。

– 计算predicted probabilities pt,利用target和预测结果计算pt。

– 根据公式计算focal loss两部分:

– (1-pt)**gamma实现下调易分类样例的影响

– ce_loss作为基础损失

– 分别对这两部分进行权重乘法

– 输出focal loss作为最终损失值

通过这几步,实现了Focal Loss这个新的损失函数。解决了分类任务中正负样本不平衡问题,给予难易样本不同程度的惩罚,有助于增强模型的鲁棒性。

在医疗命名实体识别这样的任务中,使用Focal Loss相比常用的交叉熵损失函数有以下几点优势:

1. 数据不平衡问题更为明显。医疗实体作为负样本的数量远大于正样本。这会导致模型更倾向于识别负样本。

2. 医疗实体的边界非常难确定,包括一些小实体和易被忽视的实体。这类样例正是focal loss设计用来加强的重点。

3. Focal Loss通过调整难易样本的损失权重,弱化对易分类样本的学习,强化对难分类样本的学习能力。这在医疗实体识别中至关重要。

4. 它可以利用预测值中的置信程度来自动调整样本loss之间的平衡,不需要人工设置类样本权重。

5. 与交叉熵相比,focal loss收敛速度更快,对样本学习更有针对性,对神经网络友好些。

所以,在医疗实体识别中:

– 数据本身就存在不平衡,难易样本明显。

– 利用难易样本的识别能力对模型更关键。

– Focal Loss天然解决上述问题,更适合这类任务。

因此使用Focal Loss可以帮助模型更好地学习医疗实体,防止被大量负样本掩盖,提升识别效果。

GAU.py

这个Python文件实现了一种自注意力机制-Gate Attention Unit(GAU)。

总体来说,这个py文件完成以下工作:

1. 定义了GAU模块,可以作为Transformer的一种模块使用。

2. 实现了GAU注意力计算的前向过程。

详细功能如下:

1. GateAttentionUnit类继承nn.Module,重写forward()方法。

2. 初始化参数,如注意力尺寸、学习率等。

3. 对输入特征提取query、key、value、position信息。

4. 根据query、key计算注意力得分,加入位置编码优化。

5. 对注意力矩阵进行L2正则化,从而实现非局部注意。

6. 注意力得分作为权重对value进行加权求和。

7. 对输出特征进行线性变换后加成原特征,得到最终输出。

8. 定义辅助函数如rope()实现相对位置编码等。

通过这些步骤,实现了一种新型的自注意力机制-GAU。相比一般Transformer,它加入了非局部关注能力,适用于一些序列模型任务。

本文件从原理到实现都很清晰地规范化了GAU这一注意力变体。

getlabel.py

这个Python文件主要用于从命名实体识别(NER)数据集中提取和统计实体标签,实现NER任务中的预处理步骤。

总体来说,这个py文件实现了如下功能:

1. 读取NER数据集文件并按行解析数据。

2. 提取每行中目标列(标签列)的元素并保存到列表中。

3. 去重,只存储唯一的标签。

4. 打印所有唯一标签。

5. 输出标签到新的文本文件(实现注释)。

具体步骤:

1. open()打开数据集文件,readline()逐行读取。

2. split()按空格分割每行,取标签列元素保存列表。

3. append()将每次读取的标签添加到列表中,set()转换为集合实现去重。

4. for循环遍历唯一标签列表,打印每个标签。

5. with open写文件模式打开新文件,for循环遍历唯一标签列表逐个输出。

该py文件实现了NER数据集标签的提取、统计和清洗工作。提取了有效标签,为后续任务提供了参考标准。

通过简洁有效地处理了数据集,为提取特征、统计统计量、训练模型等提供了便利,起到了重要的预处理作用。

idcnn.py

这个Python文件实现了一种卷积神经网络模型-Interactive Dilated Convolutional Network(IDCNN),用于序列标注任务。

总体来说,这个py文件完成以下工作:

1. 定义一个IDCNN模型类,实现模型的前向计算过程。

2. 实现必要的模型参数初始化和保存功能。

详细功能如下:

1. IDCNN类继承nn.Module,重写forward()实现前向计算。

2. 初始化Embedding层、卷积层数目、层数、核大小等参数。

3. 定义Embedding层对输入进行嵌入处理。

4. 定义卷积层和残差块,以不同程度的膨胀实现交互注意。

5. 在每个残差块内进行多次卷积操作和非线性激活。

6. 将所有残差块的输出通过拼接结合成输出。

7. 定义全连接层将输出映射成标签空间进行预测。

本模型通过交互式膨胀卷积实现了对上下文特征的深度结合,并堆叠多块残差结构增强代表能力,适用于序列标注任务。

modules.py

这个Python文件定义了一些常用的模块,用于序列标注模型的构建。

总体来说,该文件实现了:

1. 定义了MultiHeadAttention模块,实现多头注意力机制。

2. 定义了FeedForward模块,实现前向投影和残差连接。

3. 定义了CRF模块,用于条件随机场解码。

详细功能:

1. MultiHeadAttention定义了多头注意力结构,包括线性映射、头结合等操作。

2. FeedForward定义了两层全连接网络,实现前向传播加残差。

3. CRF模块包含了CRF损失计算和解码功能:

– 实现CRF损失计算(_score,_log_partition)

– CRF解码实现Viterbi算法,返回最优路径和概率(_viterbi_decode)

– 定义转移矩阵和辅助函数如attenion_padding_mask

这些模块提供了序列标注模型中的重要组成部分,如多头注意力机制、残差连接和CRF解码。

能清晰定义这些通用模块接口和算法细节,方便后续直接调用进行模型构建,起到重要的复用作用。

MutiheadedAttention.py

这个Python文件定义了一些注意力机制相关的模块,用于序列标注模型的构建。

总体来说,该文件实现了:

1. 定义了ScaledDotProductAttention模块,实现缩放点积注意力机制。

2. 定义了MultiHeadAttention模块,实现多头注意力机制。

3. 定义了MultiHeadSelfAttention模块,实现多头自注意力。

4. 定义了CrossAttention模块,实现交叉注意力。

详细功能:

1. ScaledDotProductAttention实现点积注意力计算及Masked操作。

2. MultiHeadAttention定义线性映射、头合成等多头注意力结构。

3. MultiHeadSelfAttention继承SelfAttention,实现多头自注意力计算。

4. CrossAttention实现了输入与记忆间的交叉注意力计算:

– 对输入和记忆分别应用线性映射
– 计算注意力得分并归一化
– 应用注意力得分与值计算加权和

5. 还定义了旋转式位置编码方式计算键值向量位置表示。

这些模块提供了注意力算法的基本结构,如多头机制、自注意力、交叉注意力等,为序列模型构建奠定重要基础。清晰定义接口有助于模块化的模型开发。

readme .md

# 基于BERT适配器的中性序列标注任务利用词汇表增强

本仓库包含了论文《基于BERT适配器的中性序列标注任务利用词汇表增强》(Lexicon Enhanced Chinese Sequence Labelling Using BERT Adapter)的代码和权重文件。

论文链接:https://aclanthology.org/2021.acl-long.454.pdf

如果有任何问题,请联系邮箱:willie1206@163.com

# 依赖项

– Python 3.7.0
– Transformers 3.4.0
– Numpy 1.18.5
– Packaging 17.1
– skicit-learn 0.23.2
– torch 1.6.0+cu92
– tqdm 4.50.2
– multiprocess 0.70.10
– tensorflow 2.3.1
– tensorboardX 2.1
– seqeval 1.2.1

# 输入格式

采用CoNLL格式(优先采用BIOES标注方案),每个字与其标签在一行。句子用空行隔开。

“`cpp
美 B-LOC
国 E-LOC
的 O
华 B-PER
莱 I-PER
士 E-PER

我 O
跟 O
他 O
谈 O
笑 O
风 O
生 O
“`

# 中文BERT、中文词向量和权重文件

### 中文BERT

中文BERT: https://huggingface.co/bert-base-chinese/tree/main

### 中文词向量

中文词向量:https://ai.tencent.com/ailab/nlp/en/data/tencent-ailab-embedding-zh-d200-v0.2.0.tar.gz

更多信息参考:https://ai.tencent.com/ailab/nlp/en/embedding.html

### 权重文件和Shell脚本

– 微博NER
– 智能社NER
– MSRA NER
– 简历NER
– CTB5 POS
– CTB6 POS
– UD1 POS
– UD2 POS
– CTB6 CWS
– MSR CWS
– PKU CWS

# 数据目录结构

– berts: BERT权重文件
– dataset: 数据集
– vocab: 词向量词表
– embedding: 预训练词向量文件
– result: 预测结果
– log: 日志文件

# 运行过程

1. 将.char.bmes文件转换为.json格式的数据
2. 运行shell脚本训练

#### 如果需要加载我的预训练权重,需要修改transformers

我的模型采用分布式训练,无法直接加载单机版transformers。您可以按以下步骤修订transformers:

1. 进入transformers源码目录
2. 找到modeling_util.py文件
3. 修改约在995行的代码
4. 编译安装修改后的transformers

# 引用方式

“`
@inproceedings{liu-etal-2021-lexicon,
title = “Lexicon Enhanced {C}hinese Sequence Labeling Using {BERT} Adapter”,
author = “Liu, Wei and Fu, Xiyan and Zhang, Yue and Xiao, Wenming”,
booktitle = “ACL”,
year = “2021”
}
“`

repo.py

这个Python文件定义了基于BERT的序列标注模型Rope模型。

总体来说,这个文件实现了:

1. 定义Rope模块,实现Rope模型整体结构

2. 定义每层Ropeblock模块,构成Rope的网络结构

3. 构建Rope网络模型

详细功能如下:

1. Rope模块:

– 保存全局变量,如层数、head数等

– 调用Ropeblock搭建网络结构

2. Ropeblock模块:

– 输入:上一层输出

– 输出:多头注意力

– 包含主要结构:

– 多头自注意力

– 前馈网络

– 残差连接和层归一化

3. 构建网络:

– 定义配置参数

– 应用Rope模块

– 输入与输出尺寸设定

– 构建训练和预测模型

该文件定义了Rope作为序列标注Baseline的网络结构,采用模块化设计简洁明了,实现了依赖注入。

定义了标准的多头网络结构单元Ropeblock,通过堆叠搭建成整体模型结构。设计合理可扩展,有利于模型研发。

to_json.py

此py文件主要用于将序列标注数据集从字符级序列格式转换为json格式,具体功能如下:

1. 文件通过convert函数实现指定任务下不同模式(train/dev/test)下的数据集转换。

2. 具体转换流程:

– 读取原始.char.bmes文件
– 调用dele函数删除文件中的偶数行
– 将剩余奇数行写入新文件

3. 此外文件还定义了一些其他功能:

– BMES_to_json函数:将BMES标签转换为json格式
– get_all_labels_from_corpus:获取数据集所有标注类型
– bioes2span:BMES标签转换为开始结束型表示
– bio2span:BIO标签转换为开始结束型表示

4. 各功能模块功能:

– dele函数:删除文件中的偶数行
– BMES_to_json:标签转换
– bioes2span:BMES到开始结束表示转换
– bio2span:BIO到开始结束表示转换

5. 文件主要实现了数据集预处理工作:

– 格式转换
– 标签表达方式转换
– 提供更便于后续模块开发的json格式数据集

通过定义明确的转换模块,实现了数据集从原始格式到标准json格式的转换,为后续模型开发和应用提供了干净整洁的输入格式。

wcbert_modeling.py

这个wcbert_modeling.py文件实现了一个基于BERT的中文模型,主要功能包括:

1. 实现bert模型各个组成模块,包括词嵌入 Embedding、编码器 Encoder、池化器 Pooler等。

2. Embedding模块新增了词边界信息的嵌入。

3. Encoder模块的BertLayer新增了基于匹配词信息的注意力,能够将匹配词特征融入字向量表示。

4. 定义了WCBertModel,继承BertPreTrainedModel,整合Embedding、Encoder和Pooler模块。

5. 定义了WCBertCRFForTokenClassification,实现一个基于BERT-CRF的命名实体识别模型。

6. Encoder模块的BertLayer新增匹配词注意力机制,可以利用匹配词语义信息来改进字向量表示。

7. WCBertCRFForTokenClassification模型在BERT输出基础上,通过多头自注意力、GRU等对特征进行增强,然后经过CRF解码得到实体标签。

8. 实现了前向计算流程,支持训练和预测两个模式,训练模式加入CRF损失函数优化。

具体来说:

1. Embedding模块实现词、位置、类型嵌入的计算;

2. BertLayer实现了标准的Transformer编码层,并新增匹配词注意力来利用匹配词信息;

3. Encoder通过BertLayer堆叠得出最终编码;

4. Pooler对最后一层编码进行池化;

5. WCBertModel整合以上模块,定义BERT模型;

6. WCBertCRFForTokenClassification在BERT基础上利用匹配词信息等进行特征增强,最后CRF解码用于命名实体识别任务。

总体来说这个py文件实现了一个基于BERT的中文序列标注模型,利用匹配词增加上下文信息,接着利用CRF为每一个字或词进行实体类型预测。

wcbert_parser.py

这个wcbert_parser.py文件的主要作用是定义了训练与评估BERT模型的参数。

整体来说,它实现了一个命令行参数解析器,用于加载运行模型训练和预测所需要的各种参数。

具体来说:

1. 定义get_argparse函数,用于返回一个ArgumentParser对象。

2. 在ArgumentParser中添加各种参数,包括:

– 数据路径、模型路径等文件路径参数

– 模型结构相关参数,如模型类别、词典路径等

– 训练配置,如batch size、学习率、优化器等

– 训练过程控制,如epoch数、检查点间隔等

– 设备配置,如是否使用GPU、分布式训练节点数等

3. 数据路径参数主要用于控制加载数据的路径。

4. 模型结构参数用于指定加载的预训练模型和词典。

5. 训练配置参数细致地定义了训练的超参数设置。

6. 训练过程控制参数控制模型训练的过程,如评估间隔等。

7. 设备配置参数支持GPU和分布训练。

8. 解析出的参数后可以用于初始化模型和训练器,统一控制训练评估流程。

总体来说,这个脚本解析命令行,提取各种需要的训练和评估参数,为后续模型和训练器的初始化提供了方便。统一管理了BERT模型各模块的运行需要的参数。

trainer.py

这是一个NER任务的训练和评估脚本。

大致作用:

1. 数据加载:读取数据文件,构建词汇表、标签表等;构建预训练词向量;

2. 模型定义:选择WCBertCRF或BertWordLSTMCRF模型;

3. 训练过程:获取训练器、优化器等;循环训练每个epoch;记录loss、评估过程;

4. 评估过程:在验证集和测试集上评估模型性能,计算指标如F1分数等。

详细模块功能:

1. 数据加载:

– 构建词汇库、标签库
– 通过匹配词典构建输入数据词向量
– 构建Dataset类加载数据

2. 模型定义:

– 使用预训练的BERT配置
– 从BERT模型加载,添加CRF输出层

3. 训练:

– 获取优化器和学习率衰减规则
– 循环每个epoch训练
– 每步计算loss并反向传播
– 记录loss和学习率
– 每隔步评估在验证集效果

4. 评估:

– 在验证/测试集计算预测结果
– 构建词序列对比真实标签
– 计算F1/P/R指标

5. 保存结果:

– 保存最优模型
– 记录指标变化图谱

总体实现了NER任务的完整流程,从数据预处理、模型定义到训练评估而且记录了训练详细过程。

届ける言葉を今は育ててる
最后更新于 2024-09-25