直接上代码,导入数据集搭建好框架就可以直接运行

数据集:Kritik Seth, "Fruits and Vegetables Image Recognition Dataset," Kaggle 2020 [https://www.kaggle.com/kritikseth/fruit-and-vegetable-image-recognition]

import tensorflow as tf
import matplotlib.pyplot as plt

training_set= tf.keras.utils.image_dataset_from_directory(
    'data/train',
    labels = 'inferred',
    label_mode= 'categorical',
    class_names=None,
    color_mode='rgb',
    batch_size=32,
    image_size=(224,224),
    shuffle= True,
    seed=None,
    validation_split=None,
    subset= None,
    interpolation = "bilinear",
    follow_links= False,
    crop_to_aspect_ratio = False
)

validation_set= tf.keras.utils.image_dataset_from_directory(
    'data/validation',
    labels = 'inferred',
    label_mode= 'categorical',
    class_names=None,
    color_mode='rgb',
    batch_size=32,
    image_size=(224,224),
    shuffle= True,
    seed=None,
    validation_split=None,
    subset= None,
    interpolation = "bilinear",
    follow_links= False,
    crop_to_aspect_ratio = False
)

CNN = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', input_shape=[224,224,3]),#卷积层,提取图像特征。
    tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu'),#卷积层,提取图像特征。
    tf.keras.layers.MaxPool2D(pool_size=2, strides=2),#池化层,对特征图进行下采样,降低数据量,减少模型计算量和内存消耗。
    tf.keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu'),#卷积层,进一步提取图像特征。
    tf.keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu'),#卷积层,进一步提取图像特征。
    tf.keras.layers.MaxPool2D(pool_size=2, strides=2),#池化层,对特征图进行下采样,降低数据量。
    tf.keras.layers.Flatten(),#将图像特征展平为一维向量,为全连接层做准备。
    tf.keras.layers.Dense(units=512, activation='relu'),#全连接层,学习更高级别的特征表示。
    tf.keras.layers.Dense(units=512, activation='relu'),#全连接层,学习更高级别的特征表示。
    tf.keras.layers.Dropout(0.5),#随机失活层,防止过拟合。
    tf.keras.layers.Dense(units=15, activation='softmax'),#输出层,使用 softmax 激活函数输出分类结果。
])

CNN.compile(optimizer="adam", loss='categorical_crossentropy', metrics=['accuracy'])
CNN.summary()

training_history= CNN.fit(x=training_set, validation_data=validation_set, epochs=15)
CNN.save('VStrained_model.h5')
training_history.history
#包含了以下键:
#'loss':每个训练周期结束时的训练损失值;
#'accuracy':每个训练周期结束时的训练精度;
#'val_loss':每个训练周期结束时的验证损失值;
#'val_accuracy':每个训练周期结束时的验证精度。

training_set.class_names    #将类别索引映射到类别名称

import json
with open('training_hist.json','w') as f:
  json.dump(training_history.history,f) #历史训练数据保存为json文件
  
  #如果需要重新载入:
  # import json
  # with open('training_hist.json', 'r') as f:
  #   training_history_loaded = json.load(f)

print(training_history.history.keys())#获取训练历史数据字典中的所有键

print("Validation Set Accuracy: {} %" .format(training_history.history['val_accuracy'][-1]*100))
print("Training Set Accuracy: {} %" .format(training_history.history['accuracy'][-1]*100))

epochs = [i for i in range(1, 40)]
plt.plot(training_history.history['accuracy'], color='red', label='Accuracy')
plt.plot(training_history.history['val_accuracy'], color='blue', label='Validation Accuracy')
plt.xlabel('Number of Epochs')
plt.ylabel('Training Accuracy & Validation Accuracy')
plt.title('Visualization of Training Accuracy & Validation Accuracy Result')
plt.legend()
plt.show()
#绘制训练准确度和验证准确度随着 epoch 数量变化的图表

plt.plot(training_history.history['loss'],color='red',label='Loss')
plt.plot(training_history.history['val_loss'],color='blue',label='Validation Loss')
plt.xlabel('Number of Epochs')
plt.ylabel('Training Loss & Validation Loss')
plt.title('Visualization of Training Loss & Validation Loss Result')
plt.legend()
plt.show()
#绘制损失

loss,accuracy=CNN.evaluate(training_set)#评估训练集性能
val_loss,val_accuracy=CNN.evaluate(validation_set)#评估验证集的性能

