200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Python学习记录 使用tensorflow 2.8 完成猫狗识别 使用keras构建CNN神经网络

Python学习记录 使用tensorflow 2.8 完成猫狗识别 使用keras构建CNN神经网络

时间:2022-12-01 10:24:53

相关推荐

Python学习记录 使用tensorflow 2.8 完成猫狗识别 使用keras构建CNN神经网络

猫狗识别

项目数据分为带标签和不带标签

带标签:25000张

不带标签:12500张

文章目录

猫狗识别数据分类处理图像增强预处理编写神经网络结构设置模型保存路径输入样本进入模型进行训练加载模型进行预测完整代码

数据分类处理

数据集可以从kaggle下载

/c/dogs-vs-cats

也可以从我网盘下载

链接:/s/1_A3H4nsL8xX4cmMEMtpACg?pwd=mpvi

提取码:mpvi

–来自百度网盘超级会员V7的分享

下载的数据存放在data文件夹下

创建用于创建文件夹的函数

# 如果文件夹不存在就创建def mkdir(path):if not os.path.exists(path):os.makedirs(path)

# 获取当前路径runPath = os.getcwd()data_dir =runPath + '/data/'mkdir(data_dir)

train是25000张带标签的猫狗图片test1是12500张无标签的猫狗图片

我们将这25000张带标签的猫狗图片进行分类

分为训练集和验证集

训练集 20000张 验证集 5000张

猫的训练数据保存在train/cat下 一共是10000张

猫的校验数据保存在valid/cat下一共是2500张

狗的训练数据保存在train/dog下 一共是10000张

狗的校验数据保存在valid/dog下一共是2500张

# 训练素材路径train_dir = data_dir + 'train/'mkdir(train_dir)# 校验素材路径valid_dir = data_dir + 'valid/'mkdir(valid_dir)# 猫训练素材文件夹cat_dir = train_dir + 'cat/'mkdir(cat_dir)# 猫校验素材文件夹cat_val_dir = valid_dir + 'cat/'mkdir(cat_val_dir)# 狗训练素材文件夹dog_dir = train_dir + 'dog/'mkdir(dog_dir)# 狗校验素材文件夹dog_val_dir = valid_dir + 'dog/'mkdir(dog_val_dir)

使用代码进行将这25000张带标签的猫狗图片进行分类

# 移动文件到指定文件夹def move_file(file_path, target_path):# 路径分离出文件名fileName = os.path.split(file_path)[1]# 拼接目标路径名target_path+='/'+fileNameprint(target_path)if os.path.exists(file_path):shutil.move(file_path, target_path)else:print('文件不存在')# 分离图片到指定文件夹def changeFile(filetype):test_file = []for i in range(0,12500,1):filename = train_dir+filetype+"."+str(i)+'.jpg'print(filename)# 训练数据10000if i < 10000:move_file(filename,train_dir +filetype)# 验证数据2500else:move_file(filename,valid_dir +filetype)# 分离猫changeFile('cat')# 分离狗changeFile('dog')

检查分类情况

目录情况

图像增强预处理

训练前,我们将全部的图像输入ImageDataGenerator进行图像增强预处理

参数可以自行修改

# 图像增强数据预处理# 返回训练集和校验集预处理模板def img_transforms():# 创建训练数据预处理模板train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / 255, # 所有数据集将乘以该数值(归一化,数据范围控制在0到1之间)rotation_range=40, # 随机旋转的范围width_shift_range=0.2, # 随机宽度偏移量height_shift_range=0.2, # 随机高度偏移量shear_range=0.2, # 随机错切变换zoom_range=0.2, # 随机缩放范围horizontal_flip=True, # 随机将一半图像水平翻转fill_mode='nearest', # 填充模式为最近点填充)# 从文件夹导入训练集train_generator = train_datagen.flow_from_directory(train_dir,# 训练数据文件夹target_size=(128, 128), # 处理后的图片大小128*128batch_size=64, # 每次训练导入多少张图片seed=7,# 随机数种子shuffle=True, # 随机打乱数据class_mode='categorical' # 返回2D的one-hot编码标签)# 创建校验数据预处理模板valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / 255, # 数据范围控制在0到1之间)# # 从文件夹导入校验集valid_generator = valid_datagen.flow_from_directory(valid_dir,# 校验数据文件夹target_size=(128, 128), # 处理后的图片大小128*128batch_size=64, # 每次训练导入多少张图片seed=7,# 随机数种子shuffle=False,# 随机打乱数据class_mode="categorical" # 返回2D的one-hot编码标签)return train_generator,valid_generator# 图像预处理train_generator,valid_generator = img_transforms()

