当前位置:   article > 正文

基于CRF的医疗实体识别baseline_医疗数据实体识别

医疗数据实体识别

1 导包

# please run pip install sklearn-crfsuite in your environment
  • 1
#导入数据分析所需的基础包
import pandas as pd
import numpy as np
import os

#包tqdm是用来对可迭代对象执行时生成一个进度条用以监视程序运行过程
from tqdm import tqdm

#导入训练集测试集划分的包
from sklearn.model_selection import train_test_split

#导入CRF模型所需的包
from sklearn_crfsuite import CRF

#导入模型评估所需的包
from sklearn_crfsuite import metrics
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2 读取数据

数据保存在data/目录下,data/目录下共有四个文件夹,分别对应四种医学情景:出院情况、病史特点、诊疗过程和一般项目。每个文件夹下保存了该情景下的电子病历。包括两类文件:‘xxx-yyy.txtoriginal.txt’和’xxx-yyy.txt’。'xxx-yyy.txtoriginal.txt’保存了xxx情境下第yyy号病历的病历文本,保存在txt的第一行中。'xxx-yyy.txt’为其对应的标签数据。

数据中共包含5种实体:治疗、身体部位、疾病和诊断、症状和体征、检查和检验。

#读取一个病历文本数据,并查看其内容。
with open('data/一般项目/一般项目-1.txtoriginal.txt') as f:
    content = f.read().strip()
print(content)
  • 1
  • 2
  • 3
  • 4
女性,88岁,农民,双滦区应营子村人,主因右髋部摔伤后疼痛肿胀,活动受限5小时于2016-10-29;11:12入院。
  • 1
#读取上述病历对应的标签数据
with open('data/一般项目/一般项目-1.txt') as f:
    content_label = f.read().strip()
print(content_label)
  • 1
  • 2
  • 3
  • 4
右髋部	21	23	身体部位
疼痛	27	28	症状和体征
肿胀	29	30	症状和体征
  • 1
  • 2
  • 3

可以看出,标签文件的数据格式为每行对应一个实体,每行格式为“实体内容 实体在文本中的开始位置 实体在文本中的结束位置 实体类别”。如第一行表示content[21:24]对应的便是’右髋部’,为身体部位实体类别。

3 数据标注

实体识别的数据标注方式主要有BIOES和BIO两种,详细的介绍参考实验手册。这里为使标注类别不至于太多,决定采用BIO方式。即将实体部分的第一个汉字标注为B,实体的其他部分的汉字标注为I,非实体部分标注为O。

将5种实体类别治疗、身体部位、疾病和诊断、症状和体征、检查和检验分别标记为TREATMENT、BODY、DISEASES、SIGNS、EXAMINATIONS。

则标记时,如:若为治疗类别的实体的第一个汉字,则将其标注为B-TREATMENT,该实体其他字标记为I-TREATMENT。

label_dict = {'治疗':'TREATMENT',
              '身体部位':'BODY',
              '疾病和诊断':'DISEASES',
              '症状和体征':'SIGNS',
              '检查和检验':'EXAMINATIONS'}

def sentence2BIOlabel(sentence,label_from_file):
    '''
        返回句子sentence的BIO标注列表
        入参:
            sentence:一个句子,字符串类别
            label_from_file:该句子对应的标签,格式为直接从txt文件中读出的格式,形如上文中的content_label
        出参:
            sentence_label:该句子的BIO标签。一个列表,列表的第i项为第i个汉字对应的标签
    '''
    # 初始的sentence_label每个标签均定义为'O'。之后会修改其中实体部分的标签。
    sentence_label = ['O']*len(sentence)
    if label_from_file=='':
        return sentence_label
    # line为label_from_file中每一行的数据,对应一个实体的信息。格式为“实体内容 实体在文本中的开始位置 实体在文本中的结束位置 实体类别”
    for line in label_from_file.split('\n'):
        # entity_info中保存了单个实体的信息
        entity_info = line.strip().split('\t')
        start_index = int(entity_info[1])     #实体在文本中的开始位置
        end_index = int(entity_info[2])      #实体在文本中的结束位置
        entity_label = label_dict[entity_info[3]]      #实体标签类别
        # 为实体的第一个汉字标记为B-xx
        sentence_label[start_index] = 'B-'+entity_label
        # 为实体中的其他汉字标记为I-xx
        for i in range(start_index+1,end_index+1):
            sentence_label[i] = 'I-'+entity_label
    return sentence_label
  • 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
# 以上文中的content和content_label为例查看sentence2BIOlabel函数的使用方法
# 返回上文中content对应的BIO标签并输出
sentence_label_tmp = sentence2BIOlabel(content,content_label)
print(sentence_label_tmp)
  • 1
  • 2
  • 3
  • 4
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-BODY', 'I-BODY', 'I-BODY', 'O', 'O', 'O', 'B-SIGNS', 'I-SIGNS', 'B-SIGNS', 'I-SIGNS', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']
  • 1
# 输出content中每个汉字与BIO标签的对应关系
for i in range(len(content)):
    print(content[i],sentence_label_tmp[i])
  • 1
  • 2
  • 3
女 O
性 O
, O
8 O
8 O
岁 O
, O
农 O
民 O
, O
双 O
滦 O
区 O
应 O
营 O
子 O
村 O
人 O
, O
主 O
因 O
右 B-BODY
髋 I-BODY
部 I-BODY
摔 O
伤 O
后 O
疼 B-SIGNS
痛 I-SIGNS
肿 B-SIGNS
胀 I-SIGNS
, O
活 O
动 O
受 O
限 O
5 O
小 O
时 O
于 O
2 O
0 O
1 O
6 O
- O
1 O
0 O
- O
2 O
9 O
; O
1 O
1 O
: O
1 O
2 O
入 O
院 O
。 O
  • 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
  • 55
  • 56
  • 57
  • 58
  • 59
# 将数据集中每个样本读进来并将其保存在sentence_list中,将每个样本对应的BIO标签保存在label_list中
# sentence_list的格式为[第一个句子,第二个句子,第三个句子,...,第n个句子]
# label_list的格式为[第一个句子对应的BIO标注列表,第二个句子对应的BIO标注列表,第三个句子对应的BIO标注列表,...,第n个句子对应的BIO标注列表]

sentence_list = []
label_list = []
data_base_path = "./data/"
for parent_path in os.listdir(data_base_path):
    if os.path.isdir(data_base_path+parent_path):
        for file_name in os.listdir(data_base_path+parent_path):
            if "original" in file_name:
                with open(data_base_path+parent_path+"/"+file_name,"r") as f:
                    content = f.read().strip()
                sentence_list.append(content)
                label_file_name = file_name.split("original")[0]
                with open(data_base_path+parent_path+"/"+label_file_name,"r") as f:
                    content_label = f.read().strip()
                label = sentence2BIOlabel(content,content_label)
                label_list.append(label)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

4 文本特征工程

要使用CRF算法对每个字进行标注,就需要获取每个字对应的特征。就需要对文本进行特征工程,这一部分就是构建一句话中每个字的特征。

#中文分词时最常用的包是jieba。但我们本次的数据集是专门针对医疗领域的,这里选用了一个在细分领域上表现更好的库pkuseg
import pkuseg
# 将model_name设置为'medicine'以加载医疗领域的模型。第一次执行此代码时会自动下载医疗领域对应的模型,这可能需要一些时间。
# 设置postag为True会在分词的同时进行词性标注
seg = pkuseg.pkuseg(model_name='medicine',postag=True)
  • 1
  • 2
  • 3
  • 4
  • 5
# pkuseg包使用示例
seg.cut('发病原因为右髋部摔伤后疼痛肿胀')
  • 1
  • 2
[('发病', 'vn'),
 ('原因', 'n'),
 ('为', 'v'),
 ('右髋部', 'n'),
 ('摔伤', 'v'),
 ('后', 'f'),
 ('疼痛', 'a'),
 ('肿胀', 'v')]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

pkuseg包对医疗方面的文本有较好的分词效果。seg.cut(文本)的输出格式为[(第一个词,第一个词的词性),(第二个词,第二个词的词性),…,(第n个词,第n个词的词性)]。稍后在构建每个字的特征时我们会用到pkuseg的分词功能。

