iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
AI & Data

30 天在 Colab 嘗試的 30 個影像分類訓練實驗系列 第 14

【14】如果不做圖片標準化(Normalization)會怎麼樣

Colab連結

圖片標準化 Image Normalization 不做可以嗎?小實驗實測差別

一般我們在處理大部分的機器學習問題時,我們都會將輸入的資料特徵做 Normalization,將範圍縮小到0的附近後在進行訓練,而這個再丟給模型推論之前所做動作稱之為資料預處理,而預處理的方式又有很多種,像是減去平均值除上標準差等方式。

通常大家在學習上聽到的預處理是為了讓模型收斂速度加快,而我們今天就來做個小實驗比較看看這兩者的差別。

實驗一:有做 Normalization

def normalize_img(image, label):
  image = tf.cast(image, tf.float32)
  image = tf.image.resize(image, (224,224))
  return image / 255., label.  # Normalization 到 [0,+1]

ds_train = train_split.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(SHUFFLE_SIZE)
ds_train = ds_train.batch(BATCH_SIZE)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)

ds_test = test_split.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(BATCH_SIZE)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)

base = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
net = tf.keras.layers.GlobalAveragePooling2D()(base.output)
net = tf.keras.layers.Dense(NUM_OF_CLASS)(net)

model = tf.keras.Model(inputs=[base.input], outputs=[net])

model.compile(
    optimizer=tf.keras.optimizers.SGD(LR),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history = model.fit(
    ds_train,
    epochs=EPOCHS,
    validation_data=ds_test,
    verbose=True)

產出:

loss: 3.6706e-04 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.4833 - val_sparse_categorical_accuracy: 0.8647

https://ithelp.ithome.com.tw/upload/images/20210928/201072990i5vXlTkND.png

loss值落在 0.4833,準確度落在86.5%

實驗二:不做 Normalization,使用原圖片輸入數值範圍 [0, 255]。

def normalize_img(image, label):
  image = tf.cast(image, tf.float32)
  image = tf.image.resize(image, (224,224))
  return image, label # 不除255.

ds_train = train_split.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(SHUFFLE_SIZE)
ds_train = ds_train.batch(BATCH_SIZE)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)

ds_test = test_split.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(BATCH_SIZE)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)

base = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
net = tf.keras.layers.GlobalAveragePooling2D()(base.output)
net = tf.keras.layers.Dense(NUM_OF_CLASS)(net)

model = tf.keras.Model(inputs=[base.input], outputs=[net])

model.compile(
    optimizer=tf.keras.optimizers.SGD(LR),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

start = timeit.default_timer()
history = model.fit(
    ds_train,
    epochs=EPOCHS,
    validation_data=ds_test,
    verbose=True)

產出:

loss: 3.7623e-04 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.4478 - val_sparse_categorical_accuracy: 0.8873

https://ithelp.ithome.com.tw/upload/images/20210928/20107299HaXLbrRrXI.png

結果有些出乎我意料,loss 值0.4478,準確度88.7%,整體結果比實驗一好,而且實驗一在第50個 epoch 達到80%準確度,但實驗二更快,在第36個 epoch 就到達了80%,實驗一並沒有收斂比較快。

雖然這次實驗結果是不做 Normalization 的成績好一些,但我還是不太建議略過 Normalization ,之所以會有這樣的結果,我猜想可能是我的模型用了 Batch Normalization 來解決數值的差異,如果數值的差異很大的話,其實蠻容易訓練到一半時,loss變成nan 的狀況(gradient exploding),有關這種狀況,後面我會再獨立介紹。


上一篇
【13】模型套不套用資料增強 (Data Augmentation) 的比較實驗
下一篇
【15】圖片標準化 [0,1] 與 [-1,+1] 的差別實驗
系列文
30 天在 Colab 嘗試的 30 個影像分類訓練實驗31

尚未有邦友留言

立即登入留言