【问题标题】:Tensorflow reporting wrong AUCTensorFlow 报告错误的 AUC
【发布时间】:2018-01-27 14:52:34
【问题描述】:

我在使用 tensorflow 库中的 AUC 时遇到问题。我每批训练我的模型(卷积神经网络)(我不使用验证集),并且在每个时期之后,我使用独立的测试集来获得我的评估。问题在于 AUC 评估。

在每批中,我计算训练集的 AUC/Accuracy/Loss/Precision/Recall/F1_score,然后汇总这些分数的平均值。当我尝试对测试集做同样的事情时,我再次计算出相同的分数。我注意到除 AUC 之外的所有分数都有不同的值。我认为增加测试的损失函数和增加 AUC 是不正确的。问题是测试的 AUC 与训练的 AUC 几乎相同(尽管它们的准确率、损失误差完全不同)。

    with tf.name_scope("output"):
        W = tf.Variable(tf.truncated_normal([num_filters_total, num_classes], stddev=0.1), name="W")
        b = tf.Variable(tf.constant(0.1, shape=[num_classes]), name="b")
        scores = tf.nn.xw_plus_b(h_drop, W, b, name="scores")
        predictions = tf.argmax(scores, 1, name="predictions")
        l2_loss += tf.nn.l2_loss(W, name="l2_loss")
        l2_loss += tf.nn.l2_loss(b, name="l2_loss")
        tf.summary.histogram("l2", l2_loss)
        tf.summary.histogram("weigths", W)
        tf.summary.histogram("biases", b)

    with tf.name_scope("auc_score"):
        # labelOut = tf.argmax(y_place_holder, 1)
        probability = tf.nn.softmax(scores)
        # auc_scoreTemp = streaming_auc(y_place_holder, probability, curve="PR")
        auc_scoreTemp = tf.metrics.auc(y_place_holder, probability, curve="PR")
        auc_score = tf.reduce_mean(tf.cast(auc_scoreTemp, tf.float32), name="auc_score")
        tf.summary.scalar("auc_score", auc_score)

    with tf.name_scope("accuracy"):
        labelOut = tf.argmax(y_place_holder, 1)
        correct_prediction = tf.equal(predictions, tf.argmax(y_place_holder, 1), name="correct_prediction")
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="accuracy")
        tf.summary.scalar("accuracy", accuracy)


    sess.run(tf.global_variables_initializer())
    sess.run(tf.local_variables_initializer())
    for batch in batches:
        x_batch, y_batch = list(zip(*batch))
        _,  accuracy_train, auc_training,  loss_train,  prec_batch, recall_batch, f1_batch \
            = sess.run([train_step,  accuracy, auc_score,  cross_entropy,  precision_mini_batch,
                        recall_mini_batch, f1_score_min_batch], feed_dict={x_place_holder: x_batch,
                                                                           y_place_holder: y_batch,
                                                                           emb_place_holder: vocab_inv_emb_dset,
                                                                           dropout_keep_prob: dropout_rate})
    ...
       for test_batch in test_batches:
                auc_test = None
                x_test_batch, y_test_batch = list(zip(*test_batch))

                accuracy_test, loss_test,  auc_test = sess.run([accuracy, cross_entropy, auc_score],
                       feed_dict={x_place_holder: x_test_batch,
                       y_place_holder: y_test_batch,
                       emb_place_holder: vocab_inv_emb_dset_val,
                       dropout_keep_prob: 1.0})

我还尝试使用始终返回 1 的 streaming_auc。

编辑

在每个 epoch 结束时,我通过运行来重置局部变量:

sess.run(tf.local_variables_initializer())

但第一批输出的结果非常糟糕。在第一批之后,我从测试集中得到了与训练结果不接近的正常结果。我不知道这是否是正确的方法,但这样的结果似乎更真实。

【问题讨论】:

    标签: tensorflow evaluation auc


    【解决方案1】:

    所有tf.metrics 返回一个值一个更新操作(参见here)。因此,如here 所述,您希望使用更新操作来累积值,然后评估auc_score 以检索累积值,如下所示:

    ...
    auc_score, auc_op = tf.metrics.auc(y_place_holder, probability, curve="PR")
    ...
    for batch in batches:
      sess.run([train_step,  accuracy, auc_op,  cross_entropy,...)
    ...
    py_auc = sess.run(auc)
    

    EDIT -- 展示 tf.metrics.auc 和 tf.contrib.metrics.streaming_auc 的玩具示例

    import tensorflow as tf
    from tensorflow.contrib import metrics
    batch_sz = 100
    noise_mag = 0.5
    nloop = 10
    
    tf.set_random_seed(0)
    
    batch_x = tf.random_uniform([batch_sz, 1], 0, 2, dtype=tf.int32)
    noise = noise_mag * tf.random_normal([batch_sz, 1])
    batch_y = tf.sigmoid(tf.to_float(batch_x) + noise)
    
    auc_val, auc_accum = tf.metrics.auc(batch_x, batch_y)
    
    #note: contrib.metrics.streaming_auc reverses labels, predictions
    auc_val2, auc_accum2 = metrics.streaming_auc(batch_y, batch_x)   
    
    with tf.Session() as sess:
        sess.run(tf.local_variables_initializer())
    
        for i in range(nloop):
            _ = sess.run([auc_accum, auc_accum2])
    
        auc, auc2 = sess.run([auc_val, auc_val2])
        print('Accumulated AUC = ', sess.run(auc_val))  #0.9238014
        print('Accumulated AUC2 = ', sess.run(auc_val)) #0.9238014
    

    【讨论】:

    • 我尝试了您建议的方法。我在每个批次中使用 auc_op,在批次结束时我调用 auc_score。但是对于 streaming_auc 问题仍然存在(即使我更改了 num_threshold,我总是得到结果 = 1 的训练和测试)。对于metrics.auc(不是streaming_auc),我再次收到非常相似的值,但在这种情况下,第一批有OK结果。
    • 我不知道它是否有帮助,但我在答案中添加了一个独立的示例,显示了操作的功能
    • 我在某处读到 AUC 是基于局部变量的,因此您需要在新的测试集中使用它之前重置局部变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 2020-07-01
    • 1970-01-01
    • 2013-01-21
    • 2015-11-05
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多