Keras,训练期间验证集上的 auc 与 sklearn auc 不匹配

Posted

技术标签:

【中文标题】Keras,训练期间验证集上的 auc 与 sklearn auc 不匹配【英文标题】:Keras, auc on validation set during training does not match with sklearn auc 【发布时间】:2019-02-13 04:23:13 【问题描述】:

我正在使用我的测试集作为验证集。我使用了与How to compute Receiving Operating Characteristic (ROC) and AUC in keras?类似的方法

问题是我在训练期间的 val_auc 大约是 0.85,但是,当我使用时

fpr, tpr, _ = roc_curve(test_label, test_prediction)
roc_auc = auc(fpr, tpr)

我得到 0.60 的 auc。我知道他们使用不同的公式,并且流式 auc 可能与 sklearn 计算的公式不同。但是差异非常大,我无法弄清楚导致这种差异的原因。

# define roc_callback, inspired by https://github.com/keras-team/keras/issues/6050#issuecomment-329996505
def auc_roc(y_true, y_pred):
    # any tensorflow metric
    value, update_op = tf.contrib.metrics.streaming_auc(y_pred, y_true)

    # find all variables created for this metric
    metric_vars = [i for i in tf.local_variables() if 'auc_roc' in i.name.split('/')[1]]

    # Add metric variables to GLOBAL_VARIABLES collection.
    # They will be initialized for new session.
    for v in metric_vars:
        tf.add_to_collection(tf.GraphKeys.GLOBAL_VARIABLES, v)

    # force to update metric values
    with tf.control_dependencies([update_op]):
        value = tf.identity(value)
        return value

clf = Sequential()

clf.add(LSTM(units = 128, input_shape = (windowlength, trainX.shape[2]), return_sequences = True))#, kernel_regularizer=regularizers.l2(0.01)))

clf.add(Dropout(0.2))

clf.add(LSTM(units = 64, return_sequences = False))#, kernel_regularizer=regularizers.l2(0.01)))

clf.add(Dropout(0.2))

clf.add(Dense(units = 128, activation = 'relu'))
clf.add(Dropout(0.2))

clf.add(Dense(units = 128, activation = 'relu'))

clf.add(Dense(units = 1, activation = 'sigmoid'))
clf.compile(loss='binary_crossentropy', optimizer = 'adam', metrics = ['acc', auc_roc])

my_callbacks = [EarlyStopping(monitor='auc_roc', patience=50, verbose=1, mode='max')]
clf.fit(trainX, trainY, batch_size = 1000, epochs = 80, class_weight = class_weights, validation_data = (testX, testY), 
        verbose = 2, callbacks=my_callbacks)
y_pred_pro = model.predict_proba(testX)
print (roc_auc_score(y_test, y_pred_pro))

如果有人能引导我走向正确的方向,我真的很感激。

【问题讨论】:

我知道这已经很老了,但如果它回答了您的问题,您应该接受答案,如果没有,请提供反馈! 【参考方案1】:

首先,tf.contrib.metrics.streaming_auc 已弃用,请改用tf.metrics.auc

正如您所提到的,TF 使用与 Scikit-learn 不同的方法来计算 AUC。 TF 使用近似方法。引用其文档:

为了离散化 AUC 曲线,使用一组线性间隔的阈值来计算召回率和精度值对。

这几乎总是会给出比实际分数更高的 AUC 分数。此外,thresholds 参数默认为 200,如果您的数据集很大,则该参数较低。增加它应该会使分数更准确,但无论你设置多高,它总是会有一些错误。

另一方面,Scikit-learn 使用不同的方法计算“真实”AUC 分数。

我不知道 TF 使用近似方法的确切原因,但我猜是因为它的内存效率更高、速度更快。此外,虽然它高估了分数,但它很可能会保留模型的相对顺序:如果一个模型的 AUC 近似值比另一个模型更好,那么它的真实 AUC - 很可能 - 也会更好。

【讨论】:

以上是关于Keras,训练期间验证集上的 auc 与 sklearn auc 不匹配的主要内容,如果未能解决你的问题,请参考以下文章

Keras:使用批量标准化在同一数据集上的不同训练和验证结果

keras batchnorm 的测试性能很差

多个模型在测试集上的Accuracy以及AUC指标可视化对比实战

Keras cifar10 示例验证和测试损失低于训练损失

相同 Keras 模型和数据的准确度低于 AUC [关闭]

Keras 函数模型验证准确率高,但预测不正确