qidao123.com技术社区-IT企服评测·应用市场

标题: 第T8周:猫狗识别 [打印本页]

作者: 反转基因福娃    时间: 7 天前
标题: 第T8周:猫狗识别
● 语言环境:Python3.8.8
● 编译器:Jupyter Lab
● 深度学习环境:TensorFlow2.4.1

  
一、前期工作

1. 设置GPU

  1. import tensorflow as tf
  2. gpus = tf.config.list_physical_devices("GPU")
  3. if gpus:
  4.     tf.config.experimental.set_memory_growth(gpus[0], True)  #设置GPU显存用量按需使用
  5.     tf.config.set_visible_devices([gpus[0]],"GPU")
  6. # 打印显卡信息,确认GPU可用
  7. print(gpus)
复制代码
2.导入数据
  1. import matplotlib.pyplot as plt
  2. # 支持中文
  3. plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
  4. plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
  5. import os,PIL,pathlib
  6. #隐藏警告
  7. import warnings
  8. warnings.filterwarnings('ignore')
  9. data_dir = "./365-7-data"
  10. data_dir = pathlib.Path(data_dir)
  11. image_count = len(list(data_dir.glob('*/*')))
  12. print("图片总数为:",image_count)
复制代码
二、数据预处理

1. 加载数据

使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset中
  1. batch_size = 8
  2. img_height = 224
  3. img_width = 224
复制代码
  1. """
  2. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
  3. """
  4. train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  5.     data_dir,
  6.     validation_split=0.2,
  7.     subset="training",
  8.     seed=12,
  9.     image_size=(img_height, img_width),
  10.     batch_size=batch_size)
复制代码
  1. """
  2. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
  3. """
  4. val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  5.     data_dir,
  6.     validation_split=0.2,
  7.     subset="validation",
  8.     seed=12,
  9.     image_size=(img_height, img_width),
  10.     batch_size=batch_size)
复制代码
我们可以通过class_names输出数据集的标签。标签将按字母次序对应于目次名称。
  1. class_names = train_ds.class_names
  2. print(class_names)
复制代码
2.再次检查数据

  1. for image_batch, labels_batch in train_ds:
  2.     print(image_batch.shape)
  3.     print(labels_batch.shape)
  4.     break
复制代码
● Image_batch是外形的张量(8, 224, 224, 3)。这是一批外形224x224x3的8张图片(最后一维指的是彩色通道RGB)。
● Label_batch是外形(8,)的张量,这些标签对应8张图片
3.配置数据集

● shuffle() : 打乱数据,关于此函数的具体介绍可以参考:https://zhuanlan.zhihu.com/p/42417456
● prefetch() :预取数据,加快运行,其具体介绍可以参考我前两篇文章,内里都有讲解。
● cache() :将数据集缓存到内存当中,加快运行
  1. AUTOTUNE = tf.data.AUTOTUNE
  2. def preprocess_image(image,label):
  3.     return (image/255.0,label)
  4. # 归一化处理
  5. train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
  6. val_ds   = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
  7. train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
  8. val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
复制代码

三、构建VG-16网络

  1. from tensorflow.keras import layers, models, Input
  2. from tensorflow.keras.models import Model
  3. from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
  4. def VGG16(nb_classes, input_shape):
  5.     input_tensor = Input(shape=input_shape)
  6.     # 1st block
  7.     x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)
  8.     x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)
  9.     x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)
  10.     # 2nd block
  11.     x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)
  12.     x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)
  13.     x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)
  14.     # 3rd block
  15.     x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)
  16.     x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)
  17.     x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)
  18.     x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)
  19.     # 4th block
  20.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)
  21.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)
  22.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)
  23.     x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)
  24.     # 5th block
  25.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)
  26.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)
  27.     x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)
  28.     x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)
  29.     # full connection
  30.     x = Flatten()(x)
  31.     x = Dense(4096, activation='relu',  name='fc1')(x)
  32.     x = Dense(4096, activation='relu', name='fc2')(x)
  33.     output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)
  34.     model = Model(input_tensor, output_tensor)
  35.     return model
  36. model=VGG16(1000, (img_width, img_height, 3))
  37. model.summary()
复制代码

四、编译

  1. model.compile(optimizer="adam",
  2.               loss     ='sparse_categorical_crossentropy',
  3.               metrics  =['accuracy'])
