第三周:天氣識別

一、環(huán)境配置

python3.6.13,TensorFlow2.4.0-gpu,cuda 11.0,cudnn8.0.5

二、前期準(zhǔn)備

1.設(shè)置GPU

import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
    gpu0 = gpus[0] #如果有多個(gè)GPU,僅使用第0個(gè)GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #設(shè)置GPU顯存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

2.導(dǎo)入數(shù)據(jù)

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 = "D:/jupyter notebook/DL-100-days/datasets/weather_photos/" #數(shù)據(jù)路徑
data_dir = pathlib.Path(data_dir)

3.查看數(shù)據(jù)

數(shù)據(jù)集一共分為cloudy、rain、shine、sunrise四類,分別存放于weather_photos文件夾中以各自名字命名的子文件夾中。

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

print("圖片總數(shù)為:",image_count)
"""
圖片總數(shù)為: 1125
"""

三、數(shù)據(jù)預(yù)處理

1.加載數(shù)據(jù)

使用image_dataset_from_directory方法將磁盤中的數(shù)據(jù)加載到tf.data.Dataset中

batch_size = 32
img_height = 180
img_width = 180
"""
training數(shù)據(jù)
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,  # 數(shù)據(jù)所在目錄。如果標(biāo)簽是inferred(默認(rèn)),則它應(yīng)該包含子目錄,每個(gè)目錄包含一個(gè)類的圖像。否則,將忽略目錄結(jié)構(gòu)。
    validation_split=0.2, # 0和1之間的可選浮點(diǎn)數(shù),可保留一部分?jǐn)?shù)據(jù)用于驗(yàn)證。
    subset="training", # training或validation之一。僅在設(shè)置validation_split時(shí)使用。
    seed=123, # 用于shuffle和轉(zhuǎn)換的可選隨機(jī)種子。
    image_size=(img_height, img_width), # 從磁盤讀取數(shù)據(jù)后將其重新調(diào)整大小。默認(rèn):(256,256)。由于管道處理的圖像批次必須具有相同的大小,因此該參數(shù)必須提供。
    batch_size=batch_size)  # 數(shù)據(jù)批次的大小。默認(rèn)值:32

"""
validation數(shù)據(jù)
"""
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)
"""
Found 1125 files belonging to 4 classes.  1125個(gè)圖片屬于4個(gè)分類
Using 225 files for validation. 用225張作為驗(yàn)證集
"""
class_names = train_ds.class_names
print(class_names)
"""
打印類別名稱
['cloudy', 'rain', 'shine', 'sunrise']
"""

2.可視化數(shù)據(jù)

for images, labels in train_ds.take(1):
    for i in range(20):
        ax = plt.subplot(2, 10, i + 1)
        plt.imshow(images[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]])
        plt.axis("off") # 關(guān)閉坐標(biāo)軸
plt.show()
myplot.png

3.再次檢查數(shù)據(jù)

for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break
"""
(32, 180, 180, 3)
(32,)
"""

4.配置數(shù)據(jù)集

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():打亂數(shù)據(jù)
  • prefetch():預(yù)取數(shù)據(jù),加速運(yùn)行

prefetch()功能詳細(xì)介紹:CPU 正在準(zhǔn)備數(shù)據(jù)時(shí),加速器處于空閑狀態(tài)。相反,當(dāng)加速器正在訓(xùn)練模型時(shí),CPU 處于空閑狀態(tài)。因此,訓(xùn)練所用的時(shí)間是 CPU 預(yù)處理時(shí)間和加速器訓(xùn)練時(shí)間的總和。prefetch()將訓(xùn)練步驟的預(yù)處理和模型執(zhí)行過程重疊到一起。當(dāng)加速器正在執(zhí)行第 N 個(gè)訓(xùn)練步時(shí),CPU 正在準(zhǔn)備第 N+1 步的數(shù)據(jù)。這樣做不僅可以最大限度地縮短訓(xùn)練的單步用時(shí)(而不是總用時(shí)),而且可以縮短提取和轉(zhuǎn)換數(shù)據(jù)所需的時(shí)間。如果不使用prefetch(),CPU 和 GPU/TPU 在大部分時(shí)間都處于空閑狀態(tài):


未使用prefetch.png

使用prefetch()可顯著減少空閑時(shí)間:


使用prefetch.png
  • cache():將數(shù)據(jù)集緩存到內(nèi)存當(dāng)中,加速運(yùn)行

四、構(gòu)建CNN網(wǎng)絡(luò)模型

卷積神經(jīng)網(wǎng)絡(luò)(CNN)的輸入是張量 (Tensor) 形式的 (image_height, image_width, color_channels),包含了圖像高度、寬度及顏色信息。不需要輸入batch size。color_channels 為 (R,G,B) 分別對應(yīng) RGB 的三個(gè)顏色通道(color channel)。在此示例中,我們的 CNN 輸入,fashion_mnist 數(shù)據(jù)集中的圖片,形狀是 (28, 28, 1)即灰度圖像。我們需要在聲明第一層時(shí)將形狀賦值給參數(shù)input_shape。

"""
layers.Dropout(0.3) 作用是防止過擬合,提高模型的泛化能力。
在上一篇文章花朵識別中,訓(xùn)練準(zhǔn)確率與驗(yàn)證準(zhǔn)確率相差巨大就是由于模型過擬合導(dǎo)致的
"""

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'),  # 全連接層,特征進(jìn)一步提取
    layers.Dense(num_classes)  # 輸出層,輸出預(yù)期結(jié)果
])

model.summary()  # 打印網(wǎng)絡(luò)結(jié)構(gòu)
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
rescaling (Rescaling)        (None, 180, 180, 3)       0         
_________________________________________________________________
conv2d (Conv2D)              (None, 178, 178, 16)      448       
_________________________________________________________________
average_pooling2d (AveragePo (None, 89, 89, 16)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 87, 87, 32)        4640      
_________________________________________________________________
average_pooling2d_1 (Average (None, 43, 43, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 41, 41, 64)        18496     
_________________________________________________________________
dropout (Dropout)            (None, 41, 41, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 107584)            0         
_________________________________________________________________
dense (Dense)                (None, 128)               13770880  
_________________________________________________________________
dense_1 (Dense)              (None, 4)                 516       
=================================================================
Total params: 13,794,980
Trainable params: 13,794,980
Non-trainable params: 0
_________________________________________________________________

五、編譯模型

在準(zhǔn)備對模型進(jìn)行訓(xùn)練之前,還需要再對其進(jìn)行一些設(shè)置。以下內(nèi)容是在模型的編譯步驟中添加的:

  • 損失函數(shù)(loss):用于衡量模型在訓(xùn)練期間的準(zhǔn)確率。
  • 優(yōu)化器(optimizer):決定模型如何根據(jù)其看到的數(shù)據(jù)和自身的損失函數(shù)進(jìn)行更新。
  • 指標(biāo)(metrics):用于監(jiān)控訓(xùn)練和測試步驟。以下示例使用了準(zhǔn)確率,即被正確分類的圖像的比率。
# 設(shè)置優(yōu)化器
opt = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=opt,
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

六、訓(xùn)練模型

epochs = 10 # 10個(gè)批次
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
"""
訓(xùn)練了10個(gè)epoch 最后精度達(dá)到0.8844
"""
Epoch 1/10
29/29 [==============================] - 9s 65ms/step - loss: 1.9558 - accuracy: 0.5181 - val_loss: 0.6152 - val_accuracy: 0.7333
Epoch 2/10
29/29 [==============================] - 0s 15ms/step - loss: 0.5536 - accuracy: 0.7833 - val_loss: 0.5670 - val_accuracy: 0.7422
Epoch 3/10
29/29 [==============================] - 0s 15ms/step - loss: 0.4033 - accuracy: 0.8678 - val_loss: 0.6584 - val_accuracy: 0.7600
Epoch 4/10
29/29 [==============================] - 0s 15ms/step - loss: 0.2977 - accuracy: 0.8802 - val_loss: 0.6118 - val_accuracy: 0.7911
Epoch 5/10
29/29 [==============================] - 0s 15ms/step - loss: 0.2101 - accuracy: 0.9064 - val_loss: 0.3968 - val_accuracy: 0.8711
Epoch 6/10
29/29 [==============================] - 0s 15ms/step - loss: 0.1321 - accuracy: 0.9562 - val_loss: 0.4799 - val_accuracy: 0.8222
Epoch 7/10
29/29 [==============================] - 0s 15ms/step - loss: 0.1543 - accuracy: 0.9524 - val_loss: 0.5195 - val_accuracy: 0.8400
Epoch 8/10
29/29 [==============================] - 0s 15ms/step - loss: 0.1011 - accuracy: 0.9598 - val_loss: 0.5621 - val_accuracy: 0.8400
Epoch 9/10
29/29 [==============================] - 0s 15ms/step - loss: 0.0695 - accuracy: 0.9818 - val_loss: 0.4733 - val_accuracy: 0.8711
Epoch 10/10
29/29 [==============================] - 0s 15ms/step - loss: 0.0639 - accuracy: 0.9797 - val_loss: 0.5442 - val_accuracy: 0.8844

七、模型評估

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()
Accuracy.png

八、總結(jié)

本次學(xué)習(xí)內(nèi)容為天氣識別,與之前不同的是需要導(dǎo)入數(shù)據(jù)集,學(xué)習(xí)到了如何導(dǎo)入數(shù)據(jù)集,以及將磁盤中的數(shù)據(jù)如何加載到tf.data.Dataset中,學(xué)習(xí)了image_dataset_from_directory()的使用以及參數(shù)的一些說明。加載完數(shù)據(jù)集以后,配置過程中學(xué)習(xí)了shuffle()函數(shù)的使用,預(yù)取數(shù)據(jù)方法prefetch()和緩存數(shù)據(jù)cache()。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容