如何计算张量流中的矩阵相关系数

时间:2019-07-03 07:48:35

标签: python-2.7 tensorflow machine-learning tf.keras

所以我用tensorflow keras制作了一个模型,看起来工作正常。但是,我的主管说,计算马修斯相关系数及其已经计算出的精度和损耗将非常有用。

我的模型与此处的教程(https://www.tensorflow.org/tutorials/keras/basic_classification)中的代码非常相似,只是数据集要小得多。

是否有预构建的函数,或者我必须获取每个测试的预测并手动进行计算?

4 个答案:

答案 0 :(得分:6)

用于计算矩阵相关系数的预构建函数

sklearn.metrics.matthews_corrcoef(y_true, y_pred, sample_weight=None )

示例:

> from sklearn.metrics import matthews_corrcoef
> y_true = [+1, +1, +1, -1]
> y_pred = [+1, -1, +1, +1]
> matthews_corrcoef(y_true, y_pred) 

请参阅https://scikit-learn.org/stable/modules/model_evaluation.html#matthews-corrcoef

希望这会有所帮助。

答案 1 :(得分:1)

由于请求者接受了sklearn的Python版本,因此以下是纯Python中的Stewart_Rs答案:

from math import sqrt
def mcc(tp, fp, tn, fn):

    # https://stackoverflow.com/a/56875660/992687
    x = (tp + fp) * (tp + fn) * (tn + fp) * (tn + fn)
    return ((tp * tn) - (fp * fn)) / sqrt(x)

它具有通用性的优点,而不仅仅是评估二进制分类。

答案 2 :(得分:0)

开箱即用,但我们可以根据自定义指标中的公式进行计算。

您提供的基本分类链接用于多类分类问题,而Matthews相关系数专门用于二进制分类问题。

假设您的模型是以“正常”方式构建的,以解决此类问题(即y_pred是表示记录的“ True”预测概率的每条记录的介于0和1之间的数字,而标签均正好是{{ 1}}或0分别代表基本事实“ False”和“ True”),那么我们可以添加以下MCC指标:

1

我们可以将其包含在# if y_pred > threshold we predict true. # Sometimes we set this to something different to 0.5 if we have unbalanced categories threshold = 0.5 def mcc_metric(y_true, y_pred): predicted = tf.cast(tf.greater(y_pred, threshold), tf.float32) true_pos = tf.math.count_nonzero(predicted * y_true) true_neg = tf.math.count_nonzero((predicted - 1) * (y_true - 1)) false_pos = tf.math.count_nonzero(predicted * (y_true - 1)) false_neg = tf.math.count_nonzero((predicted - 1) * y_true) x = tf.cast((true_pos + false_pos) * (true_pos + false_neg) * (true_neg + false_pos) * (true_neg + false_neg), tf.float32) return tf.cast((true_pos * true_neg) - (false_pos * false_neg), tf.float32) / tf.sqrt(x) 调用中:

model.compile

示例

这是一个完整的示例,其中我们根据mnist位数是否大于4对它们进行分类:

model.compile(optimizer='adam',
              loss=tf.keras.losses.binary_crossentropy,
              metrics=['accuracy', mcc_metric])

输出:

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
y_train, y_test = 0 + (y_train > 4), 0 + (y_test > 4)

def mcc_metric(y_true, y_pred):
  predicted = tf.cast(tf.greater(y_pred, 0.5), tf.float32)
  true_pos = tf.math.count_nonzero(predicted * y_true)
  true_neg = tf.math.count_nonzero((predicted - 1) * (y_true - 1))
  false_pos = tf.math.count_nonzero(predicted * (y_true - 1))
  false_neg = tf.math.count_nonzero((predicted - 1) * y_true)
  x = tf.cast((true_pos + false_pos) * (true_pos + false_neg) 
      * (true_neg + false_pos) * (true_neg + false_neg), tf.float32)
  return tf.cast((true_pos * true_neg) - (false_pos * false_neg), tf.float32) / tf.sqrt(x)

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='relu'),
  tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.binary_crossentropy,
              metrics=['accuracy', mcc_metric])

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)

答案 3 :(得分:0)

这个问题的其他答案(例如,MCS的Keras / Tensorflow实现)在某种意义上是有限的,因为它需要二进制分类和单个输出列。如果不是您的设置,则该功能将为您提供错误的MCC值,而不会出现任何错误。

当然,可以为多类和多列输出计算MCC。以下是Keras(Tensorflow)MCC的常规自定义指标功能。

import tensorflow as tf
from keras import backend as K

def keras_calculate_mcc_from_conf(confusion_m):
    """tensor version of MCC calculation from confusion matrix"""
    # as in Gorodkin (2004)
    N = K.sum(confusion_m)
    up = N * tf.linalg.trace(confusion_m) - K.sum(tf.matmul(confusion_m, confusion_m))
    down_left = K.sqrt(N ** 2 - K.sum(tf.matmul(confusion_m, K.transpose(confusion_m))))
    down_right = K.sqrt(N ** 2 - K.sum(tf.matmul(K.transpose(confusion_m), confusion_m)))
    mcc_val = up / (down_left * down_right + K.epsilon())
    return mcc_val


def keras_better_to_categorical(y_pred_in):
    """tensor version of to_categorical"""
    nclass = K.shape(y_pred_in)[1]
    y_pred_argmax = K.argmax(y_pred_in, axis=1)
    y_pred = tf.one_hot(tf.cast(y_pred_argmax, tf.int32), depth=nclass)
    y_pred = tf.cast(y_pred, tf.float32)
    return y_pred


def mcc(y_true, y_pred):
    """To calculate Matthew's correlation coefficient for multi-class classification"""
    # this is necessary to make y_pred values of 0 or 1 because
    # y_pred may contain other value (e.g., 0.6890)
    y_pred = keras_better_to_categorical(y_pred)

    # now it's straightforward to calculate confusion matrix and MCC
    confusion_m = tf.matmul(K.transpose(y_true), y_pred)
    return keras_calculate_mcc_from_conf(confusion_m)


# test mcc
actuals = tf.constant([[1.0, 0], [1.0, 0], [0, 1.0], [1.0, 0]], dtype=tf.float32)
preds = tf.constant([[1.0, 0], [0, 1.0], [0, 1.0], [1.0, 0]], dtype=tf.float32)
mcc_val = mcc(actuals, preds)
print(K.eval(mcc_val))

还请注意,由于每批大小的度量标准计算,在迭代过程中从Keras打印的MCC值将不正确。拟合后,您只能通过调用“评估”或“评分”来信任MCC值。这是因为,与其他指标不同,整个样本的MCC并非各部分的总和/平均值。例如,如果您的批次大小为1,则在迭代过程中打印的MCC将为零。