iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
AI Engineering

從 Pixel 到 AI:30 天影像辨識入門之路系列 第 15 篇

Day15 第一次完整訓練 CNN!建立我們的 Baseline Model

  • 分享至 

  • xImage
  •  

前幾天我們把 CNN 拆成不同的部分來認識,在 Day12 我們知道 CNN 和 Dense Neural Network 的差別,Day13 認識了 Convolution、Kernel 與 Feature Map,Day14 則介紹了 Pooling 如何縮小 Feature Map

今天終於要把前面學到的東西全部組合起來,建立我們第一個完整的 CNN 圖片分類模型!

這次的目標不是馬上做出最好的模型,而是先建立一個簡單的 Baseline Model(基準模型)
之後我們調整模型架構、Batch Size、Learning Rate 或其他方法時,就可以和今天的結果比較,看看模型到底有沒有真的進步


一、先回顧 Day11 的 Dense Model

Day11 我們建立的模型大概是:
https://ithelp.ithome.com.tw/upload/images/20260925/20169251uxBoe1lMqu.png
最大的問題就是圖片一進入模型,很快就被 Flatten 成一串數字

今天我們改成 CNN:
https://ithelp.ithome.com.tw/upload/images/20260925/20169251P2IgDQc8Ee.png
最大的差別就是:在 Flatten 之前,先透過 Convolution 和 Pooling 進行 Feature Extraction


二、建立第一個 CNN

我們繼續使用前面處理好的:

  • X_train、y_train
  • X_val、y_val
  • X_test、y_test
    圖片大小一樣維持 64 × 64 × 3,接著建立模型
import tensorflow as tf

model = tf.keras.Sequential([

    # 輸入圖片:64 × 64,3 代表 RGB 三個 Channel
    tf.keras.layers.Input(shape=(64, 64, 3)),

    # 第一層 Convolution
    # 使用 32 個 3 × 3 Filter 學習圖片的局部特徵
    tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", padding="same"),

    # 將 Feature Map 的空間尺寸縮小
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),

    # 第二層 Convolution
    # 使用 64 個 Filter 學習更多特徵
    tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu", padding="same"),

    # 再次縮小 Feature Map
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),

    # 將 Feature Map 攤平成一維
    tf.keras.layers.Flatten(),

    # Dense Layer
    tf.keras.layers.Dense(128, activation="relu"),

    # HAM10000 有 7 個類別
    tf.keras.layers.Dense(7, activation="softmax")
])

三、模型裡到底發生了什麼?

這裡我加入了 padding="same",它可以讓 Convolution 前後的空間尺寸(Height、Width)維持相同,所以第一個 Conv2D 從 64 × 64 × 3 到 64 × 64 × 32,圖片的寬和高仍然是 64 × 64,但最後變成 32,是因為我們使用了 filters=32,也就是產生 32 個輸出 Feature Map


四、Pooling 開始把 Feature Map 變小

接著

tf.keras.layers.MaxPooling2D(pool_size=(2, 2))

就會把 64 × 64 × 32 縮小成 32 × 32 × 32 ,接著第二個 Conv2D 使用 filters=64,因此變成 32 × 32 × 64,再次經過 MaxPooling 變成 16 × 16 × 64,這邊可以發現一個很有趣的變化:

  • 圖片的 Width、Height:64 × 64⮕32 × 32⮕16 × 16
  • Feature Map 數量:3⮕32⮕64

空間尺寸逐漸縮小,但是 Feature Map 的數量增加,模型就是透過這些 Layer,逐步建立更豐富的特徵表示


五、CNN 最後還是需要 Flatten?

前面一直說 Dense Model 的問題是 Flatten,那為什麼 CNN 最後還是用了:

tf.keras.layers.Flatten()

差別在於 Flatten 的時間點不同

Day11 是:原始圖片直接 Flatten⮕Dense
今天則是經過了幾個Conv2D與Pooling再Flatten

CNN 並不是完全不能使用 Flatten,而是先透過 Convolution 和 Pooling 進行 Feature Extraction,最後再把提取出的 Feature Map 攤平成一維,交給 Dense Layer 進行分類


六、看看模型長什麼樣子

建立完模型後,可以使用model.summary()實際看到每一層到底有多少需要學習的參數
https://ithelp.ithome.com.tw/upload/images/20260925/20169251r0Y3BXTQ4c.png


七、Compile

模型建立完成之後,和 Day11 一樣需要 Compile,這次我們先維持和 Dense Model 類似的設定,因為今天的目的,是先建立 CNN Baseline,而不是一次改很多東西,如果一次同時改模型、Optimizer、Learning Rate、Batch Size 等設定,最後反而很難知道到底是哪一個改變造成結果不同


八、開始訓練 CNN、畫出 Accuracy

從結果可以看到,隨著 Epoch 增加,Training Accuracy 持續上升,從一開始約 67.5%,最後提高到約 82.7%

但是 Validation Accuracy 並沒有跟著持續上升,Validation Accuracy 在前幾個 Epoch 上升後,大約在第 5 個 Epoch 達到 72.5% 左右,之後反而開始出現下降與波動
https://ithelp.ithome.com.tw/upload/images/20260925/201692512gKBQ5qIyv.png

訓練完成後,最後使用先前保留下來的 Test Data 評估模型,這次得到:

Test Loss: 0.7663570046424866
Test Accuracy: 0.7349397540092468

換算成百分比後,這個 CNN Baseline Model 在 Test Data 上的 Accuracy 約為 73.49%,也就是說,在目前的 Test Data 中,模型整體大約有 73.49% 的圖片分類正確

不過,73.49% 就代表模型表現得很好嗎?

這時候就要回想到前面探索 HAM10000 時發現的問題:這個 Dataset 存在明顯的 Class Imbalance,其中 nv 的圖片數量遠高於其他類別

因此,只看整體 Accuracy 還不能知道模型對每一個病灶類別的表現,例如模型可能很會判斷 nv,但對數量較少的 df、vasc 等類別表現較差,最後仍然可以得到看起來不錯的 Accuracy


上一篇
Day14 Pooling 為什麼要把圖片越變越小?
系列文
從 Pixel 到 AI:30 天影像辨識入門之路 共 15 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言