iT邦幫忙

0

Python 演算法 Day 19 - 卷積神經網路 (CNN) 簡介

  • 分享至 

  • xImage
  •  

Chap.III 深度學習與模型優化

Part 4: 卷積神經網路 (CNN)

Day18提到了數字與文字辨識的機器學習。
然而實際上,我們應該進一步考慮圖片的每個像素權重與各個像素間彼此的關聯性。
舉例來說,一張帶有數字的圖片,在中心區塊的權重(紅圈處)理當明顯比角落的權重要高。
https://ithelp.ithome.com.tw/upload/images/20220530/20138527HqlibhoODZ.png

為此,科學家提出了新方法:Convolutional Neural Network

也就是常看到的 CNN 卷積神經網路

卷積神經網路 (CNN) 是一種前饋神經網路 (Feedforward Neural Network)。
藉影像處理,從圖片中萃取特徵,使特徵抽象化 (Abstraction),從而更準確辨識影像。
https://ithelp.ithome.com.tw/upload/images/20220523/20138527qLcmmGWzeX.png

常由多個卷積層與池化層 Convolution & Pooling;和全連接層 Fully Connected 組成。
此結構使 CNN 與其他深度學習相比,在圖像和語音辨識表現得更好。
https://ithelp.ithome.com.tw/upload/images/20220523/20138527TTby2h51MV.png
原圖網址

4-1. Assumption 假設

CNN 有兩大假設

Local Connectivity 局部連接

即是每個神經元僅接收上一層部分神經元的傳導,又稱 Receptive Field 感知域。

Share Weight 共享權重

每個感知域對下一隱藏層均使用相同的權重,即 Feature Detector 也稱 Filter。

4-2. Function of Layers 各層功能

A. Convolution Layer 卷積層

甚麼是卷積運算?

即是將 "Input" 與 "Filter" 以 numpy nd array 的方式相乘後加總

假設今天我們有一個 7*7 的 input image
https://ithelp.ithome.com.tw/upload/images/20220524/20138527fZJeZsRSOf.png
我們使用一個 3*3 的 Feature Detector(又稱 Filter)stride=1, 1 來轉換:
https://ithelp.ithome.com.tw/upload/images/20220525/201385277HyhAViTAX.png

這樣一來我們就把原圖的 7*7 個特徵,萃取成 5*5 個特徵了!

實例上,我們常用卷積運算萃取物體邊界
https://ithelp.ithome.com.tw/upload/images/20220523/20138527zd9CVR2Get.png

甚至搭配 Relu 函數,進一步淬煉物體形狀(因負值都變成 0,輪廓更顯著)
https://ithelp.ithome.com.tw/upload/images/20220523/20138527KQYU0ktBQJ.png

不同的 Filter

除上述自訂的 Filter,也很常使用以下幾種濾波器:

  1. Denosing 去噪:濾波器內訊號平均,使噪訊被模糊化。
    https://ithelp.ithome.com.tw/upload/images/20220531/20138527cZoqrrdX41.png
    https://ithelp.ithome.com.tw/upload/images/20220530/20138527HMqTcwMI7z.png
  2. Sharpening 銳利化:中間訊號特別強,拉大每個像素與周遭的差距。
    https://ithelp.ithome.com.tw/upload/images/20220531/20138527JxSfJZmAln.png
    https://ithelp.ithome.com.tw/upload/images/20220530/20138527WCuaQM8gtB.png

重要參數

tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), strides=(2, 2), padding='same', activation='relu')
  1. filters:就是你該卷積層想要使用多少個 filters。常設 4 的倍數。
  2. kernel_size:你使用的 filter 的 shape。常設奇數邊長的正方形(3*3, 5*5 等)。
  3. strides:滑動步長,計算滑動視窗時移動的格數。默認 (1, 1)。
  4. padding:補 0 策略,卷積層取 kernel_size 滑動視窗時,若超越邊界,是選擇
    放棄這個 output 點(valid)、一律補零(same)、或是不計算超越邊界的 Input 值(causal)。
    因為卷積後圖形會變小,為了不讓圖片與原本大小有差異,會在周圍補上 0 維持原本圖片大小
    https://ithelp.ithome.com.tw/upload/images/20220530/20138527rECmrHvOTV.png
  5. activation:選擇你想使用的激勵函數。默認 None。

B. Pooling Layer 池化層

若說卷積層是用來萃取「精華」,那麼池化層就是用來「壓縮並保留」重要資訊的方法。
以上例延伸,使用較常見的 Max Pooling(另一種為 Avg),對 2*2 的範圍 stride=2, 2 取最大值:
https://ithelp.ithome.com.tw/upload/images/20220524/20138527spWd2xulU6.png

重要參數

tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')
  1. pool_size:池化視窗的大小。常設 2*2。
  2. strides:滑動步長,計算滑動視窗時移動的格數。默認 (1, 1)。
  3. padding:補 0 策略,卷積層取 kernel_size 滑動視窗時,若超越邊界,是選擇
    放棄這個 output 點(valid)、一律補零(same)。

C. Fully Connected Layer 全連接層

即是將結果平坦化後連接,概念就像是把 2D 的圖片拍扁變成 1D 的數列。
https://ithelp.ithome.com.tw/upload/images/20220524/20138527vAv9eoTAa5.png

4-3. 實作

講完了概念,接著我們用 Tensorflow 官網的範例來演練一下。

官網的程式碼如下:

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)

https://ithelp.ithome.com.tw/upload/images/20220530/20138527ta79gEBVkk.png

原本的 mnist 的資料已經很乾淨,因此實作的準確度本身就已相當高。
接著我們試著用 CNN 的方式來撰寫:

import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0

不同的是,這次我們在建模的時候加入 CNN:

首先,要把 x 增加一維在最後面,因為 CNN 要多一個表示顏色的維度

x_train = x_train.reshape(*x_train.shape, 1)
x_test = x_test.reshape(*x_test.shape, 1)

x_train.shape, x_test.shape

>>  ((60000, 28, 28, 1), (10000, 28, 28, 1))

建模

model_cnn = tf.keras.Sequential([
    tf.keras.Input(shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation="softmax"),
])

優化器設定:與前面同樣使用 Adam、交叉熵做損失函數,關鍵指標則看準確率。

model_cnn.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

history = model_cnn.fit(x_train, y_train, epochs=5, validation_split=0.2)

https://ithelp.ithome.com.tw/upload/images/20220530/201385276OwKvs1v5I.png

如此一來,即用 CNN 的方式做出一個更準確的模型了!


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言