编写神经网络结构

构建一个8层的神经网络,卷积层6层,全连接层2层,每两个卷积层添加一个池化层防止过拟合

# 编写神经网络# 参数1:样本宽# 参数2:样本高# 参数3:样本深度# 参数4:输出个数def cnn(width,height,depth,outputNum):# 按顺序添加神经层# 神经网络的层数指的是有权重计算的层,池化层不算层数# 该模型卷积层6层 全连接层2层 共8层model = tf.keras.models.Sequential([# Conv2D 向两个维度进行卷积/qq_37774098/article/details/111997250# 卷积层 输入样本为宽:128 高:128 深度:3tf.keras.layers.Conv2D(filters=32, # 32个过滤器kernel_size=3, # 核大小3x3padding='same', # same:边缘用0填充 valid:边缘不填充activation='relu', # 激活函数:reluinput_shape=[width, height, depth]), # 输入形状 宽:128 高:128 深度:3 不定义那就是默认输入的形状# 卷积层tf.keras.layers.Conv2D(filters=32,# 32个过滤器kernel_size=3,# 核大小3x3padding='same', # same:边缘用0填充 valid:边缘不填充activation='relu'),# 激活函数:relu# 池化层 /Chen_Swan/article/details/105486854# 池化层会不断地减小数据的空间大小,因此参数的数量和计算量也会下降,这在一定程度上也控制了过拟合tf.keras.layers.MaxPool2D(pool_size=2), # 池化核大小2x2# 卷积层tf.keras.layers.Conv2D(filters=64,# 64个过滤器kernel_size=3,# 核大小3x3padding='same',# same:边缘用0填充 valid:边缘不填充activation='relu'),# 激活函数:relu# 卷积层tf.keras.layers.Conv2D(filters=64,# 64个过滤器kernel_size=3,# 核大小3x3padding='same',# same:边缘用0填充 valid:边缘不填充 activation='relu'),# 激活函数:relu# 池化层tf.keras.layers.MaxPool2D(pool_size=2),# 池化核大小2x2# 卷积层tf.keras.layers.Conv2D(filters=128,# 128个过滤器kernel_size=3,# 核大小3x3padding='same',# 边缘用0填充activation='relu'),# 激活函数:relu# 卷积层tf.keras.layers.Conv2D(filters=128,# 128个过滤器kernel_size=3,# 核大小3x3padding='same',# 边缘用0填充activation='relu'),# 激活函数:relu# 池化层tf.keras.layers.MaxPool2D(pool_size=2),# 池化核大小2x2# 输入层的数据压成一维的数据tf.keras.layers.Flatten(),# 全连接层tf.keras.layers.Dense(128, activation='relu'),# 输出的维度大小128个特征点 激活函数:relutf.keras.layers.Dense(outputNum, activation='softmax') # 输出猫狗类型 2类 猫或者狗 激活函数:softmax 用于逻辑回归])# 模型处理# compile的用法:/yunfeather/article/details/pile(loss='categorical_crossentropy', # 损失函数 /qq_40661327/article/details/107034575optimizer='adam',# 优化器 metrics=['accuracy']) # 准确率# 打印模型每层的情况model.summary()return modelmodel = cnn(128,128,3,2)

设置模型保存路径

将模型保存在model文件夹下的catvsdog_weights.h5中

# 设置模型保存路径modelPath = './model'mkdir(modelPath)output_model_file = os.path.join(modelPath,"catvsdog_weights.h5")

输入样本进入模型进行训练

设置为回调模式,使用model.fit进行训练

使用EarlyStopping,当准确率没有提高超过一定幅度的话就会停止训练