# 加载医学的专业词汇词库THUOCL_medical.txt。地址:https://github.com/thunlp/THUOCL中下载而来。
# 文件中每行的格式为:医学名词 词频

#读取文件
with open('THUOCL_medical.txt') as f:
    medical_words = f.read().strip()
#获取医疗词汇表
medical_words_list = [words.strip().split('\t')[0] for words in medical_words.split('\n')]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
#医疗词汇表示例,这一词汇表在我们构建特征时会用到。
medical_words_list[:10]
  • 1
  • 2
['精神', '医院', '检查', '死亡', '恢复', '意识', '医疗', '治疗', '卫生', '患者']
  • 1

进行完上述准备工作后,我们接下来正式来构造特征。

def word2feature(sentence,i):
    '''
        返回句子sentence中第i个汉字的一些简单的特征
        入参:
            sentence:待处理的句子
            i:会返回第i个汉字的一些简单的特征
        出参:
            simple_feature:由一些简单的特征所组成的字典,字典的键为特征名,值为特征值
    '''
    simple_feature = {}
    simple_feature['word'] = sentence[i]   #当前字
    simple_feature['pre_word'] = sentence[i-1] if i>0 else 'start'    #前一个字
    simple_feature['after_word'] = sentence[i+1] if i<len(sentence)-1 else 'end'     #后一个字
    
    #接下来加入当前字的Bi-gram特征,即前一个字+当前字、当前字+后一个字,并将特征分别命名为'pre_word_word'和'word_after_word'
    ##在这里输入你的代码
    simple_feature['pre_word_word'] = sentence[i-1]+sentence[i] if i>0 else 'start'+sentence[i]
    ##结束你的代码
    simple_feature['word_after_word'] = sentence[i]+sentence[i+1] if i<len(sentence)-1 else sentence[i]+'end'
    #加入一个偏置项
    simple_feature['bias'] = 1
    return simple_feature
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
def sentence2feature(sentence):
    '''
        在word2feature定义的简单特征的基础上,增加一些复杂的特征,并返回句子中每个字对应的特征字典所组成的列表
        入参:
            sentence:待处理的句子
        出参:
            sentence_feature_list:句子中每个字对应的特征字典所组成的列表。格式为:[第一个字的特征字典,第二个字的特征字典,...,第n个字的特征字典]
    '''
    sentence_feature_list = [word2feature(sentence,i) for i in range(len(sentence))]
    #为每个字增加一些复杂的特征
    #增加当前字在分词后所在的词,该词的词性,该词的上一个词,该词的下一个词,该词是否为医疗专业词汇,该字是否为该词的第一个字
    word_index = 0    #指向字的指针,会逐步往后移动,其作用在之后可以看到
    #使用pkuseg对句子进行分词
    sentence_cut = seg.cut(sentence)
    #这里为和字进行区分,使用大写的WORD来表示词,小写的word来表示字
    for i,(WORD,nominal) in enumerate(sentence_cut):
        for j in range(word_index,word_index+len(WORD)):
            sentence_feature_list[j]['WORD'] = WORD     #当前字在分词后所在的词
            sentence_feature_list[j]['nominal'] = nominal     #该词的词性
            sentence_feature_list[j]['pre_WORD'] = sentence_cut[i-1][0] if i>0 else 'START'    #该词的上一个词
            sentence_feature_list[j]['after_WORD'] = sentence_cut[i+1][0] if i<len(sentence_cut)-1 else 'END'    #该词的下一个词
            sentence_feature_list[j]['is_medicalwords'] = 1 if WORD in medical_words_list else 0    #该词是否为医学专业词汇
        
        #加入一个特征'is_first'表示当前字是否为其所属词的第一个字,是则将该特征值记为1,否则记为0
        ##在这里输入你的代码
            sentence_feature_list[j]["if_first"] = 1 if j == word_index else 0
        ##结束你的代码
        
        word_index = word_index+len(WORD)    #更新word_index的值
    if sentence_feature_list == None:
        print(True)
    return sentence_feature_list
  • 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
#获取sentence_list中每句话中每个字对应的特征,并将其保存在feature_list中
#使用tqdm函数来输出一个进度条,以监控代码的运行过程
feature_list = [sentence2feature(sentence) for sentence in tqdm(sentence_list)]
  • 1
  • 2
  • 3
