第T3周:天气识别

一、前期工作

相比于上一篇教案,这篇将最大池化改为了平均池化,并且增加了Dropout层。最大池化是将池化区域的像素点取最大值,这种方式得到的特征图对纹理特征信息更加敏感。而平均池化则是对池化区域内的图像取平均值,这种方式得到的特征信息对背景信息更加敏感。

在训练神经网络时,尤其是当数据集较小的情况下,过拟合是一个常见问题。Dropout是一种有效的正则化技术,可以减轻过拟合现象。它的基本思想是在每次训练迭代中,随机选择一部分神经元,使其临时失效,即让这些神经元的激活值以一定的概率p变为0。

对于小批量数据,使用Dropout有以下几个主要效果:

  1. 防止过拟合:通过忽略部分特征检测器,Dropout有助于提高神经网络的性能和泛化能力。这是因为模型不能过于依赖任何单一的特征检测器(特征检测器,也被称为关键点检测器,是从图像中找出那些具有代表性、独特性的位置或点。这些位置或点在不同的图像之间有较好的匹配性,因此常常被用于图像配准、目标识别和跟踪等计算机视觉任务。在具体类型上,特征检测器有多种,如SIFT(Scale Invariant Feature Transform)、SURF(Speeded-Up Robust Features)和Harris角点检测等。其中,SIFT算法是一种里程碑式的算法,被誉为目前最有效的特征检测方法。),迫使其学习更鲁棒、更有代表性的特征。
  2. 集成效果:每次迭代时,由于神经元的随机失效,相当于在训练多个子网络并将其平均。这种效应等同于集成了多个不同的网络结构,可以提高模型的稳定性和准确性。
  3. 简化网络结构:由于某些神经元被随机丢弃,网络的某些部分被“冻结”,这可以被视为一个简化的网络结构。这样的网络可能更容易学习和泛化。

为了最大化Dropout的效果,它通常应用于参数较多的层,如全连接层。但需要注意的是,Dropout不应在测试或验证阶段使用,因为它在训练阶段是随机的,而在测试阶段需要完整的网络来评估模型的准确性。

1.设置GPU

import tensorflow as tf 

gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpu[0]
    tf.config.experimental.set_memory_growth(gpu0,True)
    tf.config.set_visible_devices([gpu0,"GPU"])

2.导入数据

import os,PIL,pathlib
import matplotlib.pyplot as plt
import numpy as np

from tensorflow import keras
from tensorflow.keras import layers,models
data_dir = "C:/Users/Dell/训练营/P3/"

data_dir = pathlib.Path(data_dir)

3.查看数据

代码知识点
在这段代码中,*/*.jpg是一个通配符表达式,用于匹配特定目录下的所有子目录中的jpg文件。
具体来说,*表示任意字符,.表示任意字符(除了换行符),所以*.jpg表示以.jpg为扩展名的文件。而*/*.jpg表示以/开头的任意字符(即子目录)后面跟着任意字符,再跟着.jpg扩展名的文件。
因此,data_dir.glob('*/*.jpg')会返回一个迭代器,其中包含了指定目录下所有子目录中以.jpg为扩展名的文件路径。然后通过list()函数将迭代器转换为列表,并使用len()函数计算列表的长度,得到符合条件的文件数量。

image_count = len(list(data_dir.glob('*/*.jpg')))

print("图片的总数为:  ",image_count)

输出
图片的总数为: 1125

roses = list(data_dir.glob('sunrise/*.jpg'))
PIL.Image.open(str(roses[12]))

输出
在这里插入图片描述

二、数据预处理

1.加载数据

代码知识点来自K同学啊tf.keras.preprocessing.image_dataset_from_directory() 简介
函数原型:
tf.keras.preprocessing.image_dataset_from_directory( directory, labels="inferred", label_mode="int", class_names=None, color_mode="rgb", batch_size=32, image_size=(256, 256), shuffle=True, seed=None, validation_split=None, subset=None, interpolation="bilinear", follow_links=False,)
参数

  1. directory: 数据所在目录。如果标签是inferred(默认),则它应该包含子目录,每个目录包含一个类的图像。否则,将忽略目录结构。
  2. labels: inferred(标签从目录结构生成),或者是整数标签的列表/元组,其大小与目录中找到的图像文件的数量相同。标签应根据图像文件路径的字母顺序排序(通过Python中的os.walk(directory)获得)。
  3. label_mode: int:标签将被编码成整数(使用的损失函数应为:sparse_categorical_crossentropy loss)。
    categorical:标签将被编码为分类向量(使用的损失函数应为:categorical_crossentropy loss)。
    binary:意味着标签(只能有2个)被编码为值为0或1的float32标量(例如:binary_crossentropy)。
    None:(无标签)。
  4. class_names: 仅当labels为inferred时有效。这是类名称的明确列表(必须与子目录的名称匹配)。用于控制类的顺序(否则使用字母数字顺序)。
  5. color_mode: grayscale、rgb、rgba之一。默认值:rgb。图像将被转换为1、3或者4通道。
  6. batch_size: 数据批次的大小。默认值:32
  7. mage_size: 从磁盘读取数据后将其重新调整大小。默认:(256,256)。由于管道处理的图像批次必须具有相同的大小,因此该参数必须提供。
  8. shuffle: 是否打乱数据。默认值:True。如果设置为False,则按字母数字顺序对数据进行排序。
  9. seed: 用于shuffle和转换的可选随机种子。
  10. validation_split: 0和1之间的可选浮点数,可保留一部分数据用于验证。
  11. subset:只能为training或validation之一。仅在设置validation_split时使用。指定了要加载的数据集子集,这里设置为"training",表示加载训练集数据。
  12. interpolation: 字符串,当调整图像大小时使用的插值方法。默认为:bilinear。支持bilinear, nearest, bicubic, area, lanczos3, lanczos5, gaussian, mitchellcubic。
  13. follow_links: 是否访问符号链接指向的子目录。默认:False

