繁体   English   中英

如何增加/提高分类报告的准确率、召回率和 F1-Score?

[英]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()

model总结

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM