![](/img/trans.png)
[英]Tensorflow, Keras: In a multi-class classification, accuracy is high, but precision, recall, and f1-score is zero for most classes
[英]How to increase/improve precision, recall, and F1-Score on classification report?
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import confusion_matrix
import pandas as pd
from tensorflow.keras.preprocessing.image import ImageDataGenerator
>tf._version_
2.7.0
from google.colab import drive\
drive.mount('/content/gdrive')
驱动器已安装在 /content/gdrive; 要尝试强制重新挂载,请调用 drive.mount("/content/gdrive", force_remount=True)。
batch_size = 32
train_ds = tf.keras.utils.image_dataset_from_directory(
'/content/gdrive...',
validation_split=0.2,
subset="training",
seed=1337,
image_size=image_size,
batch_size=batch_size,
)
val_ds = tf.keras.utils.image_dataset_from_directory(
'/content/gdrive...',
validation_split=0.2,
subset="validation",
seed=1337,
image_size=image_size,
batch_size=batch_size,
)
test_ds = tf.keras.utils.image_dataset_from_directory(
'/content/gdrive...',
image_size=image_size,
batch_size=batch_size,
)
test_datagen = ImageDataGenerator(rescale = 1./255.,)
test_generator = test_datagen.flow_from_directory(
'/content/gdrive...',
shuffle=False,
class_mode = 'categorical',
)
找到属于 4 个类的 494 个文件。
使用 396 个文件进行训练。
找到属于 4 个类的 494 个文件。
使用 98 个文件进行验证。
找到属于 4 个类的 60 个文件。
找到属于 4 个类别的 60 张图像。\
print(class_names)
['篮球','足球','排球','水球']
plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
for i in range(16):
ax = plt.subplot(4, 4, i + 1)
plt.imshow(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
图片
normalization_layer = tf.keras.layers.Rescaling(1./255)
normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
print(np.min(first_image), np.max(first_image))
0.0 0.89000225
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
num_classes = 4
model = tf.keras.Sequential([
tf.keras.layers.Rescaling(1./255),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
model.compile(
optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
info=model.fit(
train_ds,
validation_data=val_ds,
epochs=15
)
纪元 1/15
13/13 [===============================] - 3s 129ms/step - loss: 1.4904 - accuracy: 0.3636 - val_loss :1.0347 - val_accuracy:0.5408
纪元 2/15
13/13 [==============================] - 1s 50ms/步 - 损失:0.9531 - 准确度:0.6086 - val_loss :1.0026 - val_accuracy:0.5204
时代 3/15
13/13 [===============================] - 1s 48ms/step - loss: 0.7760 - accuracy: 0.7348 - val_loss :0.9383 - val_accuracy:0.5612
时代 4/15
13/13 [===============================] - 1s 48ms/step - loss: 0.6378 - accuracy: 0.7778 - val_loss :0.5954 - val_accuracy:0.7653
5/15 纪元
13/13 [==============================] - 1s 47ms/step - loss: 0.4761 - accuracy: 0.8561 - val_loss :0.5973 - val_accuracy:0.7347
时代 6/15
13/13 [==============================] - 1s 48ms/步 - 损失:0.3942 - 准确度:0.8586 - val_loss :0.5779 - val_accuracy:0.7551
7/15 纪元
13/13 [==============================] - 1s 48ms/step - loss: 0.3948 - accuracy: 0.8662 - val_loss :0.6813 - val_accuracy:0.7449
时代 8/15
13/13 [==============================] - 1s 48ms/步 - 损失:0.2844 - 准确度:0.9015 - val_loss :0.7343 - val_accuracy:0.7143
纪元 9/15
13/13 [===============================] - 1s 48ms/step - loss: 0.2735 - accuracy: 0.8965 - val_loss :0.6145 - val_accuracy:0.8061
时代 10/15
13/13 [==============================] - 1s 49ms/步 - 损失:0.1997 - 准确度:0.9217 - val_loss :0.7033 - val_accuracy:0.7347
时代 11/15
13/13 [===============================] - 1s 47ms/step - loss: 0.1365 - accuracy: 0.9444 - val_loss :0.8867 - val_accuracy:0.6939
时代 12/15
13/13 [==============================] - 1s 47ms/step - loss: 0.1674 - accuracy: 0.9394 - val_loss :0.6450 - val_accuracy:0.7449
时代 13/15
13/13 [==============================] - 1s 47ms/步 - 损失:0.1869 - 准确度:0.9293 - val_loss :0.7596 - val_accuracy:0.7653
时代 14/15
13/13 [===============================] - 1s 47ms/step - loss: 0.1176 - accuracy: 0.9646 - val_loss :0.7559 - val_accuracy:0.7755
时代 15/15
13/13 [==============================] - 1s 47ms/step - loss: 0.0532 - accuracy: 0.9848 - val_loss : 0.7178 - val_accuracy: 0.7857\
model.summary()
accuracy = info.history['accuracy']
val_accuracy = info.history['val_accuracy']
loss = info.history['loss']
val_loss = info.history['val_loss']
plt.figure(figsize=(15,10))
plt.subplot(2, 2, 1)
plt.plot(accuracy, label = "Training accuracy")
plt.plot(val_accuracy, label="Validation accuracy")
plt.legend()
plt.title("Training vs validation accuracy")
plt.subplot(2,2,2)
plt.plot(loss, label = "Training loss")
plt.plot(val_loss, label="Validation loss")
plt.legend()
plt.title("Training vs validation loss")
plt.show()
pred = model.predict(test_ds)
>
y_pred = np.argmax(pred, axis=1)
y_pred_class={0: 'basketball',
1: 'soccerball',
2: 'volleyball',
3: 'waterpoloball'}
y_pred = list(map(lambda x: y_pred_class[x], y_pred))
y_true = test_generator.classe
y_true = list(map(lambda x: y_pred_class[x], y_true))
from sklearn.metrics import classification_report
print('Confusion Matrix:')
print(confusion_matrix(y_true, y_pred))
print('\n\n Classification Report:')
print(classification_report(y_true, y_pred))
您可以尝试很多事情。 最有效的方法之一是使用可调节的学习率。 这可以通过使用 Keras callabck ReduceLROnPlateau 来完成。 文档在这里。 您想设置回调来监控验证丢失。 如果“耐心”时期的损失未能改善,那么学习率将降低 new lr=old lr * factor 其中 factor 是介于 0 和 1 之间的浮点数。我用于此回调的设置显示在下面的代码
rlronp=tf.keras.callbacks.ReduceLROnPlateau( monitor="val_loss", factor=0.5,
patience=1, verbose=1)
我还建议使用 Keras 回调 EarlyStopping,文档在这里。 设置此回调以监控验证丢失。 如果验证损失未能改善“耐心”的时期数,训练将停止。 设置参数 restore_best_weights=True 以便如果此回调停止训练,它会加载您的 model 与来自具有最低验证损失的时期的权重。 我用于此回调的代码如下所示
estop=tf.keras.callbacks.EarlyStopping( monitor="val_loss", patience=4, verbose=1,
restore_best_weights=True)
现在您需要在 model.fit 中使用这些回调,因此在 model.fit 中包括
callbacks=[rlronp, estop]
试试这个,看看你是否能得到更好的结果。 您可能需要考虑进行迁移学习,而不是创建自己的 model。 对于图像分类,我喜欢使用 EfficientNetB3 model。 下面的代码显示了我的实现
base_model=tf.keras.applications.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
x=base_model.output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
x=Dropout(rate=.45, seed=123)(x)
output=Dense(num_classes, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
注意 EfficientNet 期望图像像素在 0 到 255 的范围内,因此不要重新缩放图像像素。
开发好的 model 的另一个重要因素是在平衡的训练集上对其进行训练。 我的意思是您希望各个类具有大约相等数量的图像样本。 以对狗和猫图像进行分类为例。 假设您有 900 张猫图像,而只有 100 张狗图像。 您的分类器将倾向于预测猫。 如果它总是预测 cat 它将有 90% 的准确率。 您可以做几件事。 一种是欠采样,只使用 200 张猫图像。 另一种是使用增强来增加狗样本的数量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.