以 Keras 設計簡單 CNN模型
針對圖像特性的共享參數
要處理問題為如下圖 mnist 一個手寫圖片, 輸入其中一個圖案, 模型要猜 (預測或者推理)是 0, 1, 2, ...,9 中一個數字.
我們打算利用剛理解的深度學習模型來解.
前篇我們已經取得 (x_train, y_train) 訓練集, 與 (x_test, y_test) 驗證集. 同時也進行簡易的預處理. 我們要設計一個模型能準確預測.
在還沒有洞察圖像的特性前, 我們因應深度模型最快的方法就是把本來圖像是三維度的型態拉直成為一維數據, 直接餵入一個最簡單的深度學習分類模型, 雖然這樣忽略了圖像的許多特性 (圖像的每個像素是有點關係的), 但很可能也比其他手法好上一點, 在驗證集輕易就達到 92% 準確度.
上面兩層的神經網路程式碼的產生的網路架構如下:
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten_1 (Flatten) (None, 784) 0
dropout_2 (Dropout) (None, 784) 0
dense_2 (Dense) (None, 1024) 803840
dropout_3 (Dropout) (None, 1024) 0
dense_3 (Dense) (None, 10) 10250
=================================================================
Total params: 814,090
Trainable params: 814,090
Non-trainable params: 0
_________________________________________________________________
開頭我們就用 Flaten 指令讓輸入原來圖像是 28x28 的矩陣變成有 784的 Vector, 後邊緊接一個1024個神經元的 Dense 層, 這是一個全連接層產生了 (784+1)*1024 個參數, (784+1) 裡邊的 1 是 bias, 參數是要由神經網路在訓練過程中找到較佳的值以達到較優的預測 (較低的預測錯誤). 再加上後邊緊接輸出層, 這一層也有 (1024+1)*10 個參數, 這樣就有高達 81.4萬的參數量, 與訓練的圖像數據量相比, 參數量相當大的模型, 我們加了 dropout 以防 overfitting.
這麼簡單樸素的模型其準確也可以達 92%, 深度模型相比淺層模型可以逼近更符合現實的函數.
不過光用最樸素的深度模型其缺點也很明顯:
參數數量頗大, 要思考是否有可能降低參數又不太影響性能的設計
沒考慮到圖像的某點素與其周遭其他點素是比較有相關; 而遠離其周遭的點素基本上比較沒關係這特性
沒有應用到任何光學上的任何工具, 例如利用濾鏡凸顯圖像的特徵
早在 199x年 LeCunn 於 Gradient-Based Learning Applied to Document Recognition 就提出捲積層網路, 網路要學到許多的 Filter, 每個 Filter針對該類圖像的特徵都能將圖像進行捲積 (類似對涂進行濾波處理).
我們網路上任意搜尋一張 CNN 架構圖, 他的架構幾乎是 LeNet, 再嘗試以 keras 實作看看, 驗證 keras 是否有極低門檻:
圖自: Deep Learning model-based Multimedia forgery detection
其中 n1=32; n2=64; n3=100. 這些都是超參數, 而 conv_1 或者 conv_2 裡的 (5x5) kernel 也是超參數, 可以多嘗試一下諸如: (3x3), (7x7) 等等; 而且conv_1 與 conv_2 不需要一樣. 那是否可以多幾個捲積層 conv_3, conv_4, conv_5 等等呢? 這也是需要依照數據來設計的, 這也是超參數. 還有 Pooling 層是用來將圖像壓縮的, 如果要縮小尺寸為一半那選擇 (2x2); 要成為 1/3 那選擇(3x3) 這也是超參數, 可以選擇 MaxPooling 或者AveragePooling, 這也是超參數, 也需要選擇的.
經過了幾個捲積層後, 最後輸出為 (4, 4, 64) 形狀的 Tensor, 我們無法直接與後面的神經元相接, 我們用 Flatten 拉開成一排, 我們又接了一層 n3=100 Fully Connected 層, 因為會產生密密麻麻的連接, 在 Keras 取名為 Dense 層. 要不要有 Fully Connected 層? 要幾層? 每層要多少神經元都是超參數. 最後輸出為 0,1,...,9 的預測值. 我們將激活函數設定為 softmax 讓所有輸出神經元加總為1, 且每個神經元值介於0-1 之間, 這樣可以模擬類似機率分布, 讓我們判斷神經對預測值的 '信心'.
與當今SOTA網路百層以上的網路比, 這是一個極為陽春精簡的網路, 但是你就可以發現有太多的超參數要去嘗試錯誤. 超參數是要自己依照數據來設定的, 經常需要大量的嘗試錯誤方能確認. 針對這個問題發展出 NAS, Neural Architecture Search, 的技術. 我們在其他地方會用到.
我們依照上面模型的設計, 用 Keras 程式碼如下:
產生的網路架構如下:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 24, 24, 32) 832
pool1 (MaxPooling2D) (None, 12, 12, 32) 0
conv2d_1 (Conv2D) (None, 8, 8, 64) 51264
pool2 (MaxPooling2D) (None, 4, 4, 64) 0
flatten (Flatten) (None, 1024) 0
dropout (Dropout) (None, 1024) 0
dense (Dense) (None, 100) 102500
dropout_1 (Dropout) (None, 100) 0
dense_1 (Dense) (None, 10) 1010
=================================================================
Total params: 155,606
Trainable params: 155,606
Non-trainable params: 0
_________________________________________________________________
不到 15.6 萬的參數量, 簡易的CNN模型其準確可達 99.3%, 遠高於用了高達 81.4萬的參數量的一般深度網路 92%.
與上面簡易深度模型最大的差異在於引進捲積層, 比較重要的是捲積 Kernel 的引入, 有些人會命名為 Filter, 濾鏡. CNN 的架構其實是要讓神經網路在優化的過程中, 找到多組濾鏡, 這些濾鏡可以幫忙把圖像的特徵 (例如: 線條, 物件條紋, 物件外框...)給凸顯出來. 這些濾鏡取代了全連接層的大量參數.