深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 一)
深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 二)

前面两篇博文已经介绍了如何利用keras搭建出简单的模型,接下来,在前面训练好的基础上,进行模型的使用。即调用训练好的模型对图片进行预测。

1、调用模型进行图片预测

需要注意的是,前面为了快速训练模型,并未开启save功能,此处需要开启之。以便保存模型,保存模型的方法还有很多,读者可以自行百度之,此处提供一种帮助大家学习。

下面直接给出demo代码

import matplotlib.pyplot as plt
import pathlib   #本例中用于对输入输出的路径进行管理的包,直接pip即可安装
import tensorflow as tfIMG_HEIGHT = 200
IMG_WIDTH = 200"""
博主之前跑过好几个不同的模型,因此在前面保存模型时,命名为model_9,
读者也可以根据实际情况设置模型的名称
定位模型的位置后,利用tf.keras.models.load_model()导入模型"""
model = tf.keras.models.load_model('D:/Desktop/catVSdog/model_9')
#设置测试集的图片来源
data_root = pathlib.Path('D:/Desktop/catVSdog/data/test')
all_image_paths = list(data_root.glob('*/'))
all_image_paths = [str(path) for path in all_image_paths]#由于网络结构已经训练好,且已经固定,因此对喂入的图片需要经过预处理操作
def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=3)image = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])image /= 255.0  #与之前一样,进行归一化操作return image#加载图片
def load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)i = 1
while i > 0:i = int(input("请输入你想要检测的图片序号(1-12500):"))if i > 12500:print("超出列表索引范围,请重新输入")continueelse:passimage = load_and_preprocess_image(all_image_paths[i])image_array = tf.keras.preprocessing.image.img_to_array(image)"""之前喂入的是以(batchsize,200,200,3)的格式喂入,再次预测时,也需要使之符合前面的结构,此处预测,我们用到的batchsize为1,此处仅作为测试案例,真实预测时,可以一次性喂入更多的图片,充分利用GPU减少I/O的损耗此处的输入需要增加一个维度,因此需要变为(1,200,200,3)"""image_array = tf.expand_dims(image_array, 0)"""利用predict(),喂入图片,模型将返回预测结果,根据前面模型的定义,当输出的值<0时为猫,当输出的值 >0时为狗"""prediction = int(model.predict(image_array))plt.imshow(image)if prediction > 0:title = "Dog"else:title = "Cat"plt.title(("This is a " + title))#在其标题上显示预测结果plt.show() #缺少这一句将无法正常显示图片

下面时运行结果,可以看出,模型能够很好的分辨出猫和狗的图片

再贴出几张预测的图片,看看效果



对上面的代码稍加更改,即可获得下面一段利用模型进行预测并将预测结果写入csv文件的代码,运行后得到submission文件(这个文件是前面下载数据集时一同下载的,提交需要按照官方给出的格式,0代表猫,1代表狗,这里需要和上段代码中的逻辑输出值进行区分)

代码执行成功后,即可提交到kaggle网站

import numpy as np
import pathlib
import tensorflow as tfIMG_HEIGHT = 200
IMG_WIDTH = 200model = tf.keras.models.load_model('D:/Desktop/catVSdog/model_9')
data_root = pathlib.Path('D:/Desktop/catVSdog/data/test')
all_image_paths = list(data_root.glob('*/'))
all_image_paths = [str(path) for path in all_image_paths]def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=3)image = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])image /= 255.0return imagedef load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)import re
import pandas as pdlabel = np.zeros(12501, dtype=int)
"""
博主这里用的方法效率很低,但是非常简单易懂,
事实上,如果按照batch来喂入,GPU将会得到更好的利用,加快预测的时间,
后期博主还会添加利用dataset方法喂入图片,使得推理过程更加高效
"""
for i in range(12500):image = load_and_preprocess_image(all_image_paths[i])id = int(re.sub("\D", "", all_image_paths[i]))image_array = tf.keras.preprocessing.image.img_to_array(image)image_array = tf.expand_dims(image_array, 0)prediction = int(model.predict(image_array))if i % 100 == 0:print("Predict the %d photo" % (i))if prediction > 0:label[id] = 1else:label[id] = 0label = label.tolist()
dataframe = pd.DataFrame({'label': label})
dataframe.to_csv('model_9_submission.csv', sep=',')
#此处的输出可以根据自己的实际情况决定

