基于卷积神经网络的蔬菜水果识别
直接上代码,导入数据集搭建好框架就可以直接运行。
·
直接上代码,导入数据集搭建好框架就可以直接运行
数据集: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()
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)