TensorFlow Specialization Course 1學習筆記 Week 3

TensorFlow Specialization Course 1學習筆記 Week 3

卷積神經網絡實現服飾分類器

在上一個課程中,我們使用深度神經網絡實現了一個服飾分類器。深度神經網絡包含輸入層、輸出層和隱藏層。如何讓我們的分類器準確率更高呢?這一次,我們使用卷積神經網絡來實現我們的分類器,來看看效果如何。

我們在全連接層之前添加幾個卷積層和池化層。卷積層用來提取圖像中的特徵,將提取到的特徵信息傳入全連接層相比直接將圖像像素值傳入全連接層,可以顯著提高分類器的準確率。池化層用來壓縮圖像,同時保留圖像的特徵內容。

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

# 因爲卷積層的輸入需爲一個張量,所以這樣訓練集和測試卷都需要reshape爲一個四維的張量
# reshape前training_images爲60000個28x28x1的元素在一個列表中,reshape後training_images爲一個四維列表60000x28x28x1。
training_images=training_images.reshape(60000, 28, 28, 1)

training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  
  # 定義卷積層。64爲需要生成的卷積數(卷積核的數量),(3,3)爲卷積核的大小,激活函數使用relu
  # 每一個卷積核都會與輸入卷積計算得到一個結果。輸入爲28x28x1,這裏64個卷積核,則輸出爲26x26x64。
  tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
  
  # MaxPooling層用來壓縮圖像,同時保留圖像的特徵內容
  # 尺度爲(2,2)的池化層將圖像大小壓縮爲原來的一半,上一層卷積層的輸出爲26x26x64
  # 經過這個池化層後,輸出爲13x13x64
  tf.keras.layers.MaxPooling2D(2, 2),
    
  tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 調用model.summary()方法,得到整個網絡的基本信息,具體看下面輸出
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)

model.summary()的輸出如下

Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_3 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_6 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_7 (Dense)              (None, 10)                1290      
=================================================================
Total params: 243,786
Trainable params: 243,786
Non-trainable params: 0

使用了卷積神經網絡的服飾分類器在訓練11次迭代後,就可以在訓練集上得到99.8%的準確率,在測試集上得到的99.1%準確率。

可視化卷積層和池化層的輸出結果

輸入測試集中前100個圖像的標籤。

print(test_labels[:100])

在上面的輸出中,我們找到第0、23和28個的標籤都是9,9代表鞋子。在下面的代碼中,我們選擇這三個都是鞋子的圖像。

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 63
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

activation_model.predict()得到的結果是一個列表,包含神經網絡的每一層輸出結果。這裏的for循環取得是第一個卷積層、第一個池化層、第二個卷積層和第二個池化層的結果,當x=0時,取第一個卷積層的輸出結果。卷積或池化的結果都是有64個深度的,因爲我們使用了64個卷積核。CONVOLUTION_NUMBER代表我們想要哪一個深度的結果。

舉個例子,看for循環中這兩行代碼

f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')

當x=0,CONVOLUTION_NUMBER=63,我們取第一個卷積層的輸出結果:1x26x26x64,從中取出最後一個卷積覈計算的結果1x26x26x1,並將它展示出來。

自己運行上面的代碼,並不斷修改參數來觀察有趣的輸出吧。

爲什麼使用卷積?

和只使用全連接層相比,卷積層的兩個主要優勢在於參數共享和稀疏連接。

直接使用全連接層的話,需要的參數會非常多。

參數共享:觀察發現,特徵檢測入垂直邊緣檢測如果適用於圖片的某個區域,那麼它也可能適用於圖片的其他區域。整張圖片共享特徵檢測器。

稀疏連接:第二個方法是使用稀疏連接,我來解釋下。這個 0 是通過 3×3 的卷積計算得到的,它只 依賴於這個 3×3 的輸入的單元格,右邊這個輸出單元(元素 0)僅與 36 個輸入特徵中 9 個 相連接。而且其它像素值都不會對輸出產生任影響,這就是稀疏連接的概念。
WhyConv
神經網絡可以通過這兩種機制減少參數,以便我們用更小的訓練集來訓練它,從而預防過度擬合。你們也可能聽過,卷積神經網絡善於捕捉平移不變。通過觀察可以發現,向右移動兩個像素,圖片中的貓依然清晰可見,因爲神經網絡的卷積結構使得即使移動幾個像素,這張圖片依然具有非常相似的特徵,應該屬於同樣的輸出標記。實際上,我們用同一個過濾器生成各層中,圖片的所有像素值,希望網絡通過自動學習變得更加健壯,以便更好地取得所期望的平移不變屬性。


關於卷積神經網絡的詳細內容請看:https://blog.csdn.net/JSerenity/article/details/89330545

本筆記詳細內容請看:https://github.com/lmoroney/dlaicourse/blob/master/Course 1 - Part 6 - Lesson 2 - Notebook.ipynb

課程地址:https://www.coursera.org/learn/introduction-tensorflow/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章