下面是博主提交时得到的分数

kaggle上面还有各路大神,这个分数越低越好,具体的计算方法可以百度一下kaggle比赛分数计算的方法。
博主这个分数还是不太够看,但是作为刚入门的选手,这个猫狗大战更多的是让我们在实战中学会如何使用已有的知识和便捷的框架,搭建出一个还算不错的模型。

2、项目小结

1)项目总结
整个项目完成下来,给我的感觉就是keras使用还是非常方便的,利用Sequential结构,我们可以像搭建积木一样,将每一层堆叠到一起,快速的实现整个模型,特别是对于像vgg架构的网络,诸如vgg11,16,19等,都是可以很好的复现出来。再者,猫狗大战这个项目,也使得我们可以快速入门CNN的学习,其中出现的各类细节问题,也是我们完成整个项目下来最大的收获,例如利用管道的方式实现数据的实时增强,并喂入神经网络,使得我们的模型能够具有非常好的泛化能力,减少过拟合现象的发生。

值得注意的是,Sequential它有比较大的缺点,就是使得整个网络结构较为简单整齐,对于诸如InceptionNet,ResNet等复杂的架构,实现比较困难(可以通过嵌套Inecption块和resnet块的方式实现,但是比较麻烦,不如直接函数,利用函数的方式定义使整个模型简单易懂便于调试,后期还会有补充)。

因此,后续博主还会补充关于利用函数的方式搭建模型,利用类的方式搭建模型的方法,有了这些方法,并且配合keras我们可以搭建出更多结构更复杂,表现力更强的网络。
另外,前述的predict还有很大的改进空间,改进后可以更方便且高效地利用GPU,减少I/O耗费的时间。而关于运行模型的过程,时间非常长,博主运行在笔记本电脑,主要用的是intel i5 9代的处理器,gtx1650的显卡(4g显存,这也导致batchsize比较小,训练稍慢),这个配置玩玩游戏还说得过去,在2020年属于中低端游戏本,平时写写代码也很好用,但是拿它跑神经网络,倒是确实有些吃不消。

博主是分段跑的,也建议这么做,因为分段跑,可以分段观察整个模型的运行情况,当出现过拟合现象时,通过调整dropout的值,对这种现象进行一定程度的缓解。

博主在训练过程中,注意到如果数据增强得太严重,也就是说旋转度数太大,或者进行竖直翻转,会使得整个模型变得极其难以收敛,或许是因为训练得程度还不够,优化还不太足,但是这确实是个比较大的问题,后期博主还会继续补充相关的解释和解决方法。

前前后后跑了100多个epochs(具体没统计),总共花了10-20个小时的时间,模型跑下来,训练集的准确率最高到98.0%,而最高的验证集准确率能够达到93.5%左右,略微出现了过拟合,这说明模型还有很大的改进空间,当然了,作为入门级的模型,这个精度还算可以。

也可以利用vgg模型,resnet,googlenet等预训练的模型,将输出层替换为自己的设计的输出层,利用其在imagenet1000分类的预训练权重,加快训练的速度,提升效果。

接下来的项目,将是利用模型实现对验证码的破解,这个项目中根据猫狗大战项目的经验,进行了一定的优化。后续将补充出链接。

2)最后给出整个项目用到的完整代码:

其实前面的内容以及把所有用到的代码给出来了,这里只是整合到一起,方便快速部署。
train.py (前面的博客已经分部分给出,此处只是整理到一起)

