K同学[365天深度学习训练营]第一周记录T3天气识别

>- **🍨 本文为[🔗365天深度学习训练营](https://mp.weixin.qq.com/s/rbOOmire8OocQ90QM78DRA) 中的学习记录博客**
>- **🍖 原作者:[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** 

我的环境:

- 系统环境:WSL2+Ubuntu22.04

- 语言环境:Python3.8.18

- 编译器:vscode+jupyter notebook

- 深度学习环境:TensorFlow2.10.0

T3:天气识别

🍺要求

  1. 本地读取并加载数据。(完成)
  2. 测试集accuracy到达93% (最终达到96.44%,完成)

🍻拔高

  1. 测试集accuracy到达95%(最终达到96.44%,完成)
  2. 调用模型识别一张本地图片(完成)

prefetch()

本期介绍了一个应该挺有用的函数:prefetch()

正常的训练进程是:

cpu准备数据批1gpu训练数据批1cpu准备数据批2gpu训练数据批2C3→G3

在一方工作的时候另一方处于闲置状态,浪费了大量的时间。

prefetch()的作用是将准备数据和训练数据的行为并行进行:

cpu准备数据批1gpu训练数据批1同时cpu准备数据批2gpu训练数据批2同时cpu准备数据批3C3G4C4、G5

理论上最高可以做到省略50%的训练时间。

测试训练时间:

Epoch 10/10
29/29 [==============================] - 1s 18ms/step - loss: 0.1480 - accuracy: 0.9433 - val_loss: 0.4325 - val_accuracy: 0.8267

取消prefetch()函数的参与:

train_ds = train_ds.cache().shuffle(1000)
val_ds = val_ds.cache() 

发现训练速度为:

Epoch 10/10
29/29 [==============================] - 0s 17ms/step - loss: 0.0949 - accuracy: 0.9678 - val_loss: 0.4347 - val_accuracy: 0.8800

测试,使用了并行反而慢了1ms。

分析原因可能是因为该数据集过小,函数进行任务分配的时间>直接用GPU进行数据准备的时间

所以该函数适合在大批次量的数据集、复杂模型上使用,在本次作业中不适合

模型优化1(无效):

周期调至50,观察训练记录:

训练集准确率趋近1,验证集准确率却低于90%

老问题,过拟合

尝试降低模型复杂度:正则化增加dropout层减少卷积层都无改善,验证准确率始终低于90%。

优化2(升至92.44%):

重新分析数据集特征,意识到训练样本数只有900,样本数过少

恢复回初始模型,采用数据增强的方式来获得更多样本:

data_augmentation = tf.keras.Sequential([
    layers.experimental.preprocessing.RandomRotation(factor=0.2)
])
augmented_train_ds = train_ds.map(lambda x, y: (data_augmentation(x, training=True), y))
epochs = 200
history = model.fit(
  augmented_train_ds,
  validation_data=val_ds,
  epochs=epochs
)

该函数的作用是在每次训练周期开始时将输入图像随机旋转<20°

使得模型获得各种偏移的输入图像

同时考虑到因为输入图像的增强,模型更难获得规律,将训练周期增加为200

 训练记录如下:

Epoch 200/200
2023-12-06 22:00:01.735523: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:114] Plugin optimizer for device_type GPU is enabled.
29/29 [==============================] - 2s 61ms/step - loss: 0.0015 - accuracy: 1.0000 - val_loss: 0.5383 - val_accuracy: 0.9244

训练集准确率趋近1验证集准确率升至0.9244

优化3(失败):

模型仍有轻度过拟合,尝试少量减少模型复杂度

2的基础上增加第二个dropout

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(64, (3, 3), activation='relu'),  
    layers.Dropout(0.3),  
    
    layers.Flatten(),                       
    layers.Dropout(0.3),   #增加第二个dropout层
    layers.Dense(128, activation='relu'),   
    layers.Dense(num_classes)               
])

代码重新运行,结果:

训练集准确率趋近1,测试集准确率反而下降

优化4(升至95.11%):

重新分析图像,发现模型准确率上升波动非常大。

3的基础上尝试缩小优化器步长

# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.0001)

同时为模型设置早停函数:

class CustomCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        # 获取验证集准确率
        val_accuracy = logs.get('val_accuracy')
        # 添加条件判断,如果验证集准确率大于0.95,则停止训练
        if val_accuracy > 0.95:
            print("Validation accuracy > 0.95. Stopping training.")
            self.model.stop_training = True
