第三周,天气识别

第三周,天气识别

准备工作

本文将采用CNN实现多云、下雨、晴、日出四种天气状态的识别。较上篇文章,本文为了增加模型的泛化能力,新增了Dropout层并且将最大池化层调整成了平均池化层

使用GPU

import tensorflow as tf
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')

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

我前两周一直使用CPU训练,对训练速度深感疑惑,后来配置了GPU,速度立即就提升了起来,小白在使用GPU时,要根据自己的电脑的GPU选择合适的cuda,cudnn和TensorFlow-gpu,此处不过多简绍,运行结果为

在这里插入图片描述

导入数据

数据集为内部专用链接,不知道是否开源,具体请联系原博主(k同学),data_dir 为数据集在本地的地址。

# 导入数据
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:/study/artificialIntelligence/data/fieveday/weather_photos/"
data_dir = pathlib.Path(data_dir)

查看数据

数据集一共分为cloudy、rain、shine、sunrise四类,分别存放于weather_photos文件夹中以各自名字命名的子文件夹中

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

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

在这里插入图片描述

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

在这里插入图片描述

数据预处理

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

import tensorflow as tf
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
    )
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
    )
class_names = train_ds.class_names
print(class_names)

在这里插入图片描述

数据可视化

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)。这是一批形状180x180x3的32张图片(最后一维指的是彩色通道RGB)。
● Label_batch是形状(32,)的张量,这些标签对应32张图片

配置数据集

● shuffle():打乱数据,关于此函数的详细介绍可以参考:https://zhuanlan.zhihu.com/p/42417456
● prefetch():预取数据,加速运行

prefetch()功能详细介绍:CPU 正在准备数据时,加速器处于空闲状态。相反,当加速器正在训练模型时,CPU 处于空闲状态。因此,训练所用的时间是 CPU 预处理时间和加速器训练时间的总和。prefetch()将训练步骤的预处理和模型执行过程重叠到一起。当加速器正在执行第 N 个训练步时,CPU 正在准备第 N+1 步的数据。这样做不仅可以最大限度地缩短训练的单步用时(而不是总用时),而且可以缩短提取和转换数据所需的时间。如果不使用prefetch(),CPU 和 GPU/TPU 在大部分时间都处于空闲状态。
cache():将数据集缓存到内存当中,加速运行

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)的输入是张量 (Tensor) 形式的 (image_height, image_width, color_channels),包含了图像高度、宽度及颜色信息。不需要输入batch size。color_channels 为 (R,G,B) 分别对应 RGB 的三个颜色通道(color channel)。在此示例中,我们的 CNN 输入,fashion_mnist 数据集中的图片,形状是 (28, 28, 1)即灰度图像。我们需要在声明第一层时将形状赋值给参数input_shape

#构建cnn
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)),#第一层卷积
    layers.AveragePooling2D((2,2)),
    layers.Conv2D(32,(3,3),activation='relu'),#第二层
    layers.AveragePooling2D((2,2)),
    layers.Conv2D(32,(3,3),activation='relu'),#第三层卷积
    layers.Dropout(0.3),
    
    layers.Flatten(),
    layers.Dense(128,activation='relu'),
    layers.Dense(num_classes)
])
model.summary()#打印

在这里插入图片描述

模型编译

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

