用于敏感性和特异性的二进制分类器 Keras 回调?

Posted

技术标签:

【中文标题】用于敏感性和特异性的二进制分类器 Keras 回调?【英文标题】:Binary classifier Keras callback for sensitivity and specificity? 【发布时间】:2018-12-20 07:01:07 【问题描述】:

class_mode='binary' 时如何获得敏感性和特异性? - 我目前的解决方案适用于class_mode='categorical'

from keras.callbacks import Callback
import numpy as np
from sklearn.metrics import confusion_matrix


class SensitivitySpecificityCallback(Callback):
    def on_epoch_end(self, epoch, logs=None):
        if epoch:
            x_test, y_test = self.validation_data[0], self.validation_data[1]
            predictions = self.model.predict(x_test)
            output_sensitivity_specificity(epoch, predictions, y_test)


def output_sensitivity_specificity(epoch, predictions, y_test):
    y_test = np.argmax(y_test, axis=-1)
    predictions = np.argmax(predictions, axis=-1)
    c = confusion_matrix(y_test, predictions)
    print('Confusion matrix:\n', c)
    print('[:03d] sensitivity'.format(epoch), c[0, 0] / (c[0, 1] + c[0, 0]))
    print('[:03d] specificity'.format(epoch), c[1, 1] / (c[1, 1] + c[1, 0]))

82 source lines full code example(兼容 Python 2 和 3)

所有的输出都是错误的:

Confusion matrix:
 [[40]]
Traceback (most recent call last):
  File "network.py", line 118, in <module>
    callbacks=[SensitivitySpecificityCallback()], verbose=1)
  File "lib/python2.7/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "lib/python2.7/site-packages/keras/engine/training.py", line 1426, in fit_generator
    initial_epoch=initial_epoch)
  File "lib/python2.7/site-packages/keras/engine/training_generator.py", line 229, in fit_generator
    callbacks.on_epoch_end(epoch, epoch_logs)
  File "lib/python2.7/site-packages/keras/callbacks.py", line 77, in on_epoch_end
    callback.on_epoch_end(epoch, logs)
  File "network.py", line 56, in on_epoch_end
    output_sensitivity_specificity(epoch, predictions, y_test)
  File "network.py", line 64, in output_sensitivity_specificity
    print('[:03d] sensitivity'.format(epoch), c[0, 0] / (c[0, 1] + c[0, 0]))
IndexError: index 1 is out of bounds for axis 1 with size 1

【问题讨论】:

【参考方案1】:

由于在二进制模式下,您实际上是在预测一个表示正类概率的值(即二进制分类),因此在预测中使用 .argmax() 总是返回 0。因此,您需要针对这种情况修改您的 output_sensitivity_specificity 函数:

def output_sensitivity_specificity(epoch, predictions, y_test, mode='binary'):
    if mode == 'binary':
        # determine positive class predictions
        idx = predictions >= 0.5
        predictions = np.zeros(predictions.shape)
        predictions[idx] = 1
        # no need to modify y_test since it consists of zeros and ones already
    else:
        y_test = np.argmax(y_test, axis=-1)
        predictions = np.argmax(predictions, axis=-1)

    c = confusion_matrix(y_test, predictions)
    print('Confusion matrix:\n', c)
    print('[:03d] sensitivity'.format(epoch), c[0, 0] / (c[0, 1] + c[0, 0]))
    print('[:03d] specificity'.format(epoch), c[1, 1] / (c[1, 1] + c[1, 0]))

在您的回调中调用output_sensitivity_specificity 时只需传递mode=class_mode,它适用于二进制和分类模式。

【讨论】:

嗯,我试过了,但在这一行得到了IndexError: too many indices for arraypredictions[idx] = 1 @AT 抱歉,我现在无法测试。我一定犯了一个愚蠢的错误。您能否在错误发生的行之前打印predictionsidx 的形状并告诉我它们是什么? @AT 我编辑了我的帖子。只需将predictions = np.zeros((predictions.shape[0],)) 更改为predictions = np.zeros(predictions.shape) @AT 只是好奇,它不适合你吗?还是有问题吗? ? 谢谢,它成功了。我的网络似乎没有使用二进制或分类,所以我会问一个问题,我有话要说?

以上是关于用于敏感性和特异性的二进制分类器 Keras 回调?的主要内容,如果未能解决你的问题,请参考以下文章

在 R 中计算具有不同阈值的敏感性、特异性、NPV 和 PPV

对象检测/分类任务的性能指标(用于图像)

如何从 sklearn gridsearchcv 获取敏感性和特异性(真阳性率和真阴性率)?

AUC 评价指标详解,准确率(ACC),敏感性(sensitivity),特异性(specificity)计算 Python3TensorFlow2入门手册

R语言的ROC分析

利用二维卷积神经网络进行乳腺癌分类