100%|██████████| 1198/1198 [00:39<00:00, 30.34it/s]
  • 1
len(feature_list)
  • 1
1198
  • 1

5 CRF模型搭建

# 首先对数据划分训练集和测试集
x_train,x_test,y_train,y_test = train_test_split(feature_list, label_list, test_size=0.3, random_state=2020)
  • 1
  • 2
len(y_train)
  • 1
838
  • 1
# 搭建一个CRF模型
crf = CRF(
    algorithm='lbfgs',   #训练算法
    c1=0.1,    #L1正则化系数
    c2=0.1,    #L2正则化系数
    max_iterations=100,     #优化算法的最大迭代次数
    all_possible_transitions=False
)
# 使用crf模型对训练集进行训练
crf.fit(x_train,y_train)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
/home/chi/anaconda3/envs/greedyaiqa/lib/python3.6/site-packages/sklearn/base.py:197: FutureWarning: From version 0.24, get_params will raise an AttributeError if a parameter cannot be retrieved as an instance attribute. Previously it would return None.
  FutureWarning)




CRF(algorithm='lbfgs', all_possible_states=None, all_possible_transitions=False,
    averaging=None, c=None, c1=0.1, c2=0.1, calibration_candidates=None,
    calibration_eta=None, calibration_max_trials=None, calibration_rate=None,
    calibration_samples=None, delta=None, epsilon=None, error_sensitive=None,
    gamma=None, keep_tempfiles=None, linesearch=None, max_iterations=100,
    max_linesearch=None, min_freq=None, model_filename=None, num_memories=None,
    pa_type=None, period=None, trainer_cls=None, variance=None, verbose=False)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
def predict(sentence):
    '''
        输出CRF预测的一个句子的BIO标注
        入参:
            sentence:待处理的句子
        出参:
            sent_bio:一个字典,字典的键为句子中的汉字,值为其对应的BIO标注
    '''
    #提示:按照获取输入句子的特征、获取crf的预测值、获取以句子中汉字为键,对应的BIO标注为值的字典 的步骤进行
    #提示:crf.predict_single(待预测句子的特征) 可用来预测单个句子的BIO标注,返回值为每个字的BIO标注列表
    ##在这里输入你的代码
    feature = sentence2feature(sentence)
    sent_bio = crf.predict_single(feature)
    ##结束你的代码
    
    return sent_bio
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
# 使用predict函数对一个句子进行预测
predict('这是由于耳膜损伤导致的')
  • 1
  • 2
['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O']
  • 1

可以看出CRF模型能够有效的识别出这句话中的实体,接下来我们用CRF模型对我们的测试集进行预测。

# 获取测试集的预测值
y_pred = crf.predict(x_test)
  • 1
  • 2

6 模型评估

使用sklearn_crfsuite中自带的metrics包可对模型进行有效的评估

# 获取crf模型的全部标签
labels = list(crf.classes_)
# 由于标签O过多,而我们对其他标签更感兴趣。为了解决这个问题,我们标签O移除。
labels.remove('O')
# 查看除'O'外的全部标签
labels
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
['B-TREATMENT',
 'I-TREATMENT',
 'B-EXAMINATIONS',
 'I-EXAMINATIONS',
 'B-BODY',
 'I-BODY',
 'B-SIGNS',
 'I-SIGNS',
 'B-DISEASES',
 'I-DISEASES']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
# 计算除O之外的所有标签计算的平均F1分数。
metrics.flat_f1_score(y_test, y_pred,
                      average='micro', labels=labels)
  • 1
  • 2
  • 3
0.9421061480692708
  • 1
# 查看每个类别的预测情况
print(metrics.flat_classification_report(
    y_test, y_pred, labels=labels, digits=3
))
  • 1
  • 2
  • 3
  • 4
                precision    recall  f1-score   support

   B-TREATMENT      0.901     0.833     0.866       294
   I-TREATMENT      0.919     0.887     0.903      1448
