在NLP中,序列标注算法是常见的深度学习模型,但是,对于序列标注算法的评估,我们真的熟悉吗?

在本文中,笔者将会序列标注算法的模型效果评估方法和seqeval的使用。

序列标注算法的模型效果评估

在序列标注算法中,一般我们会形成如下的序列列表,如下:

['O', 'O', 'B-MISC', 'I-MISC', 'B-MISC', 'I-MISC', 'O', 'B-PER', 'I-PER']

一般序列标注算法的格式有BIOIOBESBMES等。其中,实体指的是从B开头标签开始的,同一类型(比如:PER/LOC/ORG)的,非O的连续标签序列。

常见的序列标注算法的模型效果评估指标有准确率(accuracy)、查准率(percision)、召回率(recall)、F1值等,计算的公式如下:

  • 准确率: accuracy = 预测对的元素个数/总的元素个数

  • 查准率:precision = 预测正确的实体个数 / 预测的实体总个数

  • 召回率:recall = 预测正确的实体个数 / 标注的实体总个数

  • F1值:F1 = 2 *准确率 * 召回率 / (准确率 + 召回率)

举个例子,我们有如下的真实序列y_true和预测序列y_pred,如下:

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

列表中一个有9个元素,其中预测对的元素个数为6个,那么准确率为2/3。标注的实体总个数为2个,预测的实体总个数为3个,预测正确的实体个数为1个,那么precision=1/3, recall=1/2, F1=0.4。

seqeval的使用

一般我们的序列标注算法,是用conlleval.pl脚本实现,但这是用perl语言实现的。在Python中,也有相应的序列标注算法的模型效果评估的第三方模块,那就是seqeval,其官网网址为:https://pypi.org/project/seqeval/0.0.3/ 。

seqeval支持BIOIOBES标注模式,可用于命名实体识别,词性标注,语义角色标注等任务的评估。

官网文档中给出了两个例子,笔者修改如下:

例子1:

# -*- coding: utf-8 -*-from seqeval.metrics import f1_scorefrom seqeval.metrics import precision_scorefrom seqeval.metrics import accuracy_scorefrom seqeval.metrics import recall_scorefrom seqeval.metrics import classification_report

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

print("accuary: ", accuracy_score(y_true, y_pred))print("p: ", precision_score(y_true, y_pred))print("r: ", recall_score(y_true, y_pred))print("f1: ", f1_score(y_true, y_pred))print("classification report: ")print(classification_report(y_true, y_pred))

输出结果如下:

accuary:  0.6666666666666666p:  0.3333333333333333r:  0.5f1:  0.4classification report:            precision    recall  f1-score   support

     MISC       0.00      0.00      0.00         1      PER       1.00      1.00      1.00         1

micro avg       0.33      0.50      0.40         2macro avg       0.50      0.50      0.50         2

例子2:

# -*- coding: utf-8 -*-from seqeval.metrics import f1_scorefrom seqeval.metrics import precision_scorefrom seqeval.metrics import accuracy_scorefrom seqeval.metrics import recall_scorefrom seqeval.metrics import classification_report

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

print("accuary: ", accuracy_score(y_true, y_pred))print("p: ", precision_score(y_true, y_pred))print("r: ", recall_score(y_true, y_pred))print("f1: ", f1_score(y_true, y_pred))print("classification report: ")print(classification_report(y_true, y_pred))

输出结果同上。

在Keras中使用seqeval

笔者一年多年写过文章:使用CRF++实现命名实体识别(NER), 我们对模型训练部分的代码加以改造,使之在训练过程中能输出F1值。在Github上下载项目DL_4_NER,网址为:https://github.com/percent4/DL_4_NER 。修改utils.py中的文件夹路径,以及模型训练部分的代码(DL_4_NER/Bi_LSTM_Model_training.py)如下:

# -*- coding: utf-8 -*-import pickleimport numpy as npimport pandas as pdfrom utils import BASE_DIR, CONSTANTS, load_datafrom data_processing import data_processingfrom keras.utils import np_utils, plot_modelfrom keras.models import Sequentialfrom keras.preprocessing.sequence import pad_sequencesfrom keras.layers import Bidirectional, LSTM, Dense, Embedding, TimeDistributed