# 创建自定义回调实例
custom_callback = CustomCallback()

epochs = 200
history = model.fit(
  augmented_train_ds,
  validation_data=val_ds,
  epochs=epochs,
  callbacks=[custom_callback] 
)

代码重新运行,结果如下:

Epoch 106/200
 1/29 [>.............................] - ETA: 1s - loss: 0.0332 - accuracy: 1.0000
2023-12-06 21:42:21.155474: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:114] Plugin optimizer for device_type GPU is enabled.
28/29 [===========================>..] - ETA: 0s - loss: 0.0594 - accuracy: 0.9777 Validation Accuracy at epoch 106: 0.9511111378669739
Validation accuracy > 0.95. Stopping training.
29/29 [==============================] - 2s 58ms/step - loss: 0.0594 - accuracy: 0.9778 - val_loss: 0.2358 - val_accuracy: 0.9511

成功跳出,最终验证集准确率0.9511,完成目标。

优化5(升至96.00%):

观察图像,发现上升仍有少量波动,且还有上升空间。

4的基础上再次缩小优化器步长:

# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.00005)

增加周期数1000,上调早停准确率0.96

augmented_train_ds = train_ds.map(lambda x, y: (data_augmentation(x, training=True), y))
class CustomCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        # 获取验证集准确率
        val_accuracy = logs.get('val_accuracy')
        # 添加条件判断,如果验证集准确率大于0.96,则停止训练
        if val_accuracy > 0.96:
            print("Validation accuracy > 0.96. Stopping training.")
            self.model.stop_training = True
# 创建自定义回调实例
custom_callback = CustomCallback()

epochs = 1000
history = model.fit(
  augmented_train_ds,
  validation_data=val_ds,
  epochs=epochs,
  callbacks=[custom_callback] 
)

代码重新运行,训练结果为:

Epoch 176/1000
 1/29 [>.............................] - ETA: 1s - loss: 0.0114 - accuracy: 1.0000
2023-12-06 22:32:37.179504: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:114] Plugin optimizer for device_type GPU is enabled.
29/29 [==============================] - ETA: 0s - loss: 0.0238 - accuracy: 0.9944Validation accuracy > 0.96. Stopping training.
29/29 [==============================] - 2s 60ms/step - loss: 0.0238 - accuracy: 0.9944 - val_loss: 0.2558 - val_accuracy: 0.9600

最终达到(96.00%)

优化6(最高96.44%):

准确率上升仍有轻微波动

5的基础上再次缩小优化器步长:

# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.00001)

上调早停准确率0.965:

if val_accuracy > 0.965:
            print("Validation accuracy > 0.965. Stopping training.")
            self.model.stop_training = True

对0.9600附近进行进一步探索

于是代码自优化器设置单元格开始继续运行,最终未能出现0.965以上的模型,观察训练记录,准确率最高为:

Epoch 45/1000
 1/29 [>.............................] - ETA: 1s - loss: 0.0016 - accuracy: 1.0000
2023-12-06 23:13:19.872240: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:114] Plugin optimizer for device_type GPU is enabled.
29/29 [==============================] - 2s 60ms/step - loss: 0.0069 - accuracy: 0.9989 - val_loss: 0.3044 - val_accuracy: 0.9644

最高96.44%的准确率

可以通过在模型中记录每个周期的模型,采用回溯的方法找回这个模型

然后用再次调低优化器步长的方式做进一步拟合

介于时间问题,不做后续扩展

调用模型识别一张本地图片:

模型调用识别代码:

import numpy as np
from tensorflow.keras.preprocessing import image
# 从本地读取图片
img_path = "/home/wjh/CNN/练习/T3天气识别/QQ图片20231206230208.jpg"  # 替换为你的图片路径
img = image.load_img(img_path, target_size=(img_height, img_width))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)  # 添加一个维度,以符合模型输入的要求

# 预处理图像
img_array = np.vstack([img_array])  # 添加一个维度,以符合模型输入的要求

# 使用模型进行预测
predictions = model.predict(img_array)

# 获取预测结果
predicted_class = np.argmax(predictions[0])
predicted_class_name = class_names[predicted_class]

# 打印结果
print(f"Predicted class and class_name: {predicted_class} {predicted_class_name}")

输出为:

1/1 [==============================] - 0s 21ms/step
Predicted class and class_name: 3 sunrise

成功

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

54afive

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

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

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

打赏作者

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

抵扣说明:

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

余额充值