# 导入包"""
python==3.7
Tensorflow-gpu==2.1
"""
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
import os
import time
import matplotlib.pyplot as plt# 下面的代码用于设置指定的GPU,根据需求使用即可
# os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
# os.environ["CUDA_VISIBLE_DEVICES"] = "0"
# devices = tf.config.experimental.list_physical_devices('GPU')
# 设置显存随用随涨,而不是全部一起被分配
# tf.config.experimental.set_memory_growth(devices[0], True)start = time.time()# 设置目录路径
PATH = os.path.join('D:/Desktop/catVSdog/data')  # 图片数据集的根目录
# 将目录区分位猫狗训练集和验证集
train_dir = os.path.join(PATH, 'train')  # train数据集 相对于根目录
validation_dir = os.path.join(PATH, 'validation')  # validation数据集 相对于根目录
train_cats_dir = os.path.join(train_dir, 'cats')  # train目录下的文件夹 每个会在之后分为一类
train_dogs_dir = os.path.join(train_dir, 'dogs')
validation_cats_dir = os.path.join(validation_dir, 'cats')  # validation目录下的文件夹 每个会在之后分为一类
validation_dogs_dir = os.path.join(validation_dir, 'dogs')num_cats_tr = len(os.listdir(train_cats_dir))
num_dogs_tr = len(os.listdir(train_dogs_dir))num_cats_val = len(os.listdir(validation_cats_dir))
num_dogs_val = len(os.listdir(validation_dogs_dir))total_train = num_cats_tr + num_dogs_tr  # 文件数量求和 方便 后续处理和代码复用
total_val = num_cats_val + num_dogs_val# current model accuracy: 0.9352 , val_accuracy: 0.9233
# 为方便起见,设置变量以在预处理数据集和训练网络时使用,参数根据自己的电脑配置设置
batch_size = 32
epochs = 8
# 建议每次训练,设置为8-16较为合理,这样也可以及时对模型进行更改
IMG_HEIGHT = 200
IMG_WIDTH = 200# 使用实时数据增强生成一批张量图像数据。 通过通道方式获取图片
train_image_generator = ImageDataGenerator(rescale=1. / 255, rotation_range=5,horizontal_flip=True)
validation_image_generator = ImageDataGenerator(rescale=1. / 255)train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size, directory=train_dir, shuffle=True,target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary')
val_data_gen = validation_image_generator.flow_from_directory(batch_size=batch_size, directory=validation_dir,target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary')model = tf.keras.models.Sequential([# 第一层,padding设置为SAME,则说明输入图片大小和输出图片大小是一致的layers.Conv2D(filters=32, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.32),input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),# 第二层layers.Conv2D(filters=32, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.32)),# 连续利用两层3x3通道的卷积操作,可以实现5x5的卷积效果,还可以有效降低运算量,增大感受野# 第三层layers.Conv2D(filters=64, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.64)),layers.MaxPooling2D(pool_size=2, strides=2),# 第四层layers.Conv2D(filters=64, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.64)),layers.MaxPooling2D(pool_size=2, strides=2),# 第五层layers.Conv2D(filters=128, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.128)),# 第六层layers.Conv2D(filters=128, kernel_size=3, strides=1, padding='same',activation=tf.keras.layers.LeakyReLU(alpha=0.128)),layers.MaxPooling2D(pool_size=2, strides=2),layers.Flatten(),  # 拉直# 第七层layers.Dense(1024, activation=tf.keras.layers.LeakyReLU(alpha=0.1024)),layers.Dropout(rate=0.5),# 第八层layers.Dense(512, activation=tf.keras.layers.LeakyReLU(alpha=0.512)),layers.Dropout(rate=0.4),# 第九层layers.Dense(128, activation=tf.keras.layers.LeakyReLU(alpha=0.128)),layers.Dropout(rate=0.2),# 第十层layers.Dense(1, activation=tf.keras.layers.LeakyReLU(alpha=0.1))
])model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.0001, momentum=0.0001),loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),metrics=['accuracy'])checkpoint_save_path = "./checkpoint/demo_function_model.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):print('-------------load the model-----------------')model.load_weights(checkpoint_save_path)cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,save_weights_only=True,save_best_only=True)history = model.fit(train_data_gen,steps_per_epoch=total_train // batch_size,epochs=epochs,validation_data=val_data_gen,validation_steps=total_val // batch_size,callbacks=[cp_callback],
)# 输出模型信息
model.summary()end = time.time()
print("This  %d epochs cost time: %f s , average %f s per epoch" % (epochs, (end - start), (end - start) / epochs))# 保存模型,训练到模型收敛时,打开即可
# model.save('model',save_format='tf') # 可视化培训结果
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=(10, 10))
plt.subplot(1, 2, 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(1, 2, 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()# 记录模型优化过程及准确率
logFilePath = './/checkpoint//model_log.txt'
if os.path.isfile(logFilePath):print("Log file exists.")logWriter = open(logFilePath, 'a')
else:print("Log file does not exists. Make it .")logWriter = open(logFilePath, 'w')logWriter.write('Training finish at : ' + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + '\n')
logWriter.write('model id : ' + str(model.name) + '\n')
logWriter.write('Total epoch : ' + str(epochs) + '\n')
logWriter.write('These epochs cost time (second) : ' + str((end - start)) + '\n')
logWriter.write('Training accuracy  : ' + '\n          ' + str(history.history['accuracy']) + '\n')
logWriter.write('Validation accuracy: ' + '\n          ' + str(history.history['val_accuracy']) + '\n')
logWriter.write('---------------------------------------------------------------------------\n')
logWriter.write('\n')
print("Log file has successfully written down.")
logWriter.close()

predict_demo.py (前面已给出,此处只是整理到一起)

import matplotlib.pyplot as plt
import pathlib
import tensorflow as tfIMG_HEIGHT = 200
IMG_WIDTH = 200model = tf.keras.models.load_model('D:/Desktop/catVSdog/model')
data_root = pathlib.Path('D:/Desktop/catVSdog/data/test')
all_image_paths = list(data_root.glob('*/'))
all_image_paths = [str(path) for path in all_image_paths]def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=3)image = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])image /= 255.0return imagedef load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)i = 1
while i > 0:i = int(input("请输入你想要检测的图片序号(1-12500):"))if i > 12500:print("超出列表索引范围,请重新输入")continueelse:passimage = load_and_preprocess_image(all_image_paths[i])image_array = tf.keras.preprocessing.image.img_to_array(image)image_array = tf.expand_dims(image_array, 0)prediction = int(model.predict(image_array))plt.imshow(image)if prediction > 0:title = "Dog"else:title = "Cat"plt.title(("This is a " + title))plt.show()

predict_to_csv.py (前面已给出,此处只是整理到一起)

import numpy as np
import pathlib
import tensorflow as tfIMG_HEIGHT = 200
IMG_WIDTH = 200model = tf.keras.models.load_model('D:/Desktop/catVSdog/model_9')
data_root = pathlib.Path('D:/Desktop/catVSdog/data/test')
all_image_paths = list(data_root.glob('*/'))
all_image_paths = [str(path) for path in all_image_paths]def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=3)image = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])image /= 255.0return imagedef load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)import re
import pandas as pdlabel = np.zeros(12501, dtype=int)
"""
博主这里用的方法效率很低,但是非常简单易懂,
事实上,如果按照batch来喂入,GPU将会得到更好的利用,加快预测的时间,
后期博主还会添加利用dataset方法喂入图片,使得推理过程更加高效
"""
for i in range(12500):image = load_and_preprocess_image(all_image_paths[i])id = int(re.sub("\D", "", all_image_paths[i]))image_array = tf.keras.preprocessing.image.img_to_array(image)image_array = tf.expand_dims(image_array, 0)prediction = int(model.predict(image_array))if i % 100 == 0:print("Predict the %d photo" % (i))if prediction > 0:label[id] = 1else:label[id] = 0label = label.tolist()
dataframe = pd.DataFrame({'label': label})
dataframe.to_csv('model_9_submission.csv', sep=',')
#此处的输出可以根据自己的实际情况决定

后续博主还会继续更新一些其他的方法来完善整个项目。

深度学习系列笔记——贰 (基于Tensorflow2 Keras搭建的猫狗大战模型 三)相关推荐

  1. 深度学习系列笔记——贰 (基于Tensorflow Keras搭建的猫狗大战模型 一)

    猫狗大战是著名的竞赛网站kaggle几年前的一个比赛,参赛者得到猫狗各12500张图片,作为训练集,另外还会得到12500张猫和狗的图片,作为验证.最后提交结果至kaggle平台,获得评测分数. 本篇 ...

  2. 【深度学习】SETR:基于视觉 Transformer 的语义分割模型

    Visual Transformer Author:louwill Machine Learning Lab 自从Transformer在视觉领域大火之后,一系列下游视觉任务应用研究也随之多了起来.基 ...

  3. 深度学习系列笔记之统计基础

    研究方法入门 进行调查 信任调查结果吗? 调查了谁? 调查了多少人? 调查是怎么进行的? 影响结果的是潜在变量 抽样总体的平均得分叫作总体参数μ 抽样数据和总体数据之间有个叫抽样误差 μ -x 怎样使 ...

  4. 深度学习入门笔记系列 ( 二 )——基于 tensorflow 的一些深度学习基础知识

    本系列将分为 8 篇 .今天是第二篇 .主要讲讲 TensorFlow 框架的特点和此系列笔记中涉及到的入门概念 . 1.Tensor .Flow .Session .Graphs TensorFlo ...

  5. 深度学习入门笔记系列(三)——感知器模型和 tensorboard 的使用方法

    本系列将分为 8 篇 .今天是第三篇 .主要讲讲感知器模型和 tensorboard 的基本使用方法 . 1. 感知器模型 因为小詹之前写过一篇感知器模型的介绍 ,这里就不赘述了 .有需要巩固的点击如 ...

  6. 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列)

    2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列) 目录 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原 ...

  7. 《深度学习案例精粹:基于TensorFlow与Keras》深度学习常用训练案例合集

    #好书推荐##好书奇遇季#<深度学习案例精粹:基于TensorFlow与Keras>,京东当当天猫都有发售.本书配套示例源码.PPT课件.思维导图.数据集.开发环境与答疑服务. <深 ...

  8. 3.1 计算机视觉的发展和卷积神经网络概要(百度架构师手把手带你零基础实践深度学习原版笔记系列)

    3.1 计算机视觉的发展和卷积神经网络(百度架构师手把手带你零基础实践深度学习原版笔记系列) 概要 计算机视觉作为一门让机器学会如何去"看"的科学学科,具体的说,就是让机器去识别摄 ...

  9. 深度学习系列错误笔记(一)之print(‘gpu‘,torch.cuda.is_available())输出gpu False

    0.问题出现背景 ps: win10 64位环境.cuda已经安装,显卡驱动版本472对应torch1.8.0版本对应cuda10.2版本都没问题. 因为硬盘坏了,所以从头开始装按照深度学习系列(一) ...

最新文章

  1. AR+ 实时音视频通话,×××无缝结合
  2. 常微分方程matlab求解
  3. VTK:InfoVis之PKMeansClustering
  4. LoadRunner变量到参数的互换
  5. 计算机主机设备有限公司,一种计算机主机设备
  6. 快来看,大数据两地三中心的容灾也可以如此省心!
  7. matlab使用load指令,科学网—matlab常用方法 - 陈超的博文
  8. 介词短语做后置定语(由of引导)
  9. java 接口怎么规范属性_JAVA命名规范
  10. 自然数简化到素数:黎曼猜想RiemannHypothesis及其解释(公号回复“黎曼猜想”下载PDF经典收藏版彩标资料)
  11. 哪个ei期刊容易过计算机专业,计算机期刊哪个好中_ei期刊计算机_计算机八大核心期刊...
  12. Nonebot QQ机器人插件八:点歌(网易云音乐)
  13. c语言26字母排序,C语言,26个字母的冒泡排序
  14. 韩顺平Linux教程学习笔记
  15. Ubuntu 设置搜狗输入法 Win+空格 Win+Space切换
  16. 申请ssl 验证域名 失败了 中间证书
  17. 工信部与阿里牵头即将联合打造物联网区块链框架
  18. 3阶以下贝塞尔曲线轨迹库和任意轨迹库
  19. 【风控策略】解析闪电贷贷前风控策略
  20. C语言单元测试框架——CUnit 安装(windows和Linux)及使用

热门文章

  1. Automatic Image Cropping with Aesthetic Map and Gradient Energy Map 阅读笔记
  2. 献结程序员的一个故事——管道的故事
  3. 如何在CodeIgniter中使用会话数据
  4. 【01】计算机的发展
  5. 2012年6月婚假四川游记
  6. 全国2011年1月考试电子商务与电子政务试题
  7. 电饭煲电路原理图与解析
  8. 2009年6月Milk Hill的麦田圈预示巨大天体将靠近详细分析
  9. Java学习--day02---运算,一些重要的程序
  10. 谷歌开发者大会,拳打苹果脚踢微软