使用Keras计算Matthews相关系数

9

我有一个在Python 3中的Keras模型(Sequential):

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.matthews_correlation = []

    def on_epoch_end(self, batch, logs={}):
        self.matthews_correlation.append(logs.get('matthews_correlation'))
...    
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['matthews_correlation'])
history = LossHistory()
model.fit(Xtrain, Ytrain, nb_epoch=10, batch_size=10, callbacks=[history])
scores = model.evaluate(Xtest, Ytest, verbose=1)

...
MCC = matthews_correlation(Ytest, predictions)

model.fit()方法打印出 - 据说是根据metrics = ['matthews_correlation']部分 - 进展和Matthews Correlation Coefficient(MCC). 但它们与最终的MCC相差很大。最终的MCC函数给出了预测的整体MCC,并与sklearn的MCC函数一致(即我相信这个值)。

1) model.evaluate()的得分是什么?它们与最终的MCC或每个epoch的MCC完全不同。

2) 每个epoch的MCC是什么?看起来像这样:

Epoch 1/10 580/580 [===========] - 0s - loss: 0.2500 - matthews_correlation: -0.5817

它们是如何计算的,为什么它们与最终的MCC差别如此之大?

3) 我能否在on_epoch_train()函数中添加matthews_correlation()函数?然后我可以独立计算并打印MCC结果。我不知道Keras隐含地做了什么。

感谢您的帮助。

编辑:这里是一个记录损失历史记录的示例。如果我打印(history.matthews_correlation),我会得到与进度报告给我的相同MCC的列表。

1个回答

9
你的MCC为负的原因可能是Keras实现中最近修复的错误导致。查看这个问题
解决问题的方法可能是从GitHub主分支重新安装Keras,或者编写自己的回调(如此处所述),并在问题中进行修复:
import keras.backend as K
def matthews_correlation(y_true, y_pred):
    y_pred_pos = K.round(K.clip(y_pred, 0, 1))
    y_pred_neg = 1 - y_pred_pos

    y_pos = K.round(K.clip(y_true, 0, 1))
    y_neg = 1 - y_pos

    tp = K.sum(y_pos * y_pred_pos)
    tn = K.sum(y_neg * y_pred_neg)

    fp = K.sum(y_neg * y_pred_pos)
    fn = K.sum(y_pos * y_pred_neg)

    numerator = (tp * tn - fp * fn)
    denominator = K.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn))

    return numerator / (denominator + K.epsilon())

这解释了scikit learn MCC和Keras MCC之间的区别,感谢您引起我对Keras新版本的注意。 - ste
如果我使用这个实现,就会出现错误:'''ValueError: An operation has None for gradient. Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.''' - tag
@tag 这段代码是针对Keras 1.2版本的。最新版本为2.2,因此底层接口可能已经发生了变化。有关自定义指标的定义,请参考最新文档 https://keras.io/metrics/。 - Matt07
2
我可以确认这在使用TensorFlow 2.0 API的Keras上运行良好。 - YOLO
1
MCC代码假定具有单列输出的二元分类。因此,如果您具有具有双列输出的二元分类模型,则得到的MCC将完全错误。请注意,MCC是相关系数,因此其值介于-1和1之间。 - Tae-Sung Shin
正确,它假定输出为单列,即二元分类任务。感谢您指出这一点。 关于MCC在[-1,1]之间的问题,这也是正确的,尽管0意味着标签和预测之间没有相关性(随机预测),而-1则意味着反相关。因此,在实践中很少会低于零(您的模型应该比随机猜测分类器更差),特别是在几个时期的训练后。如果发生这种情况,则可能存在错误。 - Matt07

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接