Advertisement

深度学习笔记08-猫狗识别(Tensorflow)

阅读量:

目录

一、前期工作

1.导入数据并查看

​编辑

二、图片预处理

1.加载数据

​编辑

2.再一次检查数据

​编辑

3.配置数据集

4.可视化数据

三、构建VGG网络

​编辑四、编译模型

五、模型训练

六、模型评估

七、预测指定图片

八、总结


一、前期工作

1.导入数据并查看

复制代码
 import matplotlib.pyplot as plt

    
 import os,PIL,pathlib
    
 import warnings
    
 import tensorflow as tf
    
 from tensorflow import keras
    
 # 支持中文
    
 plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签,'font.sans-serif'是matplotlib中用于设置默认字体的参数,而'SimHei'是黑体的字体名称。
    
 plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    
 #隐藏警告
    
 warnings.filterwarnings('ignore')
    
 data_dir = pathlib.Path("./T8")
    
  
    
 image_count = len(list(data_dir.glob('*/*')))
    
 print("图片总数为:",image_count)

二、图片预处理

1.加载数据

复制代码
 batch_size = 64

    
 img_height = 224
    
 img_width = 224
复制代码
 """

    
 关于image_dataset_from_directory()的详细介绍可以参考文章:
    
 """
    
 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)
    
 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)

复制代码
 class_names = train_ds.class_names

    
 print(class_names)

2.再一次检查数据

复制代码
 for i,l in train_ds:

    
     print(i.shape)
    
     print(l.shape)
    
     break

3.配置数据集

复制代码
 AUTOTUNE = tf.data.AUTOTUNE

    
  
    
 def 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=(10, 10))  # 图形的宽为10高为10

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

三、构建VGG网络

复制代码
 from tensorflow.keras import layers, models, Input

    
 from tensorflow.keras.models import Model
    
 from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
    
  
    
 def VGG16(nb_classes, input_shape):
    
     input_tensor = Input(shape=input_shape)
    
     # 1st block
    
     x = 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 block
    
     x = 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 block
    
     x = 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 block
    
     x = 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 block
    
     x = 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 connection
    
     x = 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 model
    
  
    
 model=VGG16(1000, (img_width, img_height, 3))
    
 model.summary()

四、编译模型

复制代码
 model.compile(optimizer="adam",

    
           loss     =tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
    
           metrics  =['accuracy'])

五、模型训练

复制代码
 from tqdm import tqdm

    
 import tensorflow.keras.backend as K
    
  
    
 epochs = 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)#获取训练数据集train_ds和验证数据集val_ds的长度,即样本总数。
    
     val_total   = len(val_ds)
    
     
    
     """
    
 使用tqdm创建一个进度条,total参数设置为训练样本总数,
    
 mininterval设置进度条更新的最小时间间隔,以秒为单位(默认值:0.1),
    
 desc参数设置进度条的描述,ncols设置进度条的宽度。
    
     """
    
     with tqdm(total=train_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=1,ncols=100) as pbar:
    
     
    
     lr = lr*0.92
    
     model.optimizer.learning_rate = 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": f"{K.get_value(model.optimizer.learning_rate):.4e}"})
    
         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)

六、模型评估

复制代码
 epochs_range=rang(epochs)

    
 plt.figure(figsize=(12,4))
    
 plt.subplot(1,2,1)
    
 plt.plot(epochs_range,history_train_accuracy,label='Train accuracy')
    
 plt.plot(epochs_range,history_val_accuracy,label='Validation accuracy')
    
 plt.legend(loc='lower right')
    
 plt.title('Training and Validation Accuracy')
    
  
    
 plt.subplot(1,2,2)
    
 plt.plot(epochs_range,history_train_loss,label='Train loss')
    
 plt.plot(epochs_range,history_val_accuracy,label='Validation loss')
    
 plt.legend(loc='upper right')
    
 plt.title('Training and Validation Loss')

七、预测指定图片

复制代码
 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、

tqdm是一款Python的进度条库,在Python长循环中能够提供进度提示功能。

2、

在训练模型时出现错误,在向AI寻求帮助后了解到动态调整学习率需要注意版本兼容问题。TensorFlow的优化器属性因软件版本不同而发生变化:新版本中可使用model.optimizer.learning_rate.assign(lr),而旧版本则可采用K.set_value(model.optimizer.lr, lr)进行设置。此外,请确保学习率数据类型为浮点数(float),以避免因数据类型不符导致错误的发生。通过采取兼容不同版本的方式不仅提升了代码的稳定性还能为后续模型优化提供更加灵活的解决方案

3、model.train_on_batch介绍

使用TensorFlow中的fit()fit_generator()方法可以实现模型的训练过程。这两个API对于刚开始学习深度学习的人来说非常友好且便利。然而由于其设计过于深入,在需要自定义训练流程时显得不够灵活,并且对于像GAN这样的需要分步完成整个训练流程的模型也无法直接通过fitfit_generator完成训练。因此TensorFlow提供了train_on_batch这个API,在处理一个mini-batch的数据时能够实现梯度更新的操作。

优点:

  • 采用更精细的自定义训练方案
  • 更加精确地收集与评估损失函数和性能指标
  • 利用多GPU架构显著降低了模型存储的复杂性
  • 引入多样化的数据加载策略以提升模型泛化能力

函数原型

全部评论 (0)

还没有任何评论哟~