# 模型输入数据def input_data_for_model(input_shape):

    # 数据导入    input_data = load_data()    # 数据处理    data_processing()    # 导入字典    with open(CONSTANTS[1], 'rb') as f:        word_dictionary = pickle.load(f)    with open(CONSTANTS[2], 'rb') as f:        inverse_word_dictionary = pickle.load(f)    with open(CONSTANTS[3], 'rb') as f:        label_dictionary = pickle.load(f)    with open(CONSTANTS[4], 'rb') as f:        output_dictionary = pickle.load(f)    vocab_size = len(word_dictionary.keys())    label_size = len(label_dictionary.keys())

    # 处理输入数据    aggregate_function = lambda input: [(word, pos, label) for word, pos, label in                                            zip(input['word'].values.tolist(),                                                input['pos'].values.tolist(),                                                input['tag'].values.tolist())]

    grouped_input_data = input_data.groupby('sent_no').apply(aggregate_function)    sentences = [sentence for sentence in grouped_input_data]

    x = [[word_dictionary[word[0]] for word in sent] for sent in sentences]    x = pad_sequences(maxlen=input_shape, sequences=x, padding='post', value=0)    y = [[label_dictionary[word[2]] for word in sent] for sent in sentences]    y = pad_sequences(maxlen=input_shape, sequences=y, padding='post', value=0)    y = [np_utils.to_categorical(label, num_classes=label_size + 1) for label in y]

    return x, y, output_dictionary, vocab_size, label_size, inverse_word_dictionary

# 定义深度学习模型:Bi-LSTMdef create_Bi_LSTM(vocab_size, label_size, input_shape, output_dim, n_units, out_act, activation):    model = Sequential()    model.add(Embedding(input_dim=vocab_size + 1, output_dim=output_dim,                        input_length=input_shape, mask_zero=True))    model.add(Bidirectional(LSTM(units=n_units, activation=activation,                                 return_sequences=True)))    model.add(TimeDistributed(Dense(label_size + 1, activation=out_act)))    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])    return model

# 模型训练def model_train():

    # 将数据集分为训练集和测试集,占比为9:1    input_shape = 60    x, y, output_dictionary, vocab_size, label_size, inverse_word_dictionary = input_data_for_model(input_shape)    train_end = int(len(x)*0.9)    train_x, train_y = x[0:train_end], np.array(y[0:train_end])    test_x, test_y = x[train_end:], np.array(y[train_end:])

    # 模型输入参数    activation = 'selu'    out_act = 'softmax'    n_units = 100    batch_size = 32    epochs = 10    output_dim = 20

    # 模型训练    lstm_model = create_Bi_LSTM(vocab_size, label_size, input_shape, output_dim, n_units, out_act, activation)    lstm_model.fit(train_x, train_y, validation_data=(test_x, test_y), epochs=epochs, batch_size=batch_size, verbose=1)

model_train()

模型训练的结果如下(中间过程省略):

......12598/12598 [==============================] - 26s 2ms/step - loss: 0.0075 - acc: 0.9981 - val_loss: 0.2131 - val_acc: 0.9592

我们修改代码,在lstm_model.fit那一行修改代码如下:

    lables = ['O', 'B-MISC', 'I-MISC', 'B-ORG', 'I-ORG', 'B-PER', 'B-LOC', 'I-PER', 'I-LOC', 'sO']    id2label = dict(zip(range(len(lables)), lables))    callbacks = [F1Metrics(id2label)]    lstm_model.fit(train_x, train_y, validation_data=(test_x, test_y), epochs=epochs,                   batch_size=batch_size, verbose=1, callbacks=callbacks)

此时输出结果为:

12598/12598 [==============================] - 26s 2ms/step - loss: 0.0089 - acc: 0.9978 - val_loss: 0.2145 - val_acc: 0.9560 - f1: 95.40           precision    recall  f1-score   support

     MISC     0.9707    0.9833    0.9769     15844      PER     0.9080    0.8194    0.8614      1157      LOC     0.7517    0.8095    0.7795       677      ORG     0.8290    0.7289    0.7757       745       sO     0.7757    0.8300    0.8019       100

micro avg     0.9524    0.9556    0.9540     18523macro avg     0.9520    0.9556    0.9535     18523

这就是seqeval的强大之处。

关于seqeval在Keras的使用,有不清楚的地方可以参考该项目的Github网址:https://github.com/chakki-works/seqeval 。

作者:jclian,喜欢算法,热爱分享,希望能结交更多志同道合的朋友,一起在学习Python的道路上走得更远!

推荐阅读

5分钟完全掌握PyPy

用 PyPy 让你的 Python 代码运行得更快!

有人在代码里下毒!慎用 pip install 命令

社区会员

点赞鼓励一下

