当前位置: 首页 > news >正文

Tensorflow实现深度学习8:猫狗识别

本文为为🔗365天深度学习训练营内部文章

原作者:K同学啊

 一 导入数据

import matplotlib.pyplot as plt
import tensorflow as tf
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号import os,PIL,pathlib#隐藏警告
import warnings
warnings.filterwarnings('ignore')data_dir = "./data"
data_dir = pathlib.Path(data_dir)image_count = len(list(data_dir.glob('*/*')))print("图片总数为:",image_count)
图片总数为: 3400

二、数据预处理

1. 加载数据

使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset

batch_size = 8
img_height = 224
img_width = 224
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)
Found 3400 files belonging to 2 classes.
Using 2720 files for training.
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)
Found 3400 files belonging to 2 classes.
Using 680 files for validation.
class_names = train_ds.class_names
print(class_names)
['cat', 'dog']

2. 再次检查数据 

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

3. 配置数据集

  • shuffle() : 打乱数据
  • prefetch() :预取数据,加速运行
  • cache() :将数据集缓存到内存当中,加速运行
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)

 在这里数据处理的过程中,比前几次稍微不同的是多加了一个归一化的处理

4.可视化数据 

plt.figure(figsize=(15, 10))  # 图形的宽为15高为10for 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")

三、构建VG-16网络

VGG优缺点分析:

  • VGG优点

VGG的结构非常简洁,整个网络都使用了同样大小的卷积核尺寸(3x3)和最大池化尺寸(2x2)。

  • VGG缺点

1)训练时间过长,调参难度大。2)需要的存储容量大,不利于部署。例如存储VGG-16权重值文件的大小为500多MB,不利于安装到嵌入式系统中。

结构说明:

  • 13个卷积层(Convolutional Layer),分别用blockX_convX表示
  • 3个全连接层(Fully connected Layer),分别用fcXpredictions表示
  • 5个池化层(Pool layer),分别用blockX_pool表示

VGG-16包含了16个隐藏层(13个卷积层和3个全连接层),故称为VGG-16

 

构建方法1:调用官网封装好的模型函数 

model = tf.keras.applications.VGG16(weights='imagenet')
model.summary()
Model: "vgg16"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================input_1 (InputLayer)        [(None, 224, 224, 3)]     0         block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792      block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928     block1_pool (MaxPooling2D)  (None, 112, 112, 64)      0         block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856     block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584    block2_pool (MaxPooling2D)  (None, 56, 56, 128)       0         block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168    block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080    block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080    block3_pool (MaxPooling2D)  (None, 28, 28, 256)       0         block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160   block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808   block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808   block4_pool (MaxPooling2D)  (None, 14, 14, 512)       0         block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808   block5_pool (MaxPooling2D)  (None, 7, 7, 512)         0         flatten (Flatten)           (None, 25088)             0         fc1 (Dense)                 (None, 4096)              102764544 fc2 (Dense)                 (None, 4096)              16781312  predictions (Dense)         (None, 1000)              4097000   =================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

构建方法二:自己手动搭建模型 

from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropoutdef VGG16(nb_classes, input_shape):input_tensor = Input(shape=input_shape)# 1st blockx = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)# 2nd blockx = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)# 3rd blockx = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)# 4th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)# 5th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)# full connectionx = Flatten()(x)x = Dense(4096, activation='relu',  name='fc1')(x)x = Dense(4096, activation='relu', name='fc2')(x)output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)model = Model(input_tensor, output_tensor)return modelmodel=VGG16(1000, (img_width, img_height, 3))
model.summary()
Model: "model"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================input_1 (InputLayer)        [(None, 224, 224, 3)]     0         block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792      block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928     block1_pool (MaxPooling2D)  (None, 112, 112, 64)      0         block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856     block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584    block2_pool (MaxPooling2D)  (None, 56, 56, 128)       0         block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168    block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080    block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080    block3_pool (MaxPooling2D)  (None, 28, 28, 256)       0         block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160   block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808   block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808   block4_pool (MaxPooling2D)  (None, 14, 14, 512)       0         block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808   block5_pool (MaxPooling2D)  (None, 7, 7, 512)         0         flatten (Flatten)           (None, 25088)             0         fc1 (Dense)                 (None, 4096)              102764544 fc2 (Dense)                 (None, 4096)              16781312  predictions (Dense)         (None, 1000)              4097000   =================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

