中国建设局网站查询,ui设计零基础到精通自学,wordpress 群晖设置,字体网站使用CNN实现简单的猫狗分类 完整代码见#xff1a;基于Keras3.x使用CNN实现简单的猫狗分类#xff0c;置信度约为#xff1a;85% 文章目录 概述项目整体目录环境版本注意 环境准备下载miniconda新建虚拟环境基于conda虚拟环境新建Pycharm项目下载分类需要用到的依赖 数据准备… 使用CNN实现简单的猫狗分类 完整代码见基于Keras3.x使用CNN实现简单的猫狗分类置信度约为85% 文章目录 概述项目整体目录环境版本注意 环境准备下载miniconda新建虚拟环境基于conda虚拟环境新建Pycharm项目下载分类需要用到的依赖 数据准备数据目录结构挪动图片可以采用下列代码 config准备训练、测试数据集构建模型训练模型训练过程损失和准确度曲线 测试模型使用带标签的测试图片评估整体准确率定义模型类预测单张图片将不带标签的测试图片分类并存到对应目录中源码 错误记录双重归一化问题 概述
项目整体目录 /data 存放数据集/model 存放训练好的模型/config.py 存储一些关键模型参数和路径信息等/dataset.py 返回数据增强后的数据集用于模型训练/model.py 定义模型/train.py 训练模型并绘制训练损失和准确度曲线/test.py 测试模型精准度
环境版本
python 3.11keras 3.9.2tensorflow 2.19.0
注意
本项目使用Keras3.x实现代码与keras 2.x有部分不同请仔细甄别
环境准备
下载miniconda
如果没有下载conda参照上一篇文章进行下载配置
新建虚拟环境
创建一个用于猫狗识别的虚拟环境可以指定py版本
conda create --name catanddog python3.11基于conda虚拟环境新建Pycharm项目
依次选择菜单路径 File-NewProject-Pure Python 在弹出的窗口选择
custom environmentSelect existingTypeconda选择刚刚新建的catanddog虚拟环境 如图
下载分类需要用到的依赖
主要用到keras3.9.2和tensorflow2.19.0
pip install keras数据准备
从Kaggle上下载常用的猫狗分类数据集下载下来后有训练数据共25000张猫狗各一半带标签命名示例dog.0.jpg和测试数据共12500张不带标签命名示例1.jgp。 将训练数据分为两份前20000张用于训练数据后5000张带标签的数据用于预测模型整体准确度。12500张测试数据可以用于单张图片的模型预测以及将猫狗分类后放入对应的目录中方便查看。 如图组织数据
test为12500张不带标签的测试数据test2为5000张带标签的测试数据train为20000张训练数据
数据目录结构
注意必须把训练数据、test2图片放在新建好的cats和dogs目录下模型才能自动推断标签
挪动图片可以采用下列代码
import os, shutil
# 将train_dir_tag_cat后2500张猫图像移动到test2_dir_tag_cat
cats [cat.{}.jpg.format(i) for i in range(1000)]
for cat in cats:src os.path.join(train_dir_tag_cat, cat)dst os.path.join(test2_dir_tag_cat, cat)shutil.move(src, dst)config
config.py用于存储一些关键参数和路径信息等。 训练的batch为32 训练15个EPOCH Author :Ayaki Shi
Date :2025/4/18 11:03
Description : 配置信息import os, shutildata_dir ./data# 训练集、测试集所在路径
test_dir os.path.join(data_dir, test)
test2_dir os.path.join(data_dir, test2)
train_dir os.path.join(data_dir, train)# 划分标签后的数据路径
train_dir_tag_cat os.path.join(train_dir, cats)
test_dir_tag_cat os.path.join(test_dir, cats)
test2_dir_tag_cat os.path.join(test2_dir, cats)train_dir_tag_dog os.path.join(train_dir, dogs)
test_dir_tag_dog os.path.join(test_dir, dogs)
test2_dir_tag_dog os.path.join(test2_dir, dogs)# 训练参数
IMG_SIZE (256, 256)
BATCH_SIZE 32
EPOCHS 15# 模型路径
MODEL_PATH ./model/CatAndDogClassifier.keras准备训练、测试数据集
dataset.py 训练数据经过数据增强后返回用于测试模型整体准确度的test2无需数据增强直接返回。 注意 这个方法ImageDataGenerator已经不推荐使用了因此使用image_dataset_from_directory这个方法可以根据目录自动推断标签只是数据增强稍微复杂了点 Author :Ayaki Shi
Date :2025/4/18 11:02
Description : 返回dataset
from keras.api.utils import image_dataset_from_directory
from config import train_dir,test2_dir, BATCH_SIZE,IMG_SIZE
from keras import layers, models
import tensorflow as tf# 数据增强
def create_augmentation_model():return models.Sequential([layers.RandomFlip(horizontal, seed42),layers.RandomRotation(0.2, fill_modenearest, seed42),layers.RandomZoom(0.2, fill_modenearest, seed42),layers.RandomContrast(0.3, seed42),layers.RandomTranslation(0.1, 0.1, fill_modenearest, seed42),], namedata_augmentation)def create_train_dataset():train_dataset image_dataset_from_directory(train_dir,label_mode binary,batch_size BATCH_SIZE,image_size IMG_SIZE,shuffleTrue, # 必须启用 shuffleseed42)# 创建预处理模型augmentation_model create_augmentation_model()# 定义预处理函数def preprocess_train(image, label):image augmentation_model(image, trainingTrue) # 训练模式激活增强return image, labeltrain_dataset train_dataset.map(preprocess_train,num_parallel_calls tf.data.AUTOTUNE)print(--------------返回增强后的训练数据集--------------)return train_dataset.prefetch(buffer_sizetf.data.AUTOTUNE)def create_test2_dataset():test2_dataset image_dataset_from_directory(test2_dir,label_mode binary,batch_size BATCH_SIZE,image_size IMG_SIZE,shuffleFalse)print(--------------返回测试数据集[带标签]--------------)return test2_dataset
构建模型
model.py 模型结构
输入层指定输入数据形状数据归一化四层卷积层和四层池化层交替展平层将输出的多维特征图展平为一维向量Dropout防止过拟合两个全连接层用于特征提取和最终分类 Author :Ayaki Shi
Date :2025/4/18 11:02
Description : 创建模型from keras import layers, models, optimizersfrom config import IMG_SIZEdef create_model():model models.Sequential([# 输入层指定输入数据形状layers.Input(shape(*IMG_SIZE, 3)),layers.Rescaling(1./255), # 归一化到 [0,1]# 四层卷积层和四层池化层layers.Conv2D(32, (3, 3), activationrelu),layers.MaxPooling2D(2, 2),layers.Conv2D(64, (3, 3), activationrelu),layers.MaxPooling2D(2, 2),layers.Conv2D(128, (3, 3), activationrelu),layers.MaxPooling2D(2, 2),layers.Conv2D(128, (3, 3), activationrelu),layers.MaxPooling2D(2, 2),# 展平层将输出的多维特征图展平为一维向量layers.Flatten(),# 防止过拟合layers.Dropout(0.5),# 两个全连接层用于特征提取和最终分类layers.Dense(512, activationrelu),layers.Dense(1, activationsigmoid)])# 编译模型model.compile(lossbinary_crossentropy, # 损失函数optimizer optimizers.Adam(learning_rate1e-4), # 优化器metrics[accuracy]) # 评估标准准确率print(--------------构建模型成功--------------)return model训练模型
train.py 获取数据集-创建模型-训练模型-保存模型-绘制损失和准确度曲线 Author :Ayaki Shi
Date :2025/4/18 16:08
Description : 训练模型
from dataset import create_train_dataset
from model import create_model
from config import EPOCHS, BATCH_SIZE, MODEL_PATH
import matplotlib.pyplot as pltdef train_model():# 获取datasettrain_dataset create_train_dataset()# 生成模型model create_model()# 训练模型print(--------------开始训练模型--------------)history model.fit(train_dataset,epochs EPOCHS,batch_size BATCH_SIZE)# 保存模型print(--------------开始保存模型--------------)model.save(MODEL_PATH)print(--------------开始绘制损失和准确性曲线--------------)# 绘制训练损失曲线plt.figure(figsize(10, 4))plt.plot(history.history[loss], labelTraining Loss, colorblue, markero)plt.title(Training Loss Over Epochs)plt.xlabel(Epochs)plt.ylabel(Loss)plt.legend()plt.grid(True)plt.show()# 绘制训练准确率曲线plt.figure(figsize(10, 4))plt.plot(history.history[accuracy], labelTraining Accuracy, colorgreen, markers)plt.title(Training Accuracy Over Epochs)plt.xlabel(Epochs)plt.ylabel(Accuracy)plt.legend()plt.grid(True)plt.show()if __name__ __main__:train_model()训练过程 损失和准确度曲线 测试模型
test.py
使用带标签的测试图片评估整体准确率
代码见后面可以看到整体准确度为85%左右
定义模型类
代码见后面
预测单张图片
代码见后面预测为狗的概率是73%。
将不带标签的测试图片分类并存到对应目录中
代码见后面可以看到大部分测试图片都被放到了正确的目录里但是也有少数错的 源码
from keras import models
import numpy as np
import os, shutil
from keras_preprocessing import image
from config import MODEL_PATH,IMG_SIZE,test_dir,test_dir_tag_cat,test_dir_tag_dogDOG_TAG_STR dog
CAT_TAG_STR cat
NUM_IMAGES 12500 # 测试图片数class CatAndDogClassifier:def __init__(self):self.model models.load_model(MODEL_PATH)print(模型加载成功)def predict_single_image(self, img_path):img image.load_img(img_path, target_sizeIMG_SIZE)img_array image.img_to_array(img)# 错误代码双重归一化# img_array np.expand_dims(img_array, axis0) / 255.0img_array np.expand_dims(img_array, axis0)prediction self.model.predict(img_array)[0][0]print(prediction)return DOG_TAG_STR if prediction 0.5 else CAT_TAG_STR, predictiondef classify_all_images(self):# 遍历所有图片# for i in range(1, NUM_IMAGES 1):filename for i in range(1, NUM_IMAGES 1):try:#文件名为1.jpg到12500.jpgfilename f{i}.jpgsrc_path os.path.join(test_dir, filename)# 跳过不存在的文件if not os.path.exists(src_path):print(fWarning: {filename} 不存在已跳过)continue# 进行预测label, confidence self.predict_single_image(src_path)# 确定目标目录dest_dir test_dir_tag_dog if label DOG_TAG_STR else test_dir_tag_catdest_path os.path.join(dest_dir, filename)# 移动文件shutil.move(src_path, dest_path)if i%500 0: # 打印12500行太多了每500行打印一次print(f[{i}/12500] {filename} - {dest_dir} (置信度: {confidence:.2%}))except Exception as e:print(f处理 {filename} 时发生错误: {str(e)})continuedef evaluate_model():from dataset import create_test2_datasettest2_dataset create_test2_dataset()model models.load_model(MODEL_PATH)loss, acc model.evaluate(test2_dataset)print(f\nTest accuracy: {acc:.2%})if __name__ __main__:# 初始化分类器classifier CatAndDogClassifier()# # 评估整体准确率# evaluate_model()# # 单张图片预测# img_path os.path.join(./data/train/dogs/dog.100.jpg)# label, prob classifier.predict_single_image(img_path)# print(f预测为: {label} (置信度: {prob if label DOG_TAG_STR else 1 - prob:.2%}))# 将不带标签的测试图片分类放入不同的文件夹classifier.classify_all_images()错误记录
双重归一化问题
在预测单张图片过程中出现了不管什么图片预测度总是特别低只有7%左右 首先预测结果不对第一时间考虑到是不是模型欠拟合或者过拟合的问题。 但是基于以下两个原因:
首先训练过程中记录的准确度和测试整体准确率都是85%说明模型大概率是没有问题的其次这个置信度已经低的离谱了 所以考虑是在测试单张图片对图片处理出现了问题经过排查发现问题出在了我在对单张图片进行了归一化然后模型中又进行了一次归一化导致预测置信度极低。 test.py