ner 评估指标_序列标注算法评估模块 seqeval 的使用相关推荐

  1. 评估指标_机器学习评估方法与评估指标总结

    离线评估方法 离线评估的基本原理是在离线环境中,将数据集划分为"训练集"和"测试集",用"训练集"训练模型,用"测试集" ...

  2. auuc 评估指标_分类之性能评估指标

    本文主要介绍几种常用的用于分类的性能评估指标,同时介绍如何绘制ROC曲线以及计算AUC值的便捷方法.最后再附上一个绘制ROC曲线和计算AUC的Python源码实现. Precision和Recall ...

  3. 评估指标_供应链改进常用评估指标

    供应链改善项目大部分是基于供应链SCOR模型开展,在SCOR模型中,涉及到分销.计划.采购.制造.配送.退货等功能环节.而供应链的改善核心内容是流程的优化.规则的确定,最终体现在两大目标:" ...

  4. Python深度学习-NLP实战:命名实体识别(NER)之分词与序列标注、实体识别任务简介

    系列文章目录 Python深度学习-NLP实战:深度学习系列培训教程 Linux服务器软件的简单使用 Linux命令的简单使用 训练集.测试集.验证集的介绍及制作 字向量的训练与生成 文本分类之SVM ...

  5. kmeans及模型评估指标_聚类分析的过程和两个常用的聚类算法

    聚类分析过程 一般聚类分析的数据源是需要相对干净的,即需要做统一的特征清洗.特征变换过程,即空值.非法值.异常值.类别变量等的处理.主要过程如下: 数据采集:我们可以认为是统一的ETL过程,这里涉及埋 ...

  6. auuc 评估指标_广告中增益模型理解

    由于工作的需要,广告增益越来越进入到我们的视野当中,收益永远是广告主评价广告投放的重要标准,但是这种收益也慢慢被认为有两种. 一种是广告投放所带来的直接收益,比如用户A广告投放后的cvr为3%,用户B ...

  7. kmeans及模型评估指标_如何评估聚类模型?兰德指数、轮廓系数、Calinski Harabaz指数...

    我们可以通过对一系列曲目进行聚类来创建歌曲的自动播放列表,我们可以展示如何自动创建相似歌曲的子组.通过我们现有的歌曲知识,我们能够验证该聚类练习的结果. 但是,如果我们对数据没有这种先验知识怎么办?如 ...

  8. kmeans及模型评估指标_机器学习模型评估指标总结

    常用机器学习算法包括分类.回归.聚类等几大类型,以下针对不同模型总结其评估指标 一.分类模型 常见的分类模型包括:逻辑回归.决策树.朴素贝叶斯.SVM.神经网络等,模型评估指标包括以下几种: (1)二 ...

  9. auuc 评估指标_机器学习性能评估指标汇总

    跑完分类模型(Logistic回归.决策树.神经网络等),我们经常面对一大堆模型评估的报表和指标,如ACC.ROC.AUC等,对以上提到的各个评估指标逐一点评,并力图表明: 指标分类 学习分类 性能指 ...

最新文章

  1. 清华大学《高级机器学习》课件和Fellow专家特邀报告(附pdf下载)
  2. 机器学习的数学基础 - 信息论
  3. 苹果iOS 15发布:关机也能定位,ASMR重度用户狂喜,这波库克又“去苹果化”了...
  4. ACM模板--邻接矩阵 有向图
  5. ubuntu下的能安装的百度网盘的资源最新网址
  6. 工作208:element $message居中测试无法实现
  7. linux驱动头文件说明
  8. 如何理解Unicode,UTF-8,UTF-16。
  9. 26.leetcode160_intersection_of_two_linked_lists
  10. Android Sqlite 工具类封装
  11. java 代码生成器 generator
  12. 关于安装VC++运行库遇到各种小问题
  13. 建立竞争情报系统 以监控助力企业危机公关
  14. U盘和移动硬盘不能安全删除问题及解决方案
  15. linux开机启动grub rescue,开机出现 grub rescue的解决方法探索
  16. 棋盘密码(Polybius)
  17. Android如何快速创建启动动画
  18. 点云配准NDT+ICP
  19. 招商银行信用卡2019届实习笔试题
  20. 万维网,互联网,因特网之间的区别

热门文章

  1. 交换第六天——HSRP、VRRP、GLBP、SPAN
  2. MYSQL监控-自带工具Query Profiler的使用
  3. 话里话外:实现信息化综合集成需要经历的五个阶段
  4. system-config-kickstart报错
  5. mysql 性能分析 命令_MySQL中使用SHOW PROFILE命令分析性能的用法整理
  6. 6 HBase java API访问HBase数据库
  7. 45 jump game II(贪心)
  8. go本地调用image-syncer
  9. 【收藏】IDEA中MAVEN项目自动导入依赖的启动与取消
  10. 【收藏】go博客 zxysilent / blog