• 深度学习21天——卷积神经网络(CNN):天气识别(第5天)


    目录

    一、前期准备

    1.1 设置GPU

    1.2 导入数据

    1.2.1 np.random.seed( i )

    1.2.2 tf.random.set_seed()

    1.3 查看数据

    二、数据预处理

    2.1 加载数据

    2.1.1 image_dataset_from_directory()  

    2.1.2 batch_size

    2.2 可视化数据

    2.3 再次检查数据

    2.4 配置数据集

    三、构建CNN、编译、训练、评估

    3.1 构建CNN

    3.2 编译

    3.3 训练模型

    3.4 模型评估


     活动地址:CSDN21天学习挑战赛

    学习:深度学习100例-卷积神经网络(CNN)天气识别 | 第5天_K同学啊的博客-CSDN博客

    一、前期准备

    1.1 设置GPU

    1. import tensorflow as tf
    2. gpus = tf.config.list_physical_devices("GPU")
    3. if gpus:
    4. gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    5. tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    6. tf.config.set_visible_devices([gpu0],"GPU")

    1.2 导入数据

    1. import matplotlib.pyplot as plt
    2. import os,PIL
    3. # 设置随机种子尽可能使结果可以重现
    4. import numpy as np
    5. np.random.seed(1)
    6. # 设置随机种子尽可能使结果可以重现
    7. import tensorflow as tf
    8. tf.random.set_seed(1)
    9. from tensorflow import keras
    10. from tensorflow.keras import layers,models
    11. import pathlib
    1. # 写入数据文件夹所在的路径
    2. data_dir  =  "D:/jupyter notebook/DL-100-days/datasets/weather_photos/"
    3. data_dir  =  pathlib.Path(data_dir) # 创建了path路径的对象

    相关资料:Python 的 os.path() 和 pathlib.Path()_Looooking的博客-CSDN博客

    1.2.1 np.random.seed( i )

    参考:np.random.seed()随机数种子学习笔记_偶尔躺平的咸鱼的博客-CSDN博客

    随机数种子相当于给我们一个初值,之后按照固定顺序生成随机数(该随机数种子对应的list);如果使用相同的seed( )值,则每次生成的随机数列表都相同;
    ②如果不设置这个值,则系统根据时间来自己选择这个值,此时每次生成的随机数因时间差异而不同。
    ③设置seed()的时,可以调用多次random()向该随机数的列表中添加信息;而再次使用设置的seed()值时,仅一次有效,也就是说调用第二次random()时则脱离该随机数的列表。
    ④seed方法设立的目的是为了能够实现实验的可重复进行,得到相同的随机值结果。
    该设置的初值并没有实际意义

    1. np.random.seed(0) # 先定义一个随机数种子
    2. print(np.random.rand(2, 3)) # 随机生成1个 2×3 的矩阵

    所以,np.random.seed(0) 每次只对下一次生成的随机数起作用,不同的初值生成的随机数不同,调用相同的初值,生成的随机数是相同的

    1. np.random.seed(0) # 先定义一个随机数种子
    2. print(np.random.rand(2, 3)) # 随机生成1个 2×3 的矩阵
    3. np.random.seed(0) # 先定义一个随机数种子
    4. print(np.random.rand(2, 3)) # 随机生成1个 2×3 的矩阵

    输出的两个结果相同

    1.2.2 tf.random.set_seed()

    上面写法是tensorflow2.0的写法,如果是tensorflow1.0则为:set_random_seed()

    1. #tensorflow2.0
    2. tf.random.set_seed(
    3.     seed
    4. )
    5.  
    6.  
    7. #tensorflow1.0
    8. tf.set_random_seed(
    9.     seed
    10. )

    下面以 tf.set_random_seed(i)为例,用法一致

    参考:

    tf.random.set_seed用法_仁义礼智信达的博客-CSDN博客_tf.set_random_seed 和Tensorflow中关于随机数生成种子tf.set_random_seed()_qq_31878983的博客-CSDN博客_tensorflow 随机种子

    用法与 np.random.seed(0)  相近,但分 全局种子操作种子 两种

    1.3 查看数据

    1. # 返回 data.dir 文件夹及所有子文件夹中所有后缀为 .jpg的形成列表后的长度
    2. image_count = len(list(data_dir.glob('*/*.jpg')))
    3. print("图片总数为:",image_count)

    图片总数为: 1125

    1. # 返回该文件夹下所有 sunrise +后面任意 且后缀为.jpg的列表
    2. roses = list(data_dir.glob('sunrise/*.jpg'))
    3. PIL.Image.open(str(roses[0])) # 打开第一个图片

           返回的都是路径,因为PIL.Image.open()专接图片路径,用来直接读取该路径指向的图片。要求路径必须指明到哪张图,不能只是所有图所在的文件夹; 

    二、数据预处理

    2.1 加载数据

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

    1. batch_size = 32
    2. img_height = 180
    3. img_width = 180
    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=123,
    9. image_size=(img_height, img_width),
    10. batch_size=batch_size)

    Found 1125 files belonging to 4 classes.
    Using 900 files for training. 

    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=123,
    9. image_size=(img_height, img_width),
    10. batch_size=batch_size)

    Found 1125 files belonging to 4 classes.
    Using 225 files for validation.

    2.1.1 image_dataset_from_directory()  

    1. tf.keras.preprocessing.image_dataset_from_directory(
    2. directory,
    3. labels="inferred",
    4. label_mode="int",
    5. class_names=None,
    6. color_mode="rgb",
    7. batch_size=32,
    8. image_size=(256, 256),
    9. shuffle=True,
    10. seed=None,
    11. validation_split=None,
    12. subset=None,
    13. interpolation="bilinear",
    14. follow_links=False,
    15. )

    具体见大佬文章:tf.keras.preprocessing.image_dataset_from_directory() 简介_K同学啊的博客-CSDN博客_tf.keras.preprocessing.image

    这里只展示出用到的参数:

    • directory: 数据所在目录。如果标签是inferred(默认),则它应该包含子目录,每个目录包含一个类的图像。否则,将忽略目录结构。
    • validation_split: 0和1之间的可选浮点数,可保留一部分数据用于验证。即选择测试集占数据集总数的比例
    • subsettrainingvalidation之一。仅在设置validation_split时使用。
    • seed: 用于shuffle和转换的可选随机种子。
    • image_size: 从磁盘读取数据后将其重新调整大小。默认:(256,256)。由于管道处理的图像批次必须具有相同的大小,因此该参数必须提供。
    • batch_size: 数据批次的大小。默认值:32

    2.1.2 batch_size

            表示单次传递给程序用以训练的参数个数。比如我们的训练集有1000个数据。这是如果我们设置batch_size=100,那么程序首先会用数据集中的前100个参数,即第1-100个数据来训练模型。当训练完成后更新权重,再使用第101-200的个数据训练,直至第十次使用完训练集中的1000个数据后停止。
    其他参考机器学习中的batch_size是什么?_勤奋的大熊猫的博客-CSDN博客_batch size是什么意思

    2.2 可视化数据

    1. plt.figure(figsize=(20, 10))
    2. for images, labels in train_ds.take(1):
    3. for i in range(20):
    4. ax = plt.subplot(5, 10, i + 1)
    5. plt.imshow(images[i].numpy().astype("uint8"))
    6. plt.title(class_names[labels[i]])
    7. plt.axis("off")

    2.3 再次检查数据

    1. for image_batch, labels_batch in train_ds:
    2. print(image_batch.shape)
    3. print(labels_batch.shape)
    4. break

    Image_batch是形状的张量(32,180,180,3)。这是一批形状180x180x3的32张图片(最后一维指的是彩色通道RGB)。

    Label_batch 是形状(32,)的张量,这些标签对应32张图片
     

    2.4 配置数据集

    shuffle():打乱数据,关于此函数的详细介绍可以参考:https:llzhuanlan.zhihu.com/p/42417456

    prefetch():预取数据,加速运行

    cache():将数据集缓存到内存当中,加速运行

    1. AUTOTUNE = tf.data.AUTOTUNE
    2. train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
    3. val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

    三、构建CNN、编译、训练、评估

    因为与之前的区别不大,所以直接放代码了

    3.1 构建CNN

    1. num_classes = 4
    2. """
    3. 关于卷积核的计算不懂的可以参考文章:https://blog.csdn.net/qq_38251616/article/details/114278995
    4. layers.Dropout(0.4) 作用是防止过拟合,提高模型的泛化能力。
    5. 在上一篇文章花朵识别中,训练准确率与验证准确率相差巨大就是由于模型过拟合导致的
    6. 关于Dropout层的更多介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/115826689
    7. """
    8. model = models.Sequential([
    9. layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
    10. layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3
    11. layers.AveragePooling2D((2, 2)), # 池化层1,2*2采样
    12. layers.Conv2D(32, (3, 3), activation='relu'), # 卷积层2,卷积核3*3
    13. layers.AveragePooling2D((2, 2)), # 池化层2,2*2采样
    14. layers.Conv2D(64, (3, 3), activation='relu'), # 卷积层3,卷积核3*3
    15. layers.Dropout(0.3),
    16. layers.Flatten(), # Flatten层,连接卷积层与全连接层
    17. layers.Dense(128, activation='relu'), # 全连接层,特征进一步提取
    18. layers.Dense(num_classes) # 输出层,输出预期结果
    19. ])
    20. model.summary() # 打印网络结构

    卷积的计算_K同学啊的博客-CSDN博客

    Dropout层 tf.keras.layers.Dropout() 介绍_K同学啊的博客-CSDN博客_keras.layers.dropout

    关于 layers.experimental.preprocessing.Rescaling 查看官方文档tf.keras.layers.Rescaling  |  TensorFlow Core v2.9.1,即将输入值重新调整到新范围的预处理图层

    池化层由之前的最大池化层调整成了平均池化层

    3.2 编译

    1. # 设置优化器
    2. opt = tf.keras.optimizers.Adam(learning_rate=0.001)
    3. model.compile(optimizer=opt,
    4. loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    5. metrics=['accuracy'])

    还是 adam 优化器,不过设置了学习率

    3.3 训练模型

    1. epochs = 10
    2. history = model.fit(
    3. train_ds,
    4. validation_data=val_ds,
    5. epochs=epochs
    6. )

    3.4 模型评估

    1. acc = history.history['accuracy']
    2. val_acc = history.history['val_accuracy']
    3. loss = history.history['loss']
    4. val_loss = history.history['val_loss']
    5. epochs_range = range(epochs)
    6. plt.figure(figsize=(12, 4))
    7. plt.subplot(1, 2, 1)
    8. plt.plot(epochs_range, acc, label='Training Accuracy')
    9. plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    10. plt.legend(loc='lower right')
    11. plt.title('Training and Validation Accuracy')
    12. plt.subplot(1, 2, 2)
    13. plt.plot(epochs_range, loss, label='Training Loss')
    14. plt.plot(epochs_range, val_loss, label='Validation Loss')
    15. plt.legend(loc='upper right')
    16. plt.title('Training and Validation Loss')
    17. plt.show()

  • 相关阅读:
    计算机挑战赛java c组2020年赛题
    Android 10.0 SystemUI启动流程
    云原生k8s的声明式哲学
    mac pro M1(ARM)安装:ftp远程文件互传工具
    【ESD专题】TVS管和贴片压敏电阻的区别
    [MySQL]存储引擎、索引、SQL优化
    解决DDP的参数未参与梯度计算
    将YOLO数据集按照指定比例划分(训练集、验证集、测试集)的详细教程
    公司刚来的00后真卷,上班还没2年,跳到我们公司起薪20k....
    OC-NSNumber和NSValue一般用来装箱拆箱
  • 原文地址:https://blog.csdn.net/qq_47941078/article/details/126160364