当前位置:   article > 正文

基于BiLSTM+CRF医学病例命名实体识别项目_基于bilstm-crf的中医文本实体识别系统

基于bilstm-crf的中医文本实体识别系统

一、研究背景

为通过项目实战增加对命名实体识别的认识,本文找到中科院软件所刘焕勇老师在github上的开源项目,中文电子病例命名实体识别项目MedicalNamedEntityRecognition。对其进行详细解读。
原项目地址:https://github.com/liuhuanyong/MedicalNamedEntityRecognition
修改版项目地址(详细注释):待补充

二、项目介绍

数据来自CCKS2018的电子病历命名实体识别的评测任务,是对于给定的一组电子病历纯文本文档,识别并抽取出其中与医学临床相关的实体,并将它们归类到预先定义好的类别中。共提供600份标注好的电子病历文本,共需识别含治疗方式、身体部位、疾病症状、医学检查、疾病实体五类实体。
领域命名实体识别问题自然语言处理中经典的序列标注问题, 本项目是采用BiLSTM+CRF构建模型。
病历结构如下图所示:
在这里插入图片描述

三、神经网络结构图

在这里插入图片描述

四、实验数据

1、数据格式:
评测方提供了四个目录(一般项目, 出院项目, 病史特点, 诊疗经过),四个目录下有txtoriginal文件和txt标注文件,内容样式如下:
一般项目-1.txtoriginal.txt

女性,88岁,农民,双滦区应营子村人,主因右髋部摔伤后疼痛肿胀,活动受限5小时于2016-10-29;11:12入院。
  • 1

一般项目-1.txt:

右髋部	21	23	身体部位   #实体  实体首字符在“一般项目”病历描述中的位置  实体尾字符在病历描述中的位置
疼痛	27	28	症状和体征
肿胀	29	30	症状和体征
  • 1
  • 2
  • 3

2、对分类目标进行标记
O非实体部分,TREATMENT治疗方式, BODY身体部位, SIGN疾病症状, CHECK医学检查, DISEASE疾病实体
3、序列标记方法
采用BIO标注:将每个元素(字)标注为“B-X”、“I-X”或者“O”。其中,“B-X”表示此元素所在的片段属于X类型并且此元素在此片段的开头,“I-X”表示此元素所在的片段属于X类型并且此元素在此片段的中间位置,“O”表示不属于任何类型。如:人 O;咳 SIGNS-B;嗽 SIGNS-I。

五、项目介绍

1、transfer_data.py文件
该脚本构建了一个TransferData类,将文本数据转化为实体序列标注数据,作为模型的输入变量。
如,女性,88岁,农民,双滦区应营子村人,主因右髋部。转化为下图序列:
在这里插入图片描述

import os
class TransferData:
    def __init__(self):
        cur = '/'.join(os.path.abspath(__file__).split('/')[:-1])  #获取当前文件地址的上级目录
        #对分类进行标记
        self.label_dict = {
                      '检查和检验': 'CHECK',
                      '症状和体征': 'SIGNS',
                      '疾病和诊断': 'DISEASE',
                      '治疗': 'TREATMENT',
                      '身体部位': 'BODY'}

        self.origin_path = os.path.join(cur, 'data_origin')  #原始数据地址
        self.train_filepath = os.path.join(cur, 'train.txt') #转化后的训练数据地址
        return
    def transfer(self):
        f = open(self.train_filepath, 'w+',encoding='utf-8')   #以写入的方式打开训练数据要保存的文件
        count = 0
        for root,dirs,files in os.walk(self.origin_path):
        #for (root, dirs, files) in walk(roots):
        # roots代表需要遍历的根文件夹;
        # root表示正在遍历的文件夹的名字(根/子);
        # dirs记录正在遍历的文件夹下的子文件夹集合;
        # files记录正在遍历的文件夹中的文件集合
            for file in files:
                filepath = os.path.join(root, file)
                if 'original' not in filepath:
                    continue
                label_filepath = filepath.replace('.txtoriginal','')
                print(filepath, '\t\t', label_filepath)  #data_origin\一般项目\一般项目-1.txtoriginal.txt 	data_origin\一般项目\一般项目-1.txt
                content = open(filepath,encoding='utf-8').read().strip()  #打开案例描述文件,去掉收尾空格
                res_dict = {}
                for line in open(label_filepath,encoding='utf-8'):  #打开实体类别文件
                    res = line.strip().split('	')  #每个实体描述按空格分隔 ['右髋部',‘21’,‘23’,‘身体部位’]
                    start = int(res[1])  #实体的其实字符位置
                    end = int(res[2])  #实体的结束字符位置
                    label = res[3]  #实体类别
                    label_id = self.label_dict.get(label)   #返回分类字典中实体类别对应的values,作为实体名称的id
                    for i in range(start, end+1):
                        if i == start:
                            label_cate = label_id + '-B'  #定义实体的首字符
                        else:
                            label_cate = label_id + '-I'  #实体的非首字符
                        res_dict[i] = label_cate   #构建实体字典{位置index:字符}

                for indx, char in enumerate(content):  #indx文本中字符的位置,char字符
                    char_label = res_dict.get(indx, 'O')  #如果indx在字典的key中,则返回字典value;否则返回O,代表非实体
                    print(char, char_label)   #字符:字符实体标注
                    f.write(char + '\t' + char_label + '\n')
        f.close()
        return
if __name__ == '__main__':
    handler = TransferData()
    train_datas = handler.transfer()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

2、lstm_train.py文件
(1)build_data函数:构建数据集

 [[['给','予','应','用','活','血','化','瘀','药','物'],['O','O','O','O','TREATMENT - B','TREATMENT - I','TREATMENT - I','TREATMENT - I','TREATMENT - I','TREATMENT - I']],
  • 1

(2)modify_data函数:将数据转换成keras所需的格式

x_train [['给','予','应','用','活','血','化','瘀','药','物'],[...],[...]]
y_train [['O','O','O','O','TREATMENT - B','TREATMENT - I','TREATMENT - I','TREATMENT - I','TREATMENT - I','TREATMENT - I'],[...],[...]]
  • 1
  • 2

(3)load_pretrained_embedding函数:加载预训练好的词向量
(4)build_embedding_matrix函数:使用样本数据到词向量中查表,生成训练用的词向量矩阵。
(5)tokenvec_bilstm2_crf_model函数:使用样本词向量作为Embedding输入,构建BiLSTM+CRF模型框架
(6)train_model函数:对模型进行训练

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/368010
推荐阅读
相关标签
  

闽ICP备14008679号