# 导入所需的库和模块
import os  # 对文件和目录进行操作
import numpy as np  # 处理数组和矩阵
import matplotlib.pyplot as plt  # 绘图库
import tensorflow as tf  # 深度学习框架
from tensorflow import keras  # TensorFlow中的高级API
from tensorflow.keras import layers  # TensorFlow中的各种层

# 定义训练集和测试集路径
train_dir = 'C:/Users/28938/Desktop/image/image/train'
test_dir = 'C:/Users/28938/Desktop/image/image/test'

# 定义类别标签
class_names = ['cats', 'dogs']

# 定义图像尺寸和批次大小
img_height = 224
img_width = 224
batch_size = 32

# 从目录中读取训练集和测试集
train_ds = keras.preprocessing.image_dataset_from_directory(
    train_dir,
    validation_split=0.2,  # 划分验证集的比例
    subset='training',  # 使用训练集的一部分作为训练集
    seed=42,  # 随机种子,保证每次运行时划分的数据集相同
    image_size=(img_height, img_width),  # 设置图像的大小
    batch_size=batch_size  # 设置批次大小
)
val_ds = keras.preprocessing.image_dataset_from_directory(
    train_dir,
    validation_split=0.2,  # 划分验证集的比例
    subset='validation',  # 使用训练集的一部分作为验证集
    seed=42,  # 随机种子,保证每次运行时划分的数据集相同
    image_size=(img_height, img_width),  # 设置图像的大小
    batch_size=batch_size  # 设置批次大小
)
test_ds = keras.preprocessing.image_dataset_from_directory(
    test_dir,
    seed=42,  # 随机种子,保证每次运行时划分的数据集相同
    image_size=(img_height, img_width),  # 设置图像的大小
    batch_size=batch_size  # 设置批次大小
)

# 定义数据增强器
data_augmentation = keras.Sequential(
    [
        layers.experimental.preprocessing.RandomFlip('horizontal', input_shape=(img_height, img_width, 3)),  # 随机水平翻转
        layers.experimental.preprocessing.RandomRotation(0.1),  # 随机旋转
        layers.experimental.preprocessing.RandomZoom(0.1),  # 随机缩放
        layers.experimental.preprocessing.RandomCrop(img_height, img_width),  # 随机裁剪
        layers.experimental.preprocessing.Rescaling(1./255),  # 像素值缩放到[0,1]之间
        layers.experimental.preprocessing.RandomContrast(0.1),  # 随机对比度
        layers.experimental.preprocessing.RandomSaturation(0.1),  # 随机饱和度
    ]
)

# 定义模型输入
input_shape = (img_height, img_width, 3)
model = keras.Sequential([
    data_augmentation,  # 数据增强
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=input_shape),  # 卷积层
    layers.MaxPooling2D(pool_size=(2, 2)),  # 最大池化层
    layers.Dropout(0.2),  # Dropout层,防止过拟合
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层
    layers.MaxPooling2D(pool_size=(2, 2)),  # 最大池化层
    layers.Dropout(0.2),  # Dropout层,防止过拟合
    layers.Conv2D(128, (3, 3), activation='relu'),  # 卷积层
    layers.MaxPooling2D(pool_size=(2, 2)),  # 最大池化层
    layers.Dropout(0.2),  # Dropout层,防止过拟合
    layers.Flatten(),  # 展平层,将多维输入一维化
    layers.Dense(128, activation='relu'),  # 全连接层
    layers.Dense(len(class_names), activation='softmax')  # 输出层,使用softmax激活函数进行多分类
])

# 编译模型
model.compile(optimizer='adam',  # 优化器,使用Adam算法
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),  # 损失函数,使用交叉熵损失
              metrics=['accuracy'])  # 评估指标,使用准确率

# 设定训练参数
epochs = 30  # 训练迭代次数

# 定义模型checkpoint
checkpoint_path = 'model_checkpoint/cp.ckpt'  # 模型权重保存路径
checkpoint_dir = os.path.dirname(checkpoint_path)  # 模型权重保存目录
checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,  # 模型保存路径
                                                save_weights_only=True,  # 只保存权重
                                                save_best_only=True,  # 只保存最好的模型
                                                monitor='val_accuracy',  # 监控指标为验证集准确率
                                                mode='max',  # 监控模式为最大值
                                                verbose=1)  # 显示保存信息

# 定义学习率衰减策略
lr_decay = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss',  # 监控指标为验证集损失
                                                factor=0.1,  # 学习率衰减因子
                                                patience=5,  # 没有改善时的停止轮数
                                                verbose=1,  # 显示学习率衰减信息
                                                mode='auto',  # 模式自动选择
                                                min_delta=0.0001,  # 最小变化量
                                                cooldown=0,  # 冷却时间
                                                min_lr=0)  # 最小学习率

# 开始训练模型
history = model.fit(train_ds,  # 训练集
                    validation_data=val_ds,  # 验证集
                    epochs=epochs,  # 训练迭代次数
                    callbacks=[checkpoint, lr_decay])  # 回调函数

# 加载最佳模型权重
model.load_weights(checkpoint_path)

# 对模型进行评估
test_loss, test_acc = model.evaluate(test_ds)  # 使用测试集评估模型
print('Test accuracy:', test_acc)

# 对模型进行预测
predictions = model.predict(test_ds)  # 使用测试集进行预测

# 混淆矩阵和分类报告
from sklearn.metrics import confusion_matrix, classification_report  # 导入混淆矩阵和分类报告函数

# 获取测试集真实标签
test_labels = []
for images, labels in test_ds:
    test_labels.append(labels.numpy())
test_labels = np.concatenate(test_labels)

# 获取预测标签
predicted_labels = np.argmax(predictions, axis=1)

# 计算混淆矩阵和分类报告
cm = confusion_matrix(test_labels, predicted_labels)  # 计算混淆矩阵
report = classification_report(test_labels, predicted_labels, target_names=class_names)  # 计算分类报告

# 打印混淆矩阵和分类报告
print('Confusion Matrix:')
print(cm)
print('
Classification Report:')
print(report)

# 绘制模型准确度和损失随时间变化的曲线
acc = history.history['accuracy']  # 获取训练集准确度随时间变化的曲线
val_acc = history.history['val_accuracy']  # 获取验证集准确度随时间变化的曲线
loss = history.history['loss']  # 获取训练集损失随时间变化的曲线
val_loss = history.history['val_loss']  # 获取验证集损失随时间变化的曲线
epochs_range = range(epochs)  # 定义迭代次数的范围
plt.figure(figsize=(8, 8))  # 创建一个图像窗口
plt.subplot(2, 1, 1)  # 创建子图,绘制训练集和验证集准确度随时间变化的曲线
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(2, 1, 2)  # 创建子图,绘制训练集和验证集损失随时间变化的曲线
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

# 选择一张测试图片
test_image_path = 'C:/Users/28938/Desktop/image/image/test/cats/cat.4004.jpg'

# 读取并预处理图片
img = keras.preprocessing.image.load_img(
    test_image_path, target_size=(img_height, img_width)
)
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0)  # 创建一个批次维度

# 预测图片类别
predictions = model.predict(img_array)
score = tf.nn.softmax(predictions[0])

# 显示图片和预测结果
plt.imshow(img)
plt.axis('off')
plt.show()
print('预测结果: {}, 置信度: {:.2f}%'.format(class_names[np.argmax(score)], 100 * np.max(score)))

# 打印数据集分类类别
print('数据集分类类别:', train_ds.class_names)

原文地址: https://www.cveoy.top/t/topic/pidw 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录