【深度学习21天学习挑战赛】3、使用自制数据集——卷积神经网络(CNN)天气识别

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

通过前两课的学习,加上私底下恶补基础,照猫画虎的基本算是掌握了卷积神经网络-CNN搭建模型的基本方法。

之前使用的,都是使用的现成的数据集,想想,如果今后真的需要应用,肯定需要使用自制数据集来训练模型,刚好k同学啊老师,就安排了这么一课

现将学习总结如下:(完整代码附后


1、数据分析

从老师那下载的数据,weather_photos文件夹下共四类(四个目录):

  • cloudy (阴天/多云) :300张图片
  • rain(雨天):215张图片
  • shine (阳光明媚):253张图片
  • sunrise(日出/朝霞):357张图片

图片都是jpg格式

在这里插入图片描述
同时,也可以看到,数据图片的尺寸各异
在这里插入图片描述

通过分析,可知,在使用数据集之前,至少提前做好三件事

  • 加载数据
  • 统一尺寸
  • 分配标签

2、加载数据

data_dir = "./weather_photos/"                     # 路径变量
data_dir = pathlib.Path(data_dir)                  # 构造pathlib模块下的Path对象
image_count = len(list(data_dir.glob('*/*.jpg')))  # 使用Path对象glob方法获取所有jpg格式图片
print("图片总数为:",image_count)

在这里插入图片描述

  • 我是放到程序同目录下,所以路径是"./weather_photos/",你也可以根据实际路径,如:data_dir = "D:/datasets/weather_photos/"
  • 更多用法,自己去补一下路径处理库pathlib使用详解

显示图片:

roses = list(data_dir.glob('sunrise/*.jpg'))  # 使用Path对象glob方法获取sunrise目录下所有jpg格式图片
PIL.Image.open(str(roses[6]))                 #显示一张图片

在这里插入图片描述

3、数据预处理

3.1、预处理

先定义几个重要变量:

batch_size = 32
img_height = 180
img_width = 180
  • batch_size:深度学习,是把数据分批喂入神经网络的,所以,我们来定义,每批多少条数据
  • img_height:定义图片高度,之前说过,自制数据图片尺寸不一,所以,我们来把图片进行统一处理
  • img_width:定义图片宽度,之前说过,自制数据图片尺寸不一,所以,我们来把图片进行统一处理

使用: tf.keras.preprocessing.image_dataset_from_directory将文件夹中的数据加载到tf.data.Dataset中,且加载的同时会打乱数据

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,                     # 上面定义好的变量
    validation_split=0.2,         # 保留20%当做测试集
    subset="training",
    seed=123,
    image_size=(img_height, img_width),# 上面定义好的变量
    batch_size=batch_size)             # 上面定义好的变量

参数

  • directory: 数据所在目录。
  • validation_split: 0和1之间的数,可保留一部分数据用于验证。如:0.2=20%
  • subset: trainingvalidation。仅在设置validation_split时使用。
  • image_size:从磁盘读取数据后将其重新调整大小。
  • batch_size: 数据批次的大小。默认值:32
    后调用class_names将返回以目录同名的类名
class_names = train_ds.class_names
print(class_names)

在这里插入图片描述

3.2、可视化

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

在这里插入图片描述

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

在这里插入图片描述

  • image_batch: (32, 180, 180, 3) 第一个32是批次尺寸,180是我们修改后的宽高,3是RGB三个通道
  • labels_batch:(32,) 一维,32个标签

3.3、配置数据集

AUTOTUNE = tf.data.AUTOTUNE                                         
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE) 
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)  # 
  • shuffle:数据乱序
  • prefetch:预取数据加速运行
  • cache:数据集缓存到内存中,加速

4、构建CNN网络

我们之前学习的,输入数据集形状都是(28, 28, 1),也就是说,28*28的图像,只有一个颜色通道(灰度)

今天的数据,明显是180*180的图片,并且是RGB三个维度

所以我们需要在声明第一层时定义数据形状,参数:input_shape

num_classes = 4 
model = models.Sequential([
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
    layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3  
    layers.AveragePooling2D((2, 2)),               # 池化层1,2*2采样
    layers.Conv2D(32, (3, 3), activation='relu'),  # 卷积层2,卷积核3*3
    layers.AveragePooling2D((2, 2)),               # 池化层2,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层3,卷积核3*3
    layers.Dropout(0.3),  
    layers.Flatten(),                       # Flatten层,连接卷积层与全连接层
    layers.Dense(128, activation='relu'),   # 全连接层,特征进一步提取
    layers.Dense(num_classes)               # 输出层,输出预期结果
])

model.summary()  # 打印网络结构
  • 关于model.summary()打印形状,可以看这个
  • layers.Dropout(0.4) 作用是防止过拟合,提高模型的泛化能力。什么是过拟合
  • 关于Dropout层的更多介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/115826689
    在这里插入图片描述

5、配置模型

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

这里没什么好说的,和之前用到的损失函数优化器一样

使用:learning_rate=0.001是设置学习率

  • sgd默认为0.01
  • adam默认为0.001

6、训练模型

epochs = 10

history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
  • validation_data:指定测试集数据

  • epochs :训练迭代次数
    在这里插入图片描述
    输出说明

  • loss:训练集损失值

  • accuracy:训练集准确率

  • val_loss:测试集损失值

  • val_accruacy:测试集准确率

7、模型评估

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

在这里插入图片描述

  • history :训练返回的数据,字典类型,字段:accuracy、loss、val_loss、val_accuracy

8、完整源码

import matplotlib.pyplot as plt
import os,PIL
# 设置随机种子尽可能使结果可以重现
import numpy as np
np.random.seed(1)
# 设置随机种子尽可能使结果可以重现
import tensorflow as tf
tf.random.set_seed(1)
from tensorflow import keras
from tensorflow.keras import layers,models
import pathlib
data_dir = "./weather_photos/"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*.jpg')))
print("图片总数为:",image_count)
roses = list(data_dir.glob('sunrise/*.jpg'))
PIL.Image.open(str(roses[0]))
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="training",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)
plt.figure(figsize=(20, 10))

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

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")
for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break
# AUTOTUNE = tf.data.AUTOTUNE
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
num_classes = 4
model = models.Sequential([
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
    
    layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3  
    layers.AveragePooling2D((2, 2)),               # 池化层1,2*2采样
    layers.Conv2D(32, (3, 3), activation='relu'),  # 卷积层2,卷积核3*3
    layers.AveragePooling2D((2, 2)),               # 池化层2,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层3,卷积核3*3
    layers.Dropout(0.3),  
    
    layers.Flatten(),                       # Flatten层,连接卷积层与全连接层
    layers.Dense(128, activation='relu'),   # 全连接层,特征进一步提取
    layers.Dense(num_classes)               # 输出层,输出预期结果
])

model.summary()  # 打印网络结构
# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.001)

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

学习日记

1,学习知识点

a、自制数据集的基本使用方法
b、pathlib模块的基本使用
c、tf.keras.preprocessing.image_dataset_from_directory基本使用方法

2,学习遇到的问题

继续啃西瓜书,恶补基础

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

藏蓝色攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值