vgg16猫狗识别

article/2025/8/30 5:17:17
  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍦 参考文章:365天深度学习训练营-第8周:猫狗识别(训练营内部成员可读)
  • 🍖 原作者:K同学啊|接辅导、项目定制

 

我的环境:

  • 语言环境:Python3.8
  • 编译器:jupyter lab
  • 深度学习环境:TensorFlow2.5
  • 参考文章:本人博客(60条消息) 机器学习之——tensorflow+pytorch_重邮研究森的博客-CSDN博客

● 难度:夯实基础⭐⭐
● 语言:Python3、TensorFlow2
● 时间:9月12-9月16日

🍺 要求:

  1. 了解model.train_on_batch()并运用(✔)
  2. 了解tqdm,并使用tqdm实现可视化进度条(✔)

🍻 拔高(可选):

  1. 本文代码中存在一个严重的BUG,请找出它并配以文字说明(✔)

🔎 探索(难度有点大)

  1. 修改代码,处理BUG(✔)

目录

一 前期工作

1.设置GPU或者cpu

2.导入数据

3.查看数据

二 数据预处理

1.加载数据

2.可视化数据

3.再次检查数据

4.配置数据集

三 搭建网络

四 训练模型

1.设置学习率

2.模型训练

 五 模型评估

1.Loss和Accuracy图

 2.指定图片进行预测

 3.总结


一 前期工作

环境:python3.7,1080ti,tensorflow2.5(网上租的环境😂😂)

由于电脑问题,现在在jupytr上跑了,所以代码风格发生变化。

1.设置GPU或者cpu

设置cpu(电脑gpu跑不动就用这个将就一下)

from tensorflow import keras
from tensorflow.keras import layers, models
import os, PIL, pathlib
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import tensorflow as tf
import tensorflow as tf
import os,PIL
# os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
#os.environ['CUDA_VISIBLE_DEVICES']='0'
os.environ['CUDA_VISIBLE_DEVICES']='2'
# os.environ['TF_CPP_MIN_LOG_LEVEL']='2'#屏蔽通知和警告信息
import os,PIL
os.environ['TF_XLA_FLAGS'] = '--tf_xla_enable_xla_devices'
from tensorflow import keras
keras.backend.clear_session()

设置gpu

from tensorflow       import keras
from tensorflow.keras import layers,models
import os, PIL, pathlib
import matplotlib.pyplot as plt
import tensorflow        as tf
import numpy             as npgpus = tf.config.list_physical_devices("GPU")if gpus:gpu0 = gpus[0]                                        #如果有多个GPU,仅使用第0个GPUtf.config.experimental.set_memory_growth(gpu0, True)  #设置GPU显存用量按需使用tf.config.set_visible_devices([gpu0],"GPU")gpus

2.导入数据

import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号import os,PIL,pathlib#隐藏警告
import warnings
warnings.filterwarnings('ignore')data_dir = "./365-7-data"
data_dir = pathlib.Path(data_dir)

3.查看数据

image_count = len(list(data_dir.glob('*/*')))print("图片总数为:",image_count)

二 数据预处理

1.加载数据

设置数据尺寸

batch_size = 8
img_height = 224
img_width = 224

设置dataset

"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="training",seed=12,image_size=(img_height, img_width),batch_size=batch_size)
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="validation",seed=12,image_size=(img_height, img_width),batch_size=batch_size)

关于image_dataset_from_directory()的详细介绍可以参考文章:(7条消息) tf.keras.preprocessing.image_dataset_from_directory() 简介_K同学啊的博客-CSDN博客_tf.keras.preprocessing.image

 

   输出经过image_dataset_from_directory()分类后的标签

class_names = train_ds.class_names
print(class_names)

2.可视化数据

打印部分图片

for images, labels in train_ds.take(1):for i in range(8):ax = plt.subplot(5, 8, i + 1)  plt.imshow(images[i])plt.title(class_names[labels[i]])plt.axis("off")

3.再次检查数据

输出数据的尺寸

for image_batch, labels_batch in train_ds:print(image_batch.shape)print(labels_batch.shape)break

4.配置数据集

shuffle:打乱数据集

prefetch:加速处理

AUTOTUNE = tf.data.AUTOTUNEdef preprocess_image(image,label):return (image/255.0,label)# 归一化处理
train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
val_ds   = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

三 搭建网络

 

本文神经网络为官方vgg16模型,我们需要做的是对最后一层按我们的类别进行分类即可。

调用官方

