多标签分类器的tensorflow自动精度计算

tensorflow automatic accuracy calculation for multilabel classifier

我正在为 (train_x, train_y) 安装多标签分类器,同时监控验证集的损失和准确性 (val_x, val_y):

classification_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0002),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])
classification_model.fit(train_x, train_y, validation_data=(val_x, val_y), \
        epochs=10,
        batch_size=10
)

这给出了以下输出:

Epoch 1/10
50/50 [==============================] - ETA: 0s - loss: 0.1186 - accuracy: 0.7094
Epoch 1: val_loss improved from 0.15329 to 0.11998, saving model to best_classification_model.tf
50/50 [==============================] - 12s 186ms/step - loss: 0.1186 - accuracy: 0.7094 - val_loss: 0.1200 - val_accuracy: 0.6280
Epoch 2/10
50/50 [==============================] - ETA: 0s - loss: 0.0848 - accuracy: 0.7776
Epoch 2: val_loss improved from 0.11998 to 0.10281, saving model to best_classification_model.tf
50/50 [==============================] - 8s 167ms/step - loss: 0.0848 - accuracy: 0.7776 - val_loss: 0.1028 - val_accuracy: 0.7200
Epoch 3/10
50/50 [==============================] - ETA: 0s - loss: 0.0652 - accuracy: 0.8176
Epoch 3: val_loss improved from 0.10281 to 0.09259, saving model to best_classification_model.tf
50/50 [==============================] - 10s 202ms/step - loss: 0.0652 - accuracy: 0.8176 - val_loss: 0.0926 - val_accuracy: 0.7560
Epoch 4/10
50/50 [==============================] - ETA: 0s - loss: 0.0522 - accuracy: 0.8236
Epoch 4: val_loss improved from 0.09259 to 0.08710, saving model to best_classification_model.tf
50/50 [==============================] - 10s 206ms/step - loss: 0.0522 - accuracy: 0.8236 - val_loss: 0.0871 - val_accuracy: 0.7480
Epoch 5/10
50/50 [==============================] - ETA: 0s - loss: 0.0418 - accuracy: 0.8337
Epoch 5: val_loss improved from 0.08710 to 0.08441, saving model to best_classification_model.tf
50/50 [==============================] - 10s 209ms/step - loss: 0.0418 - accuracy: 0.8337 - val_loss: 0.0844 - val_accuracy: 0.7640

我想知道这个准确度是如何计算出来的。 它计算正确标签的总数,还是所有标签的总行数? 什么是 'correct label'?是(内部)每个输出行的最大值吗?

澄清我对每个选项的意思:
正确标签总数:对于每张图片,输出20个标签,其中一些是0,一些是1。报告正确标签的总数(=正确0的数量+数量正确的 1s) 并将其除以标签总数 (= 20*num_images)。我不认为会发生这种情况,因为这可能会导致更高的准确性。只要预测到处都是 0,准确率就已经超过 90%!即使经过更长时间的训练,也不会发生这种情况。
所有标签正确的总行数: 计算所有标签正确(0 和 1)的图像数并除以图像数

模型输出和验证标签如下所示

>>> classification_model.predict(val_x)    # shape: (250, 20)
array([[ -9.385,  -5.443,  -8.274, ...,   1.936, -11.607,  -1.867],
       [-10.523,   3.074,  -7.765, ...,  -2.925, -10.35 ,  -2.602],
       [ -7.872,  -7.525,  -4.877, ...,  -6.434,  -9.063,  -8.485],
       ...,
       [ -6.04 ,  -4.826,   3.537, ...,  -5.68 ,  -7.276,  -6.05 ],
       [ -5.734,  -6.399,  -5.288, ...,  -5.495,  -6.673,   0.06 ],
       [ -9.458,  -7.892,   1.391, ...,  -6.422,  -9.75 ,  -7.702]],
      dtype=float32)
>>> val_y    # also shape: (250,20)
array([[0., 0., 0., ..., 0., 0., 1.],
       [0., 1., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 1., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 1.],
       [0., 0., 1., ..., 0., 0., 0.]])

当您使用 'accuracy' 时,您相信 Keras 会自动 select 在 BinaryAccuracy、CategoricalAccuracy 和 SparseCategoricalAccruacy 中为您提供一个指标。你会被没有被拾起的角落案例烧毁足够多的时间,你会发现它更容易明确。所以我会选择

metrics = [tf.keras.metrics.BinaryAccuracy(threshold=???)]

BinaryAccuracy 被计算为好像每个标签都是一个大桶的一部分。因此,如果您有两张图片,每张有 10 个可能的标签,在 multi-class 分类设置中,那么您将有 20 个可能的预测。二进制精度只是 TP + TN / 20。如果它对你有意义,它是一个“reduce_sum(axes=all)”而不是“(reduce_sum(reduce_mean(axis- 1) == 1))".

但 Keras 通常不会记录这些极端情况。您可以自己阅读代码(如果您使用“准确性”而不是实例化实际对象,这会变得更难)。或者 运行 实验。

此外,由于您输出的是 logits 而不是预测(例如,模型末尾没有 logistic / sigmoid 层),您的模型将输出 -inf 表示置信度为 0%,输出零表示置信度为 50%,和 +inf 表示 100% 置信度。将阈值放置在何处由您决定。典型的答案是 50% 的置信度,但如果你想调整 recall/recision/specificity,你可以将其向上或向下移动。要获得 50% 的置信度,如果您的模型输出 logits,您应该将阈值设置为 0.0,因为 0.0 的 logits 对应于 50%。

>>> tf.sigmoid(0.0)
<tf.Tensor: shape=(), dtype=float32, numpy=0.5>

你这样做。

m = tf.keras.metrics.BinaryAccuracy(threshold=0.0)

这里有一个例子,说明不正确控制 logits 的阈值会让你很痛苦。

In [12]: import tensorflow as tf

In [13]: y_true = tf.convert_to_tensor([[0,0,0],[0,1,1]])

In [14]: y_pred = tf.convert_to_tensor([[-.1, -.1, -.1], [.1, .1, .1]])

In [15]: m = tf.keras.metrics.BinaryAccuracy(threshold=0.0)

In [16]: m(y_true, y_pred)
Out[16]: <tf.Tensor: shape=(), dtype=float32, numpy=0.8333334>

In [17]: m = tf.keras.metrics.BinaryAccuracy() # default threshhold is 0.5

In [18]: m(y_true, y_pred)
Out[18]: <tf.Tensor: shape=(), dtype=float32, numpy=0.6666667>

抱歉,这么简单的事情很麻烦。欢迎使用 Tensorflow。