test_set= tf.keras.utils.image_dataset_from_directory(
    'data/test',
    labels = 'inferred',
    label_mode= 'categorical',
    class_names=None,
    color_mode='rgb',
    batch_size=32,
    image_size=(224,224),
    shuffle= True,
    seed=None,
    validation_split=None,
    subset= None,
    interpolation = "bilinear",
    follow_links= False,
    crop_to_aspect_ratio = False

)#设置测试集

test_loss,test_accuracy=CNN.evaluate(test_set)#评估测试集模型性能

test_accuracy*100

loaded_model = tf.keras.models.load_model('VStrained_model.h5')#加载模型

import numpy as np
from sklearn.metrics import confusion_matrix, classification_report

def get_true_labels_and_predictions(model, dataset):
    true_labels = []
    predicted_labels = []
    for images, labels in dataset:
        true_labels.extend(np.argmax(labels.numpy(), axis=1))
        predicted_labels.extend(np.argmax(model.predict(images), axis=1))
    return true_labels, predicted_labels

# Calculate metrics for the training dataset
train_true_labels, train_pred_labels = get_true_labels_and_predictions(CNN, training_set)
train_cm = confusion_matrix(train_true_labels, train_pred_labels)
train_report = classification_report(train_true_labels, train_pred_labels)

# Calculate metrics for the validation dataset
val_true_labels, val_pred_labels = get_true_labels_and_predictions(CNN, validation_set)
val_cm = confusion_matrix(val_true_labels, val_pred_labels)
val_report = classification_report(val_true_labels, val_pred_labels)

# Calculate metrics for the test dataset
test_true_labels, test_pred_labels = get_true_labels_and_predictions(CNN, test_set)
test_cm = confusion_matrix(test_true_labels, test_pred_labels)
test_report = classification_report(test_true_labels, test_pred_labels)

# Print or use the metrics as needed
print("Train Confusion Matrix:")
print(train_cm)
print("Train Classification Report:")
print(train_report)

print("\nValidation Confusion Matrix:")
print(val_cm)
print("Validation Classification Report:")
print(val_report)

print("\nTest Confusion Matrix:")
print(test_cm)
print("Test Classification Report:")
print(test_report)
#macro avg:对每个类别指标求平均后得到的值,值说明了模型在各个类别上的表现差异不大
#weighted avg是通过每个类别的样本数量进行加权平均得到的值,这说明模型对不同类别的样本都有不错的预测表现。

import seaborn as sns

def normalize_confusion_matrix(cm):
    # Normalize each row of the confusion matrix to sum up to 1
    row_sums = cm.sum(axis=1)
    normalized_cm = cm / row_sums[:, np.newaxis]
    return normalized_cm

train_cm_normalized = normalize_confusion_matrix(train_cm)
val_cm_normalized = normalize_confusion_matrix(val_cm)
test_cm_normalized = normalize_confusion_matrix(test_cm)

def plot_normalized_confusion_matrix(cm, class_names):
    plt.figure(figsize=(10, 8))
    sns.heatmap(cm, annot=True, xticklabels=class_names, yticklabels=class_names, cmap='Blues')
    plt.title('Normalized Confusion Matrix')
    plt.xlabel('Predicted Labels')
    plt.ylabel('True Labels')
    plt.show()

class_names = sorted(set(train_true_labels + val_true_labels + test_true_labels))

# Plot normalized confusion matrices for all datasets
plot_normalized_confusion_matrix(train_cm_normalized, class_names)
plot_normalized_confusion_matrix(val_cm_normalized, class_names)
plot_normalized_confusion_matrix(test_cm_normalized, class_names)
#可以看出模型整体准确度较高

#检索一些测试样本及其相应的真实标签
num_samples_to_display = 9
sample_images, sample_labels = next(iter(test_set.take(num_samples_to_display)))

#从test_set中获取相应的类名
class_names = test_set.class_names

#对采样图像进行预测
sample_predictions = CNN.predict(sample_images)
sample_predictions = np.argmax(sample_predictions, axis=1)

#显示带有真实标签和预测标签的图像
fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(10, 10),
                         subplot_kw={'xticks': [], 'yticks': []})

for i, ax in enumerate(axes.flat):
    ax.imshow(sample_images[i].numpy().astype(np.uint8))
    true_label = class_names[np.argmax(sample_labels[i])]
    predicted_label = class_names[sample_predictions[i]]
    ax.set_title(f"True: {true_label}\nPredicted: {predicted_label}")

plt.tight_layout()
plt.show()

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