四、编译

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

  • 损失函数(loss):用于衡量模型在训练期间的准确率。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 评价函数(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。

 

# 设置初始学习率
initial_learning_rate = 1e-4lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate, decay_steps=30,      # 敲黑板!!!这里是指 steps,不是指epochsdecay_rate=0.92,     # lr经过一次衰减就会变成 decay_rate*lrstaircase=True)# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])

 早停法:

from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStoppingepochs = 10# 保存最佳模型参数
checkpointer = ModelCheckpoint('best_model.h5',monitor='val_accuracy',verbose=1,save_best_only=True,save_weights_only=True)# 设置早停
earlystopper = EarlyStopping(monitor='val_accuracy', min_delta=0.001,patience=20, verbose=1)

五、训练模型

history = model.fit(train_ds,validation_data=val_ds,epochs=epochs,callbacks=[checkpointer, earlystopper])
Epoch 1/10
340/340 [==============================] - ETA: 0s - loss: 0.2396 - accuracy: 0.8930
Epoch 1: val_accuracy improved from -inf to 0.99412, saving model to best_model.h5
340/340 [==============================] - 1376s 4s/step - loss: 0.2396 - accuracy: 0.8930 - val_loss: 0.0210 - val_accuracy: 0.9941
Epoch 2/10
340/340 [==============================] - ETA: 0s - loss: 0.0276 - accuracy: 0.9908
Epoch 2: val_accuracy did not improve from 0.99412
340/340 [==============================] - 1345s 4s/step - loss: 0.0276 - accuracy: 0.9908 - val_loss: 0.0465 - val_accuracy: 0.9853
Epoch 3/10
340/340 [==============================] - ETA: 0s - loss: 0.1150 - accuracy: 0.9717
Epoch 3: val_accuracy did not improve from 0.99412
340/340 [==============================] - 1316s 4s/step - loss: 0.1150 - accuracy: 0.9717 - val_loss: 0.0704 - val_accuracy: 0.9750
Epoch 4/10
340/340 [==============================] - ETA: 0s - loss: 0.0192 - accuracy: 0.9949
Epoch 4: val_accuracy improved from 0.99412 to 0.99853, saving model to best_model.h5
340/340 [==============================] - 1336s 4s/step - loss: 0.0192 - accuracy: 0.9949 - val_loss: 0.0083 - val_accuracy: 0.9985
Epoch 5/10
340/340 [==============================] - ETA: 0s - loss: 0.0248 - accuracy: 0.9930
Epoch 5: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1321s 4s/step - loss: 0.0248 - accuracy: 0.9930 - val_loss: 0.0036 - val_accuracy: 0.9985
Epoch 6/10
340/340 [==============================] - ETA: 0s - loss: 0.0240 - accuracy: 0.9937
Epoch 6: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1323s 4s/step - loss: 0.0240 - accuracy: 0.9937 - val_loss: 0.0074 - val_accuracy: 0.9956
Epoch 7/10
340/340 [==============================] - ETA: 0s - loss: 0.0039 - accuracy: 0.9982
Epoch 7: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1324s 4s/step - loss: 0.0039 - accuracy: 0.9982 - val_loss: 0.0069 - val_accuracy: 0.9971
Epoch 8/10
340/340 [==============================] - ETA: 0s - loss: 8.3202e-04 - accuracy: 1.0000
Epoch 8: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1318s 4s/step - loss: 8.3202e-04 - accuracy: 1.0000 - val_loss: 0.0205 - val_accuracy: 0.9956
Epoch 9/10
340/340 [==============================] - ETA: 0s - loss: 0.0759 - accuracy: 0.9801
Epoch 9: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1326s 4s/step - loss: 0.0759 - accuracy: 0.9801 - val_loss: 0.0372 - val_accuracy: 0.9882
Epoch 10/10
340/340 [==============================] - ETA: 0s - loss: 0.0242 - accuracy: 0.9934
Epoch 10: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1328s 4s/step - loss: 0.0242 - accuracy: 0.9934 - val_loss: 0.0072 - val_accuracy: 0.9985

六 模型评估 

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=(12, 4))
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()