B-EXAMINATIONS      0.970     0.978     0.974      2975
I-EXAMINATIONS      0.964     0.971     0.968      6462
        B-BODY      0.926     0.919     0.922      3314
        I-BODY      0.917     0.928     0.922      6003
       B-SIGNS      0.967     0.980     0.974      2501
       I-SIGNS      0.969     0.980     0.974      2738
    B-DISEASES      0.833     0.721     0.773       208
    I-DISEASES      0.829     0.719     0.770       834

     micro avg      0.943     0.942     0.942     26777
     macro avg      0.919     0.892     0.905     26777
  weighted avg      0.942     0.942     0.942     26777
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

7 BiLSTM-CRF

CRF模型还可与BiLSTM模型结合来解决实体识别问题,这样的好处是BiLSTM可以自动获取文本的特征,就不需要自己去定义特征,不需要再进行文本特征工程部分。

BiLSTM-CRF模型的实现细节均在BiLSTM_CRF.py中实现。

from BiLSTM_CRF import *
  • 1
#将word映射到id
word2id = word_to_id(sentence_list)
#将label映射到id
tag2id = tag_to_id(label_list)
  • 1
  • 2
  • 3
  • 4
#查看label与id的映射关系
tag2id
  • 1
  • 2
{'O': 0,
 'B-EXAMINATIONS': 1,
 'I-EXAMINATIONS': 2,
 'B-BODY': 3,
 'I-BODY': 4,
 'B-SIGNS': 5,
 'I-SIGNS': 6,
 'B-DISEASES': 7,
 'I-DISEASES': 8,
 'B-TREATMENT': 9,
 'I-TREATMENT': 10,
 '<unk>': 11,
 '<pad>': 12,
 '<start>': 13,
 '<end>': 14}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

LSTM模型训练的时候需要在word2id和tag2id加入PAD和UNK,如果是加了CRF的lstm还要加入和 (解码的时候需要用到)。word2id的格式与tag2id的格式类似。

#按照与CRF模型划分训练集测试集时相同的比例和相同的随机数种子对sentence_list与label_list划分训练集合测试集
x_train_lstmcrf,x_test_lstmcrf,y_train_lstmcrf,y_test_lstmcrf = train_test_split(sentence_list, label_list, test_size=0.3, random_state=2020)
  • 1
  • 2
#为每句话后加入一个"<end>" token
x_train_lstmcrf,y_train_lstmcrf = prepocess_data_for_lstmcrf(x_train_lstmcrf,y_train_lstmcrf)
x_test_lstmcrf,y_test_lstmcrf = prepocess_data_for_lstmcrf(x_test_lstmcrf,y_test_lstmcrf,test=True)
  • 1
  • 2
  • 3
#搭建一个BiLSTM_CRF模型
model = BiLSTM_CRF_Model(vocab_size=len(word2id),out_size=len(tag2id),batch_size=64, epochs=30)
#在训练集上进行训练
model.train(x_train_lstmcrf,y_train_lstmcrf,word2id,tag2id)
  • 1
  • 2
  • 3
  • 4
