为多标签分类生成 sklearn 指标的问题
Posted
技术标签:
【中文标题】为多标签分类生成 sklearn 指标的问题【英文标题】:Issues producing sklearn metrics for multi-label classification 【发布时间】:2021-12-06 02:09:24 【问题描述】:我已经在视网膜(眼睛)图像上实现了一个 EfficientNet 预训练模型,但我无法弄清楚为什么我的指标不起作用!如果这是问题,我愿意使用其他指标包(keras?)。
# Loading a pretrained conv base model
input_shape = (256, 256, 3)
conv_base = EfficientNetB7(weights=None, include_top=False, input_shape=input_shape)
dropout_rate = 0.2
number_of_classes = 3
initial_learning_rate=2e-5
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate,
decay_steps=100000,
decay_rate=0.96,
staircase=True
)
en_model = models.Sequential()
en_model.add(conv_base)
en_model.add(layers.GlobalMaxPooling2D(name='gap'))
# Avoid overfitting
en_model.add(layers.Dropout(rate=dropout_rate, name='dropout_out'))
# Set number_of_classes to the number of your final predictions
en_model.add(layers.Dense(number_of_classes, activation='sigmoid', name='fc_out')) #replaced softmax with sigmoid
conv_base.trainable = False
en_model.compile(
#loss='sparse_categorical_crossentropy',
#loss='categorical_crossentropy',
#optimizer=optimizers.RMSprop(learning_rate=2e-5),
loss='binary_crossentropy',
optimizer=optimizers.Adam(learning_rate=lr_schedule),
metrics=['accuracy']
)
history = en_model.fit(
train_generator,
steps_per_epoch=10,
epochs=100,
validation_data=val_generator,
#validation_steps=None,
validation_freq=1,
verbose=1,
callbacks=[tensorboard_callbacks],
use_multiprocessing=True,
workers=4
)
print('Average test loss: ', np.average(history.history['loss']))
指标 - 这是视网膜(眼睛)图像数据,共有三个类别/标签 - 糖尿病视网膜病变、青光眼和其他。我将展示第一类的代码,您可以在其中看到每个度量的数字相同,并且混淆矩阵为零。我不知道发生了什么!
from sklearn.metrics import confusion_matrix, accuracy_score, f1_score, precision_score, recall_score
# y_true are the labels from the validation generator; we have three labels (DR, glaucoma, other)
print(f'Accuracy = accuracy_score(val_generator.labels[:,0],[round(x) for x in val_pred[:,0]])')
print(f"F1 = f1_score(val_generator.labels[:,0],[round(x) for x in val_pred[:,0]], average='micro')")
print(f"Precision = precision_score(val_generator.labels[:,0],[round(x) for x in val_pred[:,0]], average='micro')")
print(f"Recall = recall_score(val_generator.labels[:,0],[round(x) for x in val_pred[:,0]], average='micro')")
print('Confusion matrix =')
confusion_matrix(val_generator.labels[:,0],[round(x) for x in val_pred[:,0]])
输出
Accuracy = 0.7807953443258971
F1 = 0.7807953443258971
Precision = 0.7807953443258971
Recall = 0.7807953443258971
Confusion matrix =
array([[805, 0],
[226, 0]])
上面的相同代码(用 1 和 2 替换 0)产生以下结果:
Accuracy = 0.8244422890397672
F1 = 0.8244422890397672
Precision = 0.8244422890397672
Recall = 0.8244422890397672
Confusion matrix =
array([[850, 0],
[181, 0]])
Accuracy = 0.6876818622696411
F1 = 0.6876818622696411
Precision = 0.6876818622696411
Recall = 0.6876818622696411
Confusion matrix =
array([[ 0, 322],
[ 0, 709]])
【问题讨论】:
【参考方案1】:Keras 和 Tensorflow 已经有很多 metrics(如果不是全部),如果您正在寻找替代品,您会提到:
!pip install -U tensorflow-addons
import tensorflow as tf
from tensorflow.python.keras.metrics import Accuracy
from tensorflow.python.keras.metrics import Recall
from tensorflow.python.keras.metrics import Precision
from tensorflow.python.keras.metrics import AUC
import tensorflow_addons as tfa
tf.math.confusion_matrix
tfa.metrics.F1Score
关于你的Sigmoid
激活函数,你提到你有3个类;为什么不考虑使用实际用于多类逻辑回归的Softmax
激活函数?您还必须将 binary_crossentropy
损失函数替换为 categorical_crossentropy
或 sparse_categorical_crossentropy
,具体取决于标签的编码方式。如果您有一个旨在预测零个或多个类别标签 (0, 1) 的多标签分类问题,那么binary_crossentropy
是您的正确选择。
【讨论】:
标签是 0 和 1。 那么一个热编码?糖尿病视网膜病变 --> 1, 0, 0, 青光眼 --> 0, 1, 0, and other --> 0, 0, 1? 如何导入这些指标。 import tf.keras.metrics.accuracy 给了我一个错误ModuleNotFoundError: No module named 'tf'
即使我已经将 tensorflow 导入为 tf.我也做了from tensorflow import keras
不是真正的 one-hot 编码,因为每个图像在所有三个类中都可以有一个 1。
检查您的 tensorflow 版本,以及它是否与网站上可用的指标匹配的版本以上是关于为多标签分类生成 sklearn 指标的问题的主要内容,如果未能解决你的问题,请参考以下文章