复制代码
五、训练模子

  1. from tqdm import tqdm
  2. import tensorflow.keras.backend as K
  3. epochs = 10
  4. lr     = 1e-4
  5. # 记录训练数据,方便后面的分析
  6. history_train_loss     = []
  7. history_train_accuracy = []
  8. history_val_loss       = []
  9. history_val_accuracy   = []
  10. for epoch in range(epochs):
  11.     train_total = len(train_ds)
  12.     val_total   = len(val_ds)
  13.    
  14.     """
  15.     total:预期的迭代数目
  16.     ncols:控制进度条宽度
  17.     mininterval:进度更新最小间隔,以秒为单位(默认值:0.1)
  18.     """
  19.     with tqdm(total=train_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=1,ncols=100) as pbar:
  20.         
  21.         lr = lr*0.92
  22.         K.set_value(model.optimizer.lr, lr)
  23.         for image,label in train_ds:   
  24.             """
  25.             训练模型,简单理解train_on_batch就是:它是比model.fit()更高级的一个用法
  26.             想详细了解 train_on_batch 的同学,
  27.             可以看看我的这篇文章:https://www.yuque.com/mingtian-fkmxf/hv4lcq/ztt4gy
  28.             """
  29.             history = model.train_on_batch(image,label)
  30.             train_loss     = history[0]
  31.             train_accuracy = history[1]
  32.             
  33.             pbar.set_postfix({"loss": "%.4f"%train_loss,
  34.                               "accuracy":"%.4f"%train_accuracy,
  35.                               "lr": K.get_value(model.optimizer.lr)})
  36.             pbar.update(1)
  37.         history_train_loss.append(train_loss)
  38.         history_train_accuracy.append(train_accuracy)
  39.             
  40.     print('开始验证!')
  41.    
  42.     with tqdm(total=val_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=0.3,ncols=100) as pbar:
  43.         for image,label in val_ds:      
  44.             
  45.             history = model.test_on_batch(image,label)
  46.             
  47.             val_loss     = history[0]
  48.             val_accuracy = history[1]
  49.             
  50.             pbar.set_postfix({"loss": "%.4f"%val_loss,
  51.                               "accuracy":"%.4f"%val_accuracy})
  52.             pbar.update(1)
  53.         history_val_loss.append(val_loss)
  54.         history_val_accuracy.append(val_accuracy)
  55.             
  56.     print('结束验证!')
  57.     print("验证loss为:%.4f"%val_loss)
  58.     print("验证准确率为:%.4f"%val_accuracy)
复制代码

六、模子评估

  1. from datetime import datetime
  2. current_time = datetime.now() # 获取当前时间
  3. epochs_range = range(epochs)
  4. plt.figure(figsize=(12, 4))
  5. plt.subplot(1, 2, 1)
  6. plt.plot(epochs_range, history_train_accuracy, label='Training Accuracy')
  7. plt.plot(epochs_range, history_val_accuracy, label='Validation Accuracy')
  8. plt.legend(loc='lower right')
  9. plt.title('Training and Validation Accuracy')
  10. plt.xlabel(current_time) # 打卡请带上时间戳,否则代码截图无效
  11. plt.subplot(1, 2, 2)
  12. plt.plot(epochs_range, history_train_loss, label='Training Loss')
  13. plt.plot(epochs_range, history_val_loss, label='Validation Loss')
  14. plt.legend(loc='upper right')
  15. plt.title('Training and Validation Loss')
  16. plt.show()
复制代码

七、猜测

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


八、总结

VGG优缺点分析:
● VGG长处
VGG的结构非常简便,整个网络都使用了同样巨细的卷积核尺寸(3x3)和最大池化尺寸(2x2)。
● VGG缺点
1)训练时间过长,调参难度大。2)需要的存储容量大,不利于部署。比方存储VGG-16权重值文件的巨细为500多MB,不利于安装到嵌入式系统中。
结构说明:
● 13个卷积层(Convolutional Layer),分别用blockX_convX表示
● 3个全连接层(Fully connected Layer),分别用fcX与predictions表示
● 5个池化层(Pool layer),分别用blockX_pool表示
VGG的网络结构比较同一,重复使用卷积层堆叠,然后接最大池化。池化层的窗口是2x2,步长2,这样每次池化后特征图尺寸减半。然后全连接层部门有三个,最后是softmax分类。VGG16和VGG19的区别在于卷积层的数量,比如在某个块中使用2个照旧3个卷积层,大概更后面块中的数量不同。比如,VGG16的配置大概是:块1有2个卷积层,块2有2个,块3有3个,块4有3个,块5有3个,然后全连接层。而VGG19大概在这些块中多加一些卷积层,使得总层数达到19层。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4