iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
1
AI & Data

輕鬆掌握 Keras 及相關應用系列 第 11

Day 11:卷積神經網路(CNN) 剖析與視覺化

  • 分享至 

  • xImage
  •  

前言

從這一篇開始,我們要開始介紹一些演算法及其應用,了解 Keras 的進階用法。首先,介紹【卷積神經網路】(Convolutional Neural Networks work, CNN),以下簡稱CNN。

CNN 的原理在網路上已經有太多的說明,筆者就不再從頭介紹其原理,有興趣的讀者可以參考筆者之前的系列文章[1][2][3],這次會著重在程式的解說,包括:

  1. 完整程式的實作。
  2. 卷積(Convolution)運算。
  3. 卷積(Convolution)後的影像視覺化。

CNN 的特點

【Day 03:撰寫第一支完整的 Keras 程式】中,我們使用像素(pixel)作為辨識影像的特徵變數,但是人類應該不會以這種一點一點的比對來辨識影像,仔細觀察,以線條或輪廓辨識應該比較合理。CNN以卷積計算找出各種線條特徵,再將它們輸入至完全連接層(Dense)進行影像辨識。

CNN 一般的結構如下:

  1. 先透過卷積(Convolution),由圖片中萃取線條特徵。
  2. 再透過池化層(Pooling),採樣保留最大值(特徵)。
  3. 經過多次卷積/池化後,得到抽象化的特徵,壓扁為一維向量,作為完全連接層(Dense)的輸入。
  4. 經完全連接層分類,進行影像辨識。

https://ithelp.ithome.com.tw/upload/images/20200910/20001976mvGiGJxLdI.png
圖一. 卷積神經網路(CNN)結構,圖片來源:CS231n Convolutional Neural Networks Lecture-5

https://ithelp.ithome.com.tw/upload/images/20200911/20001976hZpvjwilnp.png
圖二. 卷積神經網路(CNN)處理

實作

同樣辨識手寫阿拉伯數字,模型修改如下:

# 建立模型
model = tf.keras.Sequential(
    [
        tf.keras.Input(shape=input_shape),
        layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
        layers.MaxPooling2D(pool_size=(2, 2)),
        layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
        layers.MaxPooling2D(pool_size=(2, 2)),
        layers.Flatten(),
        layers.Dropout(0.5),
        layers.Dense(10, activation="softmax"),
    ]
)

函數說明如下:

  1. Conv2D:2維的卷積層,32代表找出32個特徵(Feature Map),kernel_size=(3, 3)為 3x3大小的卷積核或濾波器(Filter)。
  2. MaxPooling2D:2維的池化層,pool_size=(2, 2)為 2x2大小的池,計算後4個值取最大的保留下來。

除了輸入,其他處理程序幾乎一樣,CNN是允許彩色影像輸入,故輸入影像須加一個維度 -- 色彩。預測時,記得樣本也要加一維。

# 加一個維度,MNIST是單色影像,故最後一維是 1,shape = (28, 28, 1)
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)

範例檔案名稱為11_01_CNN_MNIST.ipynb,執行結果的準確率確實有提高至98.86%。

卷積(Convolution)的特徵萃取

利用不同的卷積核(kernel)作卷積運算,會有不同的效果,例如,卷積核如下,將像素以週圍像素的平均值取代,會造成模糊化的效果,目的是將去躁(Denose),將雜訊去除。
https://ithelp.ithome.com.tw/upload/images/20200911/20001976QGCjU8i8zf.png
圖三. 模糊化的卷積核(kernel)

以下使用 OpenCV 的 cv2.filter2D 函數實驗卷積運算,若未安裝 OpenCV 套件,執行下列指令:

pip install opencv-python

程式如下:

# 使用cv2.filter2D進行convolution
image_name = './0_images/conv_org.png'
image = cv2.imread(image_name)
smallBlur = np.ones((7, 7), dtype="float") * (1.0 / (7 * 7))
result = cv2.filter2D(image, -1, smallBlur)

範例檔案名稱為11_02_Convolutions.ipynb,可以作出多種效果,包括模糊化(Blur)、銳化(Sharpen)、邊緣偵測(Edge detection)...等。

卷積(Convolution)的視覺化

可以將每次卷積(Convolution)後的影像視覺化(Visualization),範例檔案名稱為11_03_CNN_Visualization.ipynb,結果如下,可以看出最後一列有些圖片可以把鳥的輪廓顯現出來。

https://ithelp.ithome.com.tw/upload/images/20200911/20001976x8HjLDrv6Z.png
圖四. 各卷積層處理結果

剖析

測試及閱讀文件的心得如下:

  1. 卷積(Convolution)使用的卷積核(kernel)並不是固定的,他們的矩陣值是經由訓練得到的最佳解。
  2. 抽象化(Abstraction):透過卷積使影像抽象化,可逐漸把輪廓顯現出來,但不是每個卷積都有效。

結論

希望透過以上的程式,能對CNN更深的認識,一些細節就請大家參閱筆者之前的文章了。

以上我們利用CNN辨識手寫阿拉伯數字,其實有幾個缺點:

  1. MNIST 的訓練資料與滑鼠撰寫的樣式有所差異,我猜 MNIST 的資料收集應該是請受測者寫在紙上,再掃描存檔,因此有灰階及鋸齒狀,所以,如果要實際應用,應該自己收集訓練資料。
  2. 要收集上萬筆受測者的資料,可能不太容易,另外,有些書寫可能字體歪斜、偏一邊、或字體大小不同,我們可以透過【資料增補】(Data Augmentation)方式自動產生這些資料。
  3. 可以利用預訓模型(Pre-trained Models),套用大公司訓練好的模型,使辨識更精準。

我們在下篇就來效能調校一下。

本篇範例包括11_01_CNN_MNIST.ipynb、11_02_Convolutions.ipynb、11_03_CNN_Visualization.ipynb,可自【這裡】下載。


上一篇
Day 10:運用自訂Callback 追蹤訓練過程( Keras )
下一篇
Day 12:影像資料增補(Data Augmentation)
系列文
輕鬆掌握 Keras 及相關應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言