model = keras.applications.VGG16(include_top=False,weights='imagenet')
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
prediction_layer1 = tf.keras.layers.Dense(1024,activation='relu')
prediction_layer2 = tf.keras.layers.Dense(512,activation='relu')
prediction_layer3 = tf.keras.layers.Dense(len(class_names),activation='softmax')model = tf.keras.Sequential([model,global_average_layer,prediction_layer1,prediction_layer2,prediction_layer3
])
model.summary()

 关于VGG16函数参考下面文章

(7条消息) keras 自带VGG16 net 参数分析_vola9527的博客-CSDN博客

我们对vgg16前部分卷积层没有改变,而是不选择官方的dense层,因为我们需要根据自己的数据进行输出,官方输出为1000种分类,我们只有2种,因此按照这个写法即可。 

 自己搭建

model = models.Sequential([layers.experimental.preprocessing.Rescaling( 1. ,input_shape=(img_height, img_width, 3)),layers.Conv2D(filters=64, kernel_size=(3, 3), padding='same'),  # 卷积层1#layers.BatchNormalization(),  # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=64, kernel_size=(3, 3), padding='same', ),#layers.BatchNormalization(),  # BN层1layers.Activation('relu') , # 激活层1layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'),#layers.Dropout(0.2),  # dropout层#layers.Conv2D(filters=128, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization(),  # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=128, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization(),  # BN层1layers.Activation('relu'),  # 激活层1layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'),#layers.Dropout(0.2),  # dropout层#layers.Conv2D(filters=256, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization() , # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=256, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization() , # BN层1layers.Activation('relu') , # 激活层1layers.Conv2D(filters=256, kernel_size=(3, 3), padding='same'),# layers.BatchNormalization(),layers.Activation('relu'),layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'),#layers.Dropout(0.2),#layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),# layers.BatchNormalization() , # BN层1layers.Activation('relu') , # 激活层1layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization() , # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization(),layers.Activation('relu'),layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'),#layers.Dropout(0.2),#layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),# layers.BatchNormalization() , # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),#layers.BatchNormalization(),  # BN层1layers.Activation('relu'),  # 激活层1layers.Conv2D(filters=512, kernel_size=(3, 3), padding='same'),# layers.BatchNormalization(),layers.Activation('relu'),layers.MaxPool2D(pool_size=(2, 2), strides=2, padding='same'),#layers.Dropout(0.2),layers.Flatten(),  # Flatten层,连接卷积层与全连接层layers.Dense(4096, activation='relu'),  # 全连接层,特征进一步提取layers.Dense(4096, activation='relu'),  # 全连接层,特征进一步提取layers.Dense(len(class_names),activation='softmax')  # 输出层,输出预期结果
])
model.summary()

四 训练模型

模型训练时,需要完成如下设置

损失函数(loss):衡量模型准确率

优化器(optimizer):根据损失函数进行优化更新

指标(metrics):监控训练过程,保存最优模型

1.设置学习率

model.compile(optimizer="adam",loss     ='sparse_categorical_crossentropy',metrics  =['accuracy'])

注意损失函数不要用错了!

对于损失函数可以参考下面文章

(7条消息) tensorflow损失函数详解_重邮研究森的博客-CSDN博客

此外,需要注意在dataset设置中label_model的设置会影响loss

2.早期与保存最佳模型参数
关于ModelCheckpoint参考下面文章

(7条消息) ModelCheckpoint 讲解【TensorFlow2入门手册】_K同学啊的博客-CSDN博客_modelcheckpoint的filepath

2.模型训练

from tqdm import tqdm
import tensorflow.keras.backend as Kepochs = 10
lr     = 1e-4# 记录训练数据,方便后面的分析
history_train_loss     = []
history_train_accuracy = []
history_val_loss       = []
history_val_accuracy   = []for epoch in range(epochs):train_total = len(train_ds)val_total   = len(val_ds)"""total:预期的迭代数目ncols:控制进度条宽度mininterval:进度更新最小间隔,以秒为单位(默认值:0.1)"""with tqdm(total=train_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=1,ncols=100) as pbar:lr = lr*0.92K.set_value(model.optimizer.lr, lr)train_loss     = []train_accuracy = []for image,label in train_ds:   """训练模型,简单理解train_on_batch就是:它是比model.fit()更高级的一个用法想详细了解 train_on_batch 的同学,可以看看我的这篇文章:https://www.yuque.com/mingtian-fkmxf/hv4lcq/ztt4gy"""# 这里生成的是每一个batch的acc与losshistory = model.train_on_batch(image,label)train_loss.append(history[0])train_accuracy.append(history[1])pbar.set_postfix({"train_loss": "%.4f"%history[0],"train_acc":"%.4f"%history[1],"lr": K.get_value(model.optimizer.lr)})pbar.update(1)history_train_loss.append(np.mean(train_loss))history_train_accuracy.append(np.mean(train_accuracy))print('开始验证!')with tqdm(total=val_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=0.3,ncols=100) as pbar:val_loss     = []val_accuracy = []for image,label in val_ds:      # 这里生成的是每一个batch的acc与losshistory = model.test_on_batch(image,label)val_loss.append(history[0])val_accuracy.append(history[1])pbar.set_postfix({"val_loss": "%.4f"%history[0],"val_acc":"%.4f"%history[1]})pbar.update(1)history_val_loss.append(np.mean(val_loss))history_val_accuracy.append(np.mean(val_accuracy))print('结束验证!')print("验证loss为:%.4f"%np.mean(val_loss))print("验证准确率为:%.4f"%np.mean(val_accuracy))

 五 模型评估