预测 

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")
1/1 [==============================] - 1s 609ms/step
1/1 [==============================] - 0s 123ms/step
1/1 [==============================] - 0s 140ms/step
1/1 [==============================] - 0s 134ms/step
1/1 [==============================] - 0s 129ms/step
1/1 [==============================] - 0s 126ms/step
1/1 [==============================] - 0s 124ms/step
1/1 [==============================] - 0s 123ms/step

 

在训练模型的时候,除了用上述的代码之外,还可以用另一种方式。

改用model.train_on_batch方法。两种方法的比较:

  • model.fit():用起来十分简单,对新手非常友好
  • model.train_on_batch():封装程度更低,可以玩更多花样。

此外我也引入了进度条的显示方式,更加方便我们及时查看模型训练过程中的情况,可以及时打印各项指标

 

model.compile(optimizer="adam",loss     ='sparse_categorical_crossentropy',metrics  =['accuracy'])
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)for image,label in train_ds:   """训练模型,简单理解train_on_batch就是:它是比model.fit()更高级的一个用法想详细了解 train_on_batch 的同学,可以看看我的这篇文章:https://www.yuque.com/mingtian-fkmxf/hv4lcq/ztt4gy"""history = model.train_on_batch(image,label)train_loss     = history[0]train_accuracy = history[1]pbar.set_postfix({"loss": "%.4f"%train_loss,"accuracy":"%.4f"%train_accuracy,"lr": K.get_value(model.optimizer.lr)})pbar.update(1)history_train_loss.append(train_loss)history_train_accuracy.append(train_accuracy)print('开始验证!')with tqdm(total=val_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=0.3,ncols=100) as pbar:for image,label in val_ds:      history = model.test_on_batch(image,label)val_loss     = history[0]val_accuracy = history[1]pbar.set_postfix({"loss": "%.4f"%val_loss,"accuracy":"%.4f"%val_accuracy})pbar.update(1)history_val_loss.append(val_loss)history_val_accuracy.append(val_accuracy)print('结束验证!')print("验证loss为:%.4f"%val_loss)print("验证准确率为:%.4f"%val_accuracy)

 ​​​​​

 对比之前的model.fit()方法,这次还引用了更详细的进度条。后续的操作和上述方法一样

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Qt Dialog退出事件
  • AIGC时代从新手到高手:B端竞品分析实战案例与技巧分享
  • 华为Huawei路由器交换机SSH配置
  • 设计模式-结构型模式-组合模式
  • 学习WebGl基础知识(二)
  • Docker原理及实例
  • 使用docker部署project-exam-system(项目)
  • QT connect的使用
  • SLM2110CG 1.0A/1.6A600V完美代替IR2110 精准驱动,可靠之芯 高压、高速的功率MOSFET和IGBT驱动器
  • 【深度解读】知识库的作用
  • NVIDIA GeForce RTX标志升级 加入AI的力量
  • 9、Django Admin优化查询
  • MacOS下WKWebView设置背景透明问题
  • 行业内幕曝光!全域运营公司究竟哪家好?
  • 【mac】MAC命令快速模糊查找文件
  • 10个确保微服务与容器安全的最佳实践
  • express如何解决request entity too large问题
  • extract-text-webpack-plugin用法
  • golang中接口赋值与方法集
  • HashMap ConcurrentHashMap
  • Java多线程(4):使用线程池执行定时任务
  • Java反射-动态类加载和重新加载
  • Laravel5.4 Queues队列学习
  • Promise初体验
  • rabbitmq延迟消息示例
  • scrapy学习之路4(itemloder的使用)
  • use Google search engine
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 测试如何在敏捷团队中工作?
  • 第2章 网络文档
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • #{}和${}的区别是什么 -- java面试
  • $NOIp2018$劝退记
  • (0)Nginx 功能特性
  • (C++哈希表01)
  • (C语言)逆序输出字符串
  • (Oracle)SQL优化技巧(一):分页查询
  • (Python) SOAP Web Service (HTTP POST)
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (九十四)函数和二维数组
  • (每日一问)基础知识:堆与栈的区别
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (算法二)滑动窗口
  • (学习日记)2024.01.09
  • ./configure、make、make install 命令
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .net的socket示例
  • /bin/rm: 参数列表过长"的解决办法
  • @Builder注释导致@RequestBody的前端json反序列化失败,HTTP400
  • @ModelAttribute使用详解
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