● 损失函数(loss):用于衡量模型在训练期间的准确率。
● 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
● 指标(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。

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

训练模型

epochs =20
history =model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs
)
Epoch 1/20
29/29 [==============================] - 1s 23ms/step - loss: 0.9966 - accuracy: 0.5967 - val_loss: 0.5374 - val_accuracy: 0.7733
Epoch 2/20
29/29 [==============================] - 0s 16ms/step - loss: 0.4542 - accuracy: 0.8367 - val_loss: 0.5697 - val_accuracy: 0.7422
Epoch 3/20
29/29 [==============================] - 0s 15ms/step - loss: 0.4190 - accuracy: 0.8367 - val_loss: 0.5419 - val_accuracy: 0.7911
Epoch 4/20
29/29 [==============================] - 0s 15ms/step - loss: 0.3246 - accuracy: 0.8744 - val_loss: 0.4502 - val_accuracy: 0.8222
Epoch 5/20
29/29 [==============================] - 0s 15ms/step - loss: 0.2400 - accuracy: 0.9111 - val_loss: 0.5565 - val_accuracy: 0.8000
Epoch 6/20
29/29 [==============================] - 0s 15ms/step - loss: 0.1980 - accuracy: 0.9300 - val_loss: 0.4590 - val_accuracy: 0.8311
Epoch 7/20
29/29 [==============================] - 0s 15ms/step - loss: 0.2072 - accuracy: 0.9122 - val_loss: 0.5483 - val_accuracy: 0.8000
Epoch 8/20
29/29 [==============================] - 0s 16ms/step - loss: 0.1667 - accuracy: 0.9456 - val_loss: 0.4569 - val_accuracy: 0.8533
Epoch 9/20
29/29 [==============================] - 0s 15ms/step - loss: 0.1307 - accuracy: 0.9556 - val_loss: 0.5108 - val_accuracy: 0.8578
Epoch 10/20
29/29 [==============================] - 0s 16ms/step - loss: 0.0930 - accuracy: 0.9689 - val_loss: 0.5777 - val_accuracy: 0.8489
Epoch 11/20
29/29 [==============================] - 0s 15ms/step - loss: 0.1498 - accuracy: 0.9367 - val_loss: 0.6001 - val_accuracy: 0.8667
Epoch 12/20
29/29 [==============================] - 0s 16ms/step - loss: 0.0942 - accuracy: 0.9667 - val_loss: 0.5516 - val_accuracy: 0.8578
Epoch 13/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0798 - accuracy: 0.9689 - val_loss: 0.5350 - val_accuracy: 0.8578
Epoch 14/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0932 - accuracy: 0.9733 - val_loss: 0.5522 - val_accuracy: 0.8844
Epoch 15/20
29/29 [==============================] - 0s 15ms/step - loss: 0.1083 - accuracy: 0.9778 - val_loss: 0.4702 - val_accuracy: 0.8622
Epoch 16/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0603 - accuracy: 0.9889 - val_loss: 0.5070 - val_accuracy: 0.8711
Epoch 17/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0235 - accuracy: 0.9956 - val_loss: 0.5360 - val_accuracy: 0.8844
Epoch 18/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0269 - accuracy: 0.9900 - val_loss: 0.5049 - val_accuracy: 0.8711
Epoch 19/20
29/29 [==============================] - 0s 15ms/step - loss: 0.0128 - accuracy: 0.9989 - val_loss: 0.5290 - val_accuracy: 0.9022
Epoch 20/20
29/29 [==============================] - 0s 16ms/step - loss: 0.0155 - accuracy: 0.9944 - val_loss: 0.5566 - val_accuracy: 0.8756

模型评估

#模型评估
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 = 'Train 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.增加参加训练的特征数量,增加模型的复杂度;
2.使用更复杂的模型:如提升法boosting等集成模型方法,降低偏差;
3.数据扩增
4.提高训练迭代的次数
5.减少正则化参数
过拟合:当训练集误差很小,而验证集/测试集的误差较大时,此时模型是过拟合的,可以认为此时模型已经过度捕捉训练数据中存在的基本信息来,在对验证集和测试集进行决策时,稍微不同的数据就会导致模型的预测大不相同,也就是模型对未知的数据泛化能力较弱,此时模型的方差较大

原因:模型结构复杂,样本少
解决:
1.添加正则化,L1或者L2正则化,降低模型的复杂度:
2.集成学习方法bagging(如随机森林)能有效防止过拟合,降低方差
3.使用交叉验证方法
4.神经网络模型可通过dropout,earlystopping等方法增强模型的泛化能力
5.数据扩增

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值