1.Loss和Accuracy图

 

 2.指定图片进行预测

import numpy as np# 采用加载的模型(new_model)来看预测结果
plt.figure(figsize=(18, 3))  # 图形的宽为18高为5
plt.suptitle("预测结果展示")for images, labels in val_ds.take(1):for i in range(8):ax = plt.subplot(1,8, i + 1)  # 显示图片plt.imshow(images[i].numpy())# 需要给图片增加一个维度img_array = tf.expand_dims(images[i], 0) # 使用模型预测图片中的人物predictions = model.predict(img_array)plt.title(class_names[np.argmax(predictions)])plt.axis("off")

 3.总结

1.了解了一种新的训练方式train_on_batch,我个人感觉看起来很麻烦!!!还是fit友好。

对于该方法可以参考下面这个文章。目前我个人认为还用不到这个方法。

model.train_on_batch介绍【TensorFlow2入门手册】 · 语雀 (yuque.com)

2.了解了python中的tqdm。简单来说就是对于一个循环,我们可以把它的信息通过进度条的方式打印下来。该方法可以参考下面文章

python进度条库tqdm详解 - 知乎 (zhihu.com)

3. 由于习惯之前写法,于是我又重新按照之前的模式写了。官方模型准确率:100%

4.关于错误问题:如下所示,之前会把每次的loss和val赋值给之前的值,而现在则是插入结果。

 


http://chatgpt.dhexx.cn/article/IRBxhcPH.shtml

相关文章

VGG16-keras 优化

VGG16-keras 优化 优化结果对比VGG16网络结构VGG16网络结构优化自定义loss训练预测 优化结果对比 原始VGG16 普通调优 使用预训练权重 VGG16网络结构 VGG16网络结构优化 1.增加正则化 2.使用BN/GN层(中间层数据的标准化) 3.使用dropout Net.py i…

VGG16论文解读

VGGNET VGG16相比AlexNet的一个改进是采用连续的几个3x3的卷积核代替AlexNet中的较大卷积核(11x11,7x7,5x5)。对于给定的感受野(与输出有关的输入图片的局部大小),采用堆积的小卷积核是优于采用…

VGG16模型详解 and 代码搭建

目录 一. VGG 网络模型 二. 代码复现 1. 网络搭建 2.数据集制作(pkl) 3.源码地址 一. VGG 网络模型 Alexnet是卷积神经网络的开山之作,但是由于卷积核太大,移动步长大,无填充,所以14年提出的VGG网络解决了这一问题。而且VGG网…

动手学习VGG16

VGG 论文 《Very Deep Convolutional Networks for Large-Scale Image Recognition》 论文地址:https://arxiv.org/abs/1409.1556 使用重复元素的网络(VGG) 以学习VGG的收获、VGG16的复现二大部分,简述VGG16网络。 一. 学习VGG的收获 VGG网络明确指…

VGG16

VGG16模型的学习以及源码分析 part one 主要学习参考 pytorch 英文文档VGG16学习笔记VGG16网络原理分析与pytorch实现【深度学习】全面理解VGG16模型VGG模型的pytorch代码实现VGG16源代码详解【论文】 VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION p…

VGG16 - 用于分类和检测的卷积网络

VGG16是由牛津大学的K. Simonyan和A. Zisserman在“用于大规模图像识别的非常深卷积网络”的论文中提出的卷积神经网络模型。 该模型在ImageNet中实现了92.7%的前5个测试精度,这是属于1000个类的超过1400万张图像的数据集。它是ILSVRC-2014提交的着名模型…

VGG-16网络结构详解

VGG,又叫VGG-16,顾名思义就是有16层,包括13个卷积层和3个全连接层,是由Visual Geometry Group组的Simonyan和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型&…

经典卷积神经网络——VGG16

VGG16 前言一、VGG发展历程二、VGG网络模型三、VGG16代码详解1.VGG网络架构2.VGG16网络验证2.读取数据,进行数据增强3.训练模型,测试准确率 四、VGG缺点 前言 我们都知道Alexnet是卷积神经网络的开山之作,但是由于卷积核太大,移动…

