多标签分类器的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。
我正在为 (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。