# 打印学习信息def plot_learning_curves(history, label, epochs, min_value, max_value):data = {}data[label] = history.history[label]data['val_' + label] = history.history['val_' + label]pd.DataFrame(data).plot(figsize=(8, 5))plt.grid(True)plt.axis([0, epochs, min_value, max_value])plt.show()# 定义训练步数TRAIN_STEP = 100# 设置回调模式callbacks = [tf.keras.callbacks.TensorBoard(modelPath),tf.keras.callbacks.ModelCheckpoint(output_model_file,save_best_only=True,save_weights_only=True),tf.keras.callbacks.EarlyStopping(patience=5, min_delta=1e-3)]# 开始训练history = model.fit(train_generator,epochs=TRAIN_STEP,validation_data = valid_generator,callbacks = callbacks)# 显示训练曲线plot_learning_curves(history, 'accuracy', TRAIN_STEP, 0, 1)plot_learning_curves(history, 'loss', TRAIN_STEP, 0, 5)

可以看到训练到40步的时候准确率已经变化不大了

加载模型进行预测

准备两张要预测的图片

dog.jpg

cat.jpg

也可以直接使用test1下的图片进行预测,这里只是觉得这两张图可爱

# 预测# 参数1:要预测的图像cv2格式# 参数1:模型# 参数2:模型路径# 参数3:模型名称# 参数4:特征宽# 参数5:特征高# 参数6:特征深度# 参数7:结果1名称# 参数8:结果2名称def predict(cvImg,model,modelPath,modelName,width,height,depth,result1,result2):model_file = os.path.join(modelPath,modelName)# 加载模型model.load_weights(modelName)# 缩放图像减少检测时间img = cv2.resize(cvImg, (width, height))# 归一化img_arr = img / 255.0# 重构成模型需要输入的格式img_arr = img_arr.reshape((1, width, height, depth))# 输入模型进行预测pre = model.predict(img_arr)# 打印预测结果if pre[0][0] > pre[0][1]:print("识别结果是:"+result1+"\n概率:"+str(pre[0][0]))else:print("识别结果是:"+result2+"\n概率:"+str(pre[0][1]))img = cv2.imread("cat.jpg")cv2.imshow("img",img)predict(img,model,modelPath,"catvsdog_weights.h5",128,128,3,"猫","狗")cv2.waitKey(0)

识别结果为猫

识别结果为狗

随机从测试集中抽取一张图片进行预测

# 随机从测试集中读取文件test_dir = data_dir + "test1/"readImg = test_dir + str(random.randint(0,12499)) + ".jpg"img = cv2.imread(readImg)predict(img,model,modelPath,modelName,simpleWight,simpleHeight,simpleDepth,result1,result2)cv2.imshow("img",img)cv2.waitKey(0)

完整代码

