日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【神经网络】(3) 卷积神经网络(CNN),案例:动物三分类,附python完整代码

發布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【神经网络】(3) 卷积神经网络(CNN),案例:动物三分类,附python完整代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

各位同學好,今天和大家分享一下TensorFlow2.0深度學習中卷積神經網絡的案例。現在有貓、狗、熊貓圖片一千張,構建卷積神經網絡實現圖像的分類預測。


1. 數據加載

將訓練測試數據劃分好后放在同一個文件目錄下,使用tf.keras.preprocessing.image_dataset_from_directory()函數構造數據集。函數的具體用法見:tf.keras.preprocessing.image_dataset_from_directory_自在獨行的博客-CSDN博客_image_dataset_from_directory

訓練數據和驗證數據進行one-hot編碼,便于計算損失,讀入圖像時統一圖片大小size為128*128。batch為64,每次迭代從中取64個樣本。class_names中保存的是根據文件夾名稱生成的標簽。

# 三分類,卷積神經網絡
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers,optimizers,datasets,Sequential
import os  # 設置一下輸出框打印的內容
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # '2'輸出欄只打印error信息,其他亂七八糟的信息不打印#(1)數據獲取
# 加載訓練集數據
filepath1 = 'C:/Users/admin/.../train'
train_ds = tf.keras.preprocessing.image_dataset_from_directory(filepath1,label_mode='categorical',  # "int", "categorical"表示onehot, "binary", or Noneseed=123,image_size=(128, 128),  # resize圖片大小batch_size=64)# 加載驗證集數據
filepath2 = 'C:/Users/admin/.../new_data/val'
val_ds = tf.keras.preprocessing.image_dataset_from_directory(filepath2,label_mode='categorical',seed=123,image_size=(128, 128),batch_size=64)# 加載測試集數據
filepath3 = 'C:/Users/.../new_data/test'
test_ds = tf.keras.preprocessing.image_dataset_from_directory(filepath3,label_mode='int',seed=123,image_size=(128, 128),batch_size=64) # 類別名稱
class_names = train_ds.class_names
print('類別有:',class_names)
# 類別有: ['cats', 'dogs', 'panda']

2. 數據預處理

使用.map()對dataset中的數據進行processing函數中的操作,對每個點的像素值從[0,255]變成[-1,1].shuffle()對數據集重新洗牌打散,但不改變x和y之間的對應關系。

train_ds.take(1) 是指從訓練集數據集中取出1個batch的數據,返回值img存放圖像數據,label存放圖像的標簽。

#(2)數據預處理
def processing(image, label): image = 2 * tf.cast(image, tf.float32) / 255.0 - 1  #[-1,1]之間label = tf.cast(label, tf.int32)  # 修改數據類型return (image, label)train_ds = train_ds.map(processing).shuffle(10000)  #洗牌
val_ds = val_ds.map(processing).shuffle(10000)
test_ds = test_ds.map(processing).shuffle(10000)#(2)數據檢查
for img, label in train_ds.take(1): # 取出一個batch的數據,一個batch有64個樣本print('img.shape:', img.shape)   # img.shape: (64, 128, 128, 3)print('label.shape:', label.shape)  # label.shape: (64, 3)# 數據集展示
import matplotlib.pyplot as plt
for img,label in train_ds.take(1): #取一個batchfor i in range(15):plt.subplot(3,5,i+1)plt.imshow(img[i])  # 每張圖像的shape為(4, 256, 256, 3) plt.xticks([])  # 不顯示xy軸坐標刻度plt.yticks([])
plt.show()

預處理后的圖像展示結果如下:


3. 網絡構建

這里構造一個6層的神經網絡,使用Sequential()容器堆疊網絡各層,layers.Conv2D()構造卷積層,卷積核size為3*3。layers.MaxPool2D()構造池化層,采用最大池化方法。指定padding='same'填充圖像,在傳播過程中保證生成的特征圖的size不變,只改變其channel。指定layers.Dropout(0.2)每次迭代該層每個神經元都有20%的概率被殺死,防止網絡出現過擬合現象。

在卷積池化層和全連接層之間需要指定一個Flatten層layers.Flatten(),輸入至全連接層的圖像需要是一個二維tensor,假設卷積池化層輸出的shape為[b,1,1,64],那么傳入全連接層的shape需要w是[b,64]

#(3)網絡構建
# ==1== 卷積和池化層,2次卷積1次池化
network = Sequential()
# unit1
network.add(layers.Conv2D(32, kernel_size=[3,3], strides=1, padding='same', activation=tf.nn.relu))
network.add(layers.Conv2D(32, kernel_size=[3,3], strides=1, padding='same', activation=tf.nn.relu))
network.add(layers.MaxPool2D(pool_size=[2,2], strides=2, padding='same'))
# unit2
network.add(layers.Conv2D(64, kernel_size=[3,3], strides=1, padding='same', activation=tf.nn.relu))
network.add(layers.Conv2D(64, kernel_size=[3,3], strides=1, padding='same', activation=tf.nn.relu))
network.add(layers.MaxPool2D(pool_size=[2,2], strides=2, padding='same'))
# dropout層
network.add(layers.Dropout(0.2)) #每個神經元都有0.2的概率被殺死# ==2== Flatten層,連接卷積池化層和全連接層
network.add(layers.Flatten())# ==3== 全連接層
network.add(layers.Dense(128, activation=tf.nn.relu))
network.add(layers.Dense(3))  # 輸出層logits層# ==4== 指定輸入層
network.build(input_shape=[None, 128, 128, 3])# ==5== 查看網絡結構
network.summary()

網絡結構如下,param代表該層網絡擁有的參數個數

Model: "sequential"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================conv2d_1 (Conv2D)          (None, 128, 128, 32)      896       conv2d_2 (Conv2D)          (None, 128, 128, 32)      9248      max_pooling2d_1 (MaxPoolin  (None, 64, 64, 32)       0         g2D)                                                            conv2d_3 (Conv2D)          (None, 64, 64, 64)        18496     conv2d_4 (Conv2D)          (None, 64, 64, 64)        36928     max_pooling2d_2 (MaxPoolin  (None, 32, 32, 64)       0         g2D)                                                            dropout_1 (Dropout)         (None, 32, 32, 64)        0         flatten_1 (Flatten)        (None, 65536)             0         dense_1 (Dense)            (None, 128)               8388736   dense_2 (Dense)            (None, 3)                 387       =================================================================
Total params: 8,454,691
Trainable params: 8,454,691
Non-trainable params: 0
_________________________________________________________________

4. 網絡配置

采用學習率數衰減的方法方法,tf.keras.optimizers.schedules.ExponentialDecay(),起初梯度變化大一點能更快接近目標,后續梯度變化不斷減小,越來越逼近最優點。設置早停策略,因為神經網絡在不斷迭代的過程中,準確率不會一直在上升,如果找到某一極值點,且后續多次迭代過程中,網絡效果沒有變的更優的跡象,就使用之前的極值點的結果作為最優解。

#(4)網絡配置
# 設置動態學習率指數衰減
exponential_decay = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate=0.001, #初始學習率decay_steps=2,  # 衰減步長decay_rate=0.96)  # 衰減率# 編譯
network.compile(optimizer=optimizers.Adam(learning_rate=exponential_decay), loss=tf.losses.CategoricalCrossentropy(from_logits=True), # 交叉熵損失metrics=['accuracy'])  # 準確率指標# 早停策略
early_stopping = keras.callbacks.EarlyStopping(monitor = 'val_acc', # 驗證集的準確率作為指標patience = 10, # 最多忍受多少個次循環沒有改進restore_best_weights = True)  # 發生早停時,自動尋找最優的monitor參數

5. 模型訓練

#(5)網絡訓練
# 指定訓練集、驗證集、迭代次數
# 訓練目標和驗證目標需要時one_hot編碼后的
model = network.fit(train_ds,  # 訓練集validation_data=val_ds,  # 驗證集 epochs=10,  # 迭代多少次callbacks= early_stopping, # 回調函數,在訓練過程中的適當時機被調用shuffle = True, # 每輪迭代之前洗牌verbose = 1 # 0為不在標準輸出流輸出日志信息,1:顯示進度條,2:每個epoch輸出一行記錄)

由于時間關系,這里就簡單循環10次,效果如下

Epoch 1/10
33/33 [==============================] - ETA: 0s - loss: 1.1605 - accuracy: 0.4527  WARNING:tensorflow:Early stopping conditioned on metric `val_acc` which is not available. Available metrics are: loss,accuracy,val_loss,val_accuracy
33/33 [==============================] - 75s 2s/step - loss: 1.1605 - accuracy: 0.4527 - val_loss: 0.8374 - val_accuracy: 0.5796
#.................#
#.................#
Epoch 10/10
33/33 [==============================] - ETA: 0s - loss: 0.6362 - accuracy: 0.6985  WARNING:tensorflow:Early stopping conditioned on metric `val_acc` which is not available. Available metrics are: loss,accuracy,val_loss,val_accuracy
33/33 [==============================] - 96s 3s/step - loss: 0.6362 - accuracy: 0.6985 - val_loss: 0.6821 - val_accuracy: 0.6415

6. 模型評估

比較網絡訓練集和驗證集上的準確率和損失,繪圖比較

#(6)模型評估
# ==1== 計算準確率
train_acc = model.history['accuracy']
val_acc = model.history['val_accuracy']# ==2== 損失
train_loss = model.history['loss']
val_loss = model.history['val_loss']# ==3== 曲線圖
epochs_range = range(len(train_acc))  # 橫坐標,網絡循環了幾次# 準確率曲線
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.plot(epochs_range, train_acc, label='Training_acc')
plt.plot(epochs_range, val_acc, label='validation_acc')
plt.legend()
plt.title('Accuracy')# 損失曲線
plt.subplot(1,2,2)
plt.plot(epochs_range, train_loss, label='Training_loss')
plt.plot(epochs_range, val_loss, label='validation_loss')
plt.legend()
plt.title('Loss')

如圖所示訓練集和驗證集的損失都逐漸下降,隨著迭代次數的增加,效果會更好,但要防止過擬合的現象出現。


7. 預測

采用測試集中的圖像數據對網絡進行預測,network.predict()得到輸入圖像分別屬于三個分類的數值,返回numpy類型,使用np.argmax()找到最大值的索引,該索引對應的class_names標簽就是預測得到的該圖像所屬的分類。

#(7)預測
test_pred = []
test_target = []for images, targets in test_ds:  #取一個batch的測試集生成混淆矩陣for image, label in zip(images, targets): # 每次從batch中取出一組# 需要給圖片增加一個維度img_array = tf.expand_dims(image, axis=0) # 使用模型預測圖片中的動物prediction = network.predict(img_array)# 預測結果是預測值最大值索引對應的位置test_pred.append(class_names[np.argmax(prediction)])# 保存真實值的標簽test_target.append(class_names[label])  # label沒有做onehot編碼print('測試結果:',test_pred[:10])
print('真實結果:',test_target[:10])#(8)混淆矩陣
from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd
plt.rcParams['font.sans-serif'] = ['SimSun']  #宋體
plt.rcParams['font.size'] = 15  #設置字體大小# 生成混淆矩陣
conf_numpy = confusion_matrix(test_target, test_pred)
# 將矩陣轉化為 DataFrame
conf_df = pd.DataFrame(conf_numpy, index=class_names ,columns=class_names)  plt.figure(figsize=(8,7))sns.heatmap(conf_df, annot=True, fmt="d", cmap="BuPu")plt.title('混淆矩陣')
plt.ylabel('真實值')
plt.xlabel('預測值')

輸出的前10張圖片的預測結果如下:

測試結果: ['panda', 'dogs', 'cats', 'cats', 'panda', 'panda', 'panda', 'panda', 'dogs', 'panda']
真實結果: ['panda', 'dogs', 'dogs', 'cats', 'panda', 'panda', 'panda', 'panda', 'cats', 'panda']

為了更加清晰的展示預測值和真實值的關系,構建混淆矩陣,如圖。可見一個6層的卷積網絡經過10次循環后,對熊貓的預測精度最高,對狗的預測精度較低,需要增加網絡層數和循環次數。

總結

以上是生活随笔為你收集整理的【神经网络】(3) 卷积神经网络(CNN),案例:动物三分类,附python完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。