VGG16网络模型的原理与实现

VGG 最大的特点就是通过比较彻底地采用 3x3 尺寸的卷积核来堆叠神经网络,这样也加深整个神经网络的深度。这两个重要的改变对于人们重新定义卷积神经网络模型架构也有不小的帮助,至少证明使用更小的卷积核并且增加卷积神经网络的深度,可以更有…

深度学习——VGG16模型详解

1、网络结构 VGG16模型很好的适用于分类和定位任务,其名称来自牛津大学几何组(Visual Geometry Group)的缩写。 根据卷积核的大小核卷积层数,VGG共有6种配置,分别为A、A-LRN、B、C、D、E,其中D和E两种是最…

RK3399平台开发系列讲解(PCI/PCI-E)5.54、PCIE INTx中断机制

文章目录 一、PCIe中断过程二、PCIE 控制器支持的中断三、PCIE 控制器注册中断四、PCIe设备中断号分配沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章将介绍RK3399平台PCIE总线中断INTx相关内容。 一、PCIe中断过程 层级结构为:PCIe设备 => PCIe控制器 =&g…

RK3399—中断

中断是操作系统最常见的事件之一,无论是系统层的“软中断”还是CPU底层的“硬中断”都是编程时常用的。中断的作用之一是充分利用CPU资源,正常情况下,CPU执行用户任务,当外设触发中断产生时,CPU停止当前任务&#xff0…

基于RK3399分析Linux系统下的CPU时钟管理 - 第3篇

1. 时钟系统结构 rockchip的时钟系统代码位于drivers/clk/rockchip,目录整体结构如下: ├── rockchip │ ├── clk.c---------------时钟系统注册 │ ├── clk-cpu.c-----------CPU调频 │ ├── clk-ddr.c-----------DDR调频 │ ├──…

基于RK3399+PID的手持稳定云台的设计与实现

手持稳定云台的主要作用是将外界环境因数引起的相机姿态变化进行隔离。如因操作者运动造成的机体震动、风阻力矩等,为了确保工作中相机的视轴始终保持期望的姿态不动。云台相机要拍摄出高质量的影像最重要的就是保证相机的视轴相对目标保持稳定。因此在相机拍摄的过…

RK3399学习

RK3399学习 韦东山rk3399:http://dev.t-firefly.com/forum-460-1.html firefly官网教程:http://wiki.t-firefly.com/zh_CN/Firefly-RK3399/started.html firefly官网3399资料:http://dev.t-firefly.com/forum-263-1.html 100ask 3399-pc教…

RK3399平台开发系列讲解(内核入门篇)1.53、platform平台设备

🚀返回专栏总目录 文章目录 一、设备配置-非设备树1.1、资源1.2、平台数据1.3、声明平台设备二、设备配置 - DTS沉淀、分享、成长,让自己和他人都能有所收获!😄 📢平台设备在内核中表示为struct platform_device的实例。 有两种方法可以把有关设备所需的资源(IRQ、DMA…

RK3399 Android7.1 编译

RK3399 Android7.1 编译 文章目录 RK3399 Android7.1 编译前言设置 Linux 编译环境安装 JDK可选- 更新默认的 Java 版本 安装所需的程序包(Ubuntu 14.04) 下载 Android SDK 前言 RK官网编译 Android搭建编译环境 设置 Linux 编译环境 使用的环境Linux 16.0.4 安装 JDK 如…

基于RK3399+5G的医用视频终端设计

当前在各种先进的信息通信技术的驱动下,医疗行业已呈现出信息化、移动化、智能化的发展趋势。特别是 5G 通信技术的落地应用推动了智慧医疗行业的 蓬勃发展,涌现出大量基于 5G 技术的医疗健康应用与服务,进一步融合了 5G 、 物联网与大数据…

RK3399平台开发系列讲解(PCI/PCI-E)PCIE相关配置说明

🚀返回专栏总目录 文章目录 一、DTS 配置二、menuconfig 配置三、cmdline 配置沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍在使用 RK3399 平台 PCIE 时候的配置。 一、DTS 配置 ep-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; 此项是设置 PCIe…

RK3399快速上手 | 02-rockchip rk3399 linux sdk的使用(编译内核、编译uboot)

更新时间更新内容2022-09-15增加内核编译方法2022-10-21增加uboot编译方法和sdk开发版配置链路分析一、sdk区别 瑞芯微提供了两套sdk,一套是通过官方git仓库释放,适合于项目使用,另一套是通过github释放,适合于爱好者。 本文中使用从瑞芯微官方释放的正式linux sdk 2.7版…