Epoch 1, step/total_step: 10/14 71.43% Loss:703.1040
Epoch 1, Val Loss:354.8586
Epoch 2, step/total_step: 10/14 71.43% Loss:419.8804
Epoch 2, Val Loss:280.7740
Epoch 3, step/total_step: 10/14 71.43% Loss:351.4792
Epoch 3, Val Loss:253.9364
Epoch 4, step/total_step: 10/14 71.43% Loss:320.9320
Epoch 4, Val Loss:202.8077
Epoch 5, step/total_step: 10/14 71.43% Loss:269.4268
Epoch 5, Val Loss:176.0763
Epoch 6, step/total_step: 10/14 71.43% Loss:232.1650
Epoch 6, Val Loss:150.6498
Epoch 7, step/total_step: 10/14 71.43% Loss:198.0663
Epoch 7, Val Loss:126.4110
Epoch 8, step/total_step: 10/14 71.43% Loss:166.0142
Epoch 8, Val Loss:106.4447
Epoch 9, step/total_step: 10/14 71.43% Loss:140.0015
Epoch 9, Val Loss:89.2141
Epoch 10, step/total_step: 10/14 71.43% Loss:117.0769
Epoch 10, Val Loss:76.6977
Epoch 11, step/total_step: 10/14 71.43% Loss:100.5820
Epoch 11, Val Loss:67.0900
Epoch 12, step/total_step: 10/14 71.43% Loss:87.8584
Epoch 12, Val Loss:60.0311
Epoch 13, step/total_step: 10/14 71.43% Loss:77.5198
Epoch 13, Val Loss:54.0604
Epoch 14, step/total_step: 10/14 71.43% Loss:70.3888
Epoch 14, Val Loss:49.1572
Epoch 15, step/total_step: 10/14 71.43% Loss:63.0964
Epoch 15, Val Loss:46.0829
Epoch 16, step/total_step: 10/14 71.43% Loss:59.1197
Epoch 16, Val Loss:41.5716
Epoch 17, step/total_step: 10/14 71.43% Loss:53.2706
Epoch 17, Val Loss:37.3219
Epoch 18, step/total_step: 10/14 71.43% Loss:49.1802
Epoch 18, Val Loss:33.9772
Epoch 19, step/total_step: 10/14 71.43% Loss:44.7907
Epoch 19, Val Loss:31.7810
Epoch 20, step/total_step: 10/14 71.43% Loss:41.8903
Epoch 20, Val Loss:29.3012
Epoch 21, step/total_step: 10/14 71.43% Loss:38.7684
Epoch 21, Val Loss:27.7391
Epoch 22, step/total_step: 10/14 71.43% Loss:37.1167
Epoch 22, Val Loss:27.8624
Epoch 23, step/total_step: 10/14 71.43% Loss:35.7134
Epoch 23, Val Loss:25.9406
Epoch 24, step/total_step: 10/14 71.43% Loss:33.8559
Epoch 24, Val Loss:25.1907
Epoch 25, step/total_step: 10/14 71.43% Loss:32.3450
Epoch 25, Val Loss:23.9051
Epoch 26, step/total_step: 10/14 71.43% Loss:31.1568
Epoch 26, Val Loss:22.7183
Epoch 27, step/total_step: 10/14 71.43% Loss:29.5120
Epoch 27, Val Loss:21.2255
Epoch 28, step/total_step: 10/14 71.43% Loss:28.1631
Epoch 28, Val Loss:20.2317
Epoch 29, step/total_step: 10/14 71.43% Loss:26.7550
Epoch 29, Val Loss:19.0803
Epoch 30, step/total_step: 10/14 71.43% Loss:25.4697
Epoch 30, Val Loss:18.3434
  • 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
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
#获取测试集的预测值
y_pred_lstmcrf, _ = model.test(x_test_lstmcrf,y_test_lstmcrf,word2id,tag2id)
  • 1
  • 2
/pytorch/aten/src/ATen/native/cudnn/RNN.cpp:1236: UserWarning: RNN module weights are not part of single contiguous chunk of memory. This means they need to be compacted at every call, possibly greatly increasing memory usage. To compact weights again call flatten_parameters().
  • 1
#计算BiLSTM-CRF模型除O之外的所有标签计算的平均F1分数。
metrics.flat_f1_score(y_test_lstmcrf, y_pred_lstmcrf,
                      average='micro', labels=labels)
  • 1
  • 2
  • 3
0.9319616117106688
  • 1
#查看BiLSTM-CRF模型每个类别的预测情况
print(metrics.flat_classification_report(
    y_test_lstmcrf, y_pred_lstmcrf, labels=labels, digits=3
))
  • 1
  • 2
  • 3
  • 4
                precision    recall  f1-score   support

   B-TREATMENT      0.873     0.748     0.806       294
   I-TREATMENT      0.887     0.887     0.887      1448
B-EXAMINATIONS      0.952     0.974     0.963      2975
I-EXAMINATIONS      0.950     0.970     0.960      6462
        B-BODY      0.913     0.909     0.911      3314
        I-BODY      0.914     0.916     0.915      6003
       B-SIGNS      0.956     0.946     0.951      2501
       I-SIGNS      0.959     0.961     0.960      2738
    B-DISEASES      0.880     0.740     0.804       208
    I-DISEASES      0.850     0.749     0.797       834

     micro avg      0.932     0.932     0.932     26777
     macro avg      0.913     0.880     0.895     26777
  weighted avg      0.931     0.932     0.931     26777
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16


  • 1
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号