import os# 设置LOG等级为 1 警告 2 错误os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# 0为使用CPU 1为使用GPUCPU = 1if CPU == 0 :os.environ['CUDA_VISIBLE_DEVICES'] = '-1'else :os.environ['CUDA_VISIBLE_DEVICES'] = '0'import randomimport shutilimport cv2import tensorflow as tfimport pandas as pdimport matplotlib.pyplot as plt# 模式选择:0 训练模型 1 预测图片mode = 1# 移动文件到指定文件夹def move_file(file_path, target_path):# 路径分离出文件名fileName = os.path.split(file_path)[1]# 拼接目标路径名target_path+='/'+fileNameprint(target_path)if os.path.exists(file_path):shutil.move(file_path, target_path)else:print('文件不存在')# 如果文件夹不存在就创建def mkdir(path):if not os.path.exists(path):os.makedirs(path)# 分离图片到指定文件夹def changeFile(filetype):test_file = []for i in range(0,12500,1):filename = train_dir+filetype+"."+str(i)+'.jpg'print(filename)# 训练数据10000if i < 10000:move_file(filename,train_dir +filetype)# 验证数据2500else:move_file(filename,valid_dir +filetype)# 图像增强数据预处理# 参数解释参考:# /fioletfly/article/details/101345584# /view/8f05e708ac45b307e87101f69e3143323968f5c6.html# 返回训练集和校验集预处理模板# 参数1:训练集文件夹路径# 参数2:校验集文件夹路径def img_transforms(train_dir,valid_dir):# 创建训练数据预处理模板train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / 255, # 所有数据集将乘以该数值(归一化,数据范围控制在0到1之间)rotation_range=40, # 随机旋转的范围width_shift_range=0.2, # 随机宽度偏移量height_shift_range=0.2, # 随机高度偏移量shear_range=0.2, # 随机错切变换zoom_range=0.2, # 随机缩放范围horizontal_flip=True, # 随机将一半图像水平翻转fill_mode='nearest', # 填充模式为最近点填充)# 从文件夹导入训练集train_generator = train_datagen.flow_from_directory(train_dir,# 训练数据文件夹target_size=(128, 128), # 处理后的图片大小128*128batch_size=64, # 每次训练导入多少张图片seed=7,# 随机数种子shuffle=True, # 随机打乱数据class_mode='categorical' # 返回2D的one-hot编码标签)# 创建校验数据预处理模板valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / 255, # 数据范围控制在0到1之间)# # 从文件夹导入校验集valid_generator = valid_datagen.flow_from_directory(valid_dir,# 校验数据文件夹target_size=(128, 128), # 处理后的图片大小128*128batch_size=64, # 每次训练导入多少张图片seed=7,# 随机数种子shuffle=False,# 随机打乱数据class_mode="categorical" # 返回2D的one-hot编码标签)return train_generator,valid_generator# 编写神经网络# 参数1:样本宽# 参数2:样本高# 参数3:样本深度# 参数4:输出个数def cnn(width,height,depth,outputNum):# 按顺序添加神经层# 神经网络的层数指的是有权重计算的层,池化层不算层数# 该模型卷积层6层 全连接层2层 共8层model = tf.keras.models.Sequential([# Conv2D 向两个维度进行卷积/qq_37774098/article/details/111997250# 卷积层 输入样本为宽:128 高:128 深度:3tf.keras.layers.Conv2D(filters=32, # 32个过滤器kernel_size=3, # 核大小3x3padding='same', # same:边缘用0填充 valid:边缘不填充activation='relu', # 激活函数:reluinput_shape=[width, height, depth]), # 输入形状 宽:128 高:128 深度:3 不定义那就是默认输入的形状# 卷积层tf.keras.layers.Conv2D(filters=32,# 32个过滤器kernel_size=3,# 核大小3x3padding='same', # same:边缘用0填充 valid:边缘不填充activation='relu'),# 激活函数:relu# 池化层 /Chen_Swan/article/details/105486854# 池化层会不断地减小数据的空间大小,因此参数的数量和计算量也会下降,这在一定程度上也控制了过拟合tf.keras.layers.MaxPool2D(pool_size=2), # 池化核大小2x2# 卷积层tf.keras.layers.Conv2D(filters=64,# 64个过滤器kernel_size=3,# 核大小3x3padding='same',# same:边缘用0填充 valid:边缘不填充activation='relu'),# 激活函数:relu# 卷积层tf.keras.layers.Conv2D(filters=64,# 64个过滤器kernel_size=3,# 核大小3x3padding='same',# same:边缘用0填充 valid:边缘不填充 activation='relu'),# 激活函数:relu# 池化层tf.keras.layers.MaxPool2D(pool_size=2),# 池化核大小2x2# 卷积层tf.keras.layers.Conv2D(filters=128,# 128个过滤器kernel_size=3,# 核大小3x3padding='same',# 边缘用0填充activation='relu'),# 激活函数:relu# 卷积层tf.keras.layers.Conv2D(filters=128,# 128个过滤器kernel_size=3,# 核大小3x3padding='same',# 边缘用0填充activation='relu'),# 激活函数:relu# 池化层tf.keras.layers.MaxPool2D(pool_size=2),# 池化核大小2x2# 输入层的数据压成一维的数据tf.keras.layers.Flatten(),# 全连接层tf.keras.layers.Dense(128, activation='relu'),# 输出的维度大小128个特征点 激活函数:relutf.keras.layers.Dense(outputNum, activation='softmax') # 输出猫狗类型 2类 猫或者狗 激活函数:softmax 用于逻辑回归])# 模型处理# compile的用法:/yunfeather/article/details/pile(loss='categorical_crossentropy', # 损失函数 /qq_40661327/article/details/107034575optimizer='adam',# 优化器 metrics=['accuracy']) # 准确率# 打印模型每层的情况model.summary()return model# 训练# 参数1:模型# 参数2:模型路径# 参数3:模型名称# 参数4:训练步数# 参数5:训练集# 参数6:校验集# 参数5:是否打印训练曲线def train(model,modelPath,modelName,step,train_generator,valid_generator,isplot=False):# 打印学习信息def plot_learning_curves(history, label, epochs, min_value, max_value):data = {}data[label] = history.history[label]data['val_' + label] = history.history['val_' + label]pd.DataFrame(data).plot(figsize=(8, 5))plt.grid(True)plt.axis([0, epochs, min_value, max_value])plt.show()output_model_file = os.path.join(modelPath,modelName)# 设置回调模式callbacks = [tf.keras.callbacks.TensorBoard(modelPath),tf.keras.callbacks.ModelCheckpoint(output_model_file,save_best_only=True,save_weights_only=True),tf.keras.callbacks.EarlyStopping(patience=5, min_delta=1e-3)]# 开始训练history = model.fit(train_generator,epochs=step,validation_data = valid_generator,callbacks = callbacks)if isplot:# 显示训练曲线plot_learning_curves(history, 'accuracy', TRAIN_STEP, 0, 1)plot_learning_curves(history, 'loss', TRAIN_STEP, 0, 5)# 预测# 参数1:要预测的图像cv2格式# 参数1:模型# 参数2:模型路径# 参数3:模型名称# 参数4:特征宽# 参数5:特征高# 参数6:特征深度# 参数7:结果1名称# 参数8:结果2名称def predict(cvImg,model,modelPath,modelName,width,height,depth,result1,result2):model_file = os.path.join(modelPath,modelName)# 加载模型model.load_weights(model_file)# 缩放图像减少检测时间img = cv2.resize(cvImg, (width, height))# 归一化img_arr = img / 255.0# 重构成模型需要输入的格式img_arr = img_arr.reshape((1, width, height, depth))# 输入模型进行预测pre = model.predict(img_arr)# 打印预测结果if pre[0][0] > pre[0][1]:print("识别结果是:"+result1+"\n概率:"+str(pre[0][0]))else:print("识别结果是:"+result2+"\n概率:"+str(pre[0][1]))# 获取当前路径runPath = os.getcwd()data_dir =runPath + '/data/'mkdir(data_dir)# 训练素材路径train_dir = data_dir + 'train/'mkdir(train_dir)# 校验素材路径valid_dir = data_dir + 'valid/'mkdir(valid_dir)# 猫训练素材文件夹cat_dir = train_dir + 'cat/'mkdir(cat_dir)# 猫校验素材文件夹cat_val_dir = valid_dir + 'cat/'mkdir(cat_val_dir)# 狗训练素材文件夹dog_dir = train_dir + 'dog/'mkdir(dog_dir)# 狗校验素材文件夹dog_val_dir = valid_dir + 'dog/'mkdir(dog_val_dir)# 设置模型保存路径modelPath = './model'mkdir(modelPath)# 测试模型名称modelName = "catvsdog_weights.h5"# 设置样本参数simpleWight = 128simpleHeight = 128simpleDepth = 3# 设置输出类型outputNum = 2result1 = "猫"result2 = "狗"# 定义训练步数TRAIN_STEP = 100# 搭建神经网络model = cnn(simpleWight,simpleHeight,simpleDepth,outputNum)if mode == 0:# 分离猫changeFile('cat')# 分离狗changeFile('dog')# 图像预处理train_generator,valid_generator = img_transforms(train_dir,valid_dir)# 训练模型train(model,modelPath,modelName,TRAIN_STEP,train_generator,valid_generator)elif mode == 1:#img = cv2.imread("dog.jpg")#predict(img,model,modelPath,modelName,simpleWight,simpleHeight,simpleDepth,result1,result2)#cv2.imshow("img",img)#cv2.waitKey(0)# 随机从测试集中读取文件test_dir = data_dir + "test1/"readImg = test_dir + str(random.randint(0,12499)) + ".jpg"img = cv2.imread(readImg)predict(img,model,modelPath,modelName,simpleWight,simpleHeight,simpleDepth,result1,result2)cv2.imshow("img",img)cv2.waitKey(0)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。