在计算机科学中,seed=123通常用作随机数生成器的初始值。它没有特殊的含义,只是一个任意选择的整数。通过设置相同的seed值,可以确保每次运行程序时,生成的随机数序列是相同的。这在某些情况下很有用,例如在调试过程中需要重现特定的随机结果,或者在比较不同算法的性能时需要保持一致的随机输入。

batch_size = 32
img_height = 180
img_width = 180
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
 data_dir,
 validation_split=0.2,
 subset="validation",
 seed=123,
 image_size=(img_height, img_width),
 batch_size=batch_size)#使得每个批次的图像数量相同

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

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
 data_dir,
 validation_split=0.2,
 subset="training",
 seed=123,
 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="training",
 seed=123,
 image_size=(img_height, img_width),
 batch_size=batch_size)

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

class_names = train_ds.class_names
print(class_names)

输出
[‘cloudy’, ‘rain’, ‘shine’, ‘sunrise’]

2.可视化

代码知识点
在TensorFlow中.take()是一个方法,它用于从数据集中提取一部分元素.这个方法接受一个参数count ,表示你想要从数据集中获取的元素数量.如果你希望获取前n个元素,你可以传入n作为参数.
此外,需要注意的是,如果count参数值为-1或者大于数据集的大小,那么新的数据集将会包含该数据集的所有元素.
.subplot()是Matplotlib库中的一个函数,用于创建子图.接受三个参数:行数,列数和子图的索引号,例如,plt.subplot(1, 2, 1)将创建一个1行2列的子图网格,并选择第一个子图进行绘制。
.astype("uint8") 是一个用于将数组的数据类型转换为无符号8位整数(uint8)的方法.

plt.figure(figsize=(20, 10))

for images, labels in train_ds.take(1):
    for i in range(20):
        ax = plt.subplot(5, 10, i+1)
        
        plt.imshow(images[i].numpy().astype("uint8"))
        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

输出
(32, 180, 180, 3)
(32,)

4.配置数据集

代码知识点
tf.data.AUTOTUNE是一个特殊的值,用于告诉TensorFlow在运行时自动调整数据加载和预处理的参数,以获得最佳性能。
train_ds = train_ds.cache():这行代码将训练数据集(train_ds)缓存到内存中。缓存可以将数据集存储在内存中,以便更快地访问和处理数据。这对于大型数据集特别有用,因为它可以避免重复读取和预处理数据。
train_ds = train_ds.shuffle(1000): 这行代码将训练数据集随机打乱,并返回一个新的数据集。shuffle函数接受一个参数,表示要打乱的元素数量。在这个例子中,我们使用1000作为参数,这意味着每次从训练数据集中获取下一个批次时,都会随机选择1000个元素进行打乱。
train_ds = train_ds.prefetch(buffer_size=AUTOTUNE): 这行代码将预取操作应用到训练数据集上。预取操作可以在数据实际被模型使用之前将其加载到内存中,从而减少等待时间。prefetch函数接受一个参数buffer_size,表示预取缓冲区的大小。在这里,我们使用AUTOTUNE作为参数,这意味着TensorFlow会自动选择一个合适的缓冲区大小来平衡性能和内存占用。

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

三、构建CNN网络

这个CNN网络比较经典且结构比较简单。

num_class = 4
model = models.Sequential([
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),#预处理,将图像缩放到0-1之间
    
    layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)),#第一次输入时需要声明input_shape
    layers.AveragePooling2D((2, 2)),
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.AveragePooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Dropout(0.3),# 每个神经元有30%的概率被丢弃
    
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(num_class)
])  
    
model.summary()
                  

输出
在这里插入图片描述

四、编译

代码知识点
这行代码将之前创建的优化器对象opt作为参数传递给model.compile()方法,用于配置模型的训练过程。
optimizer=opt:指定使用的优化器为之前创建的opt对象。
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True):指定损失函数为稀疏分类交叉熵损失函数(SparseCategoricalCrossentropy)。
from_logits=True表示模型输出的是未经过激活函数处理的原始预测值。
metrics=[‘accuracy’]:指定评估指标为准确率(accuracy)。

opt = tf.keras.optimizers.Adam(learning_rate=1e-3)#创建Adam优化器对象

model.compile(optimizer=opt,
             loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
             metrics=['accuracy'])

五、训练模型

epochs = 10
history = model.fit(
   train_ds,
   validation_data=val_ds,
   epochs=epochs
)

这里是引用

六、模型评估

代码知识点
一二行从history对象中提取了训练集和验证集的准确率数据,分别存储在变量acc和val_acc中.
三四行从history对象中提取了训练集和验证集的损失值数据,分别存储在变量loss和val_loss中.
epochs_range = range(epochs)这行代码创建了一个范围为0到epochs-1的整数序列,表示训练的轮数。

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()

输出
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值