なんとなく 255 で割っていませんか?
画像をKerasに入力するとき、x / 255.0 で正規化するのが"お約束"になっていませんか?
でも BatchNormalization や LayerNormalization を使う方法と、精度や収束速度はどう違うのでしょうか。
今回はGoogle ColabとCIFAR-10を使い、4種類の正規化方法を完全同一条件で比較しました。
- 前処理の正規化(/255)とモデル内正規化(BN・LN)の根本的な違い
- CIFAR-10での精度・収束速度・学習時間の実験結果
- どの正規化方法をいつ選ぶべきかの判断基準
当ブログのBatchNormalizationあり/なし比較・BN×Dropout比較では「BatchNormを過学習対策の層」として扱いました。本記事では 「入力画像をどう前処理するか」 という観点に絞り、BatchNormを 前処理の代替 として使う場合の効果を検証します。
4つの正規化方法の違い
| パターン | 方法 | 適用タイミング | 学習パラメータ |
|---|---|---|---|
| A:/255(手動) | NumPyで x / 255.0 |
学習前に一括処理 | なし |
| B:Rescaling層 | Rescaling(1./255) をモデル先頭に追加 |
モデル内で自動処理 | なし |
| C:BatchNormalization | BatchNormalization() をモデル先頭に追加 |
ミニバッチ単位で動的に正規化 | あり(γ・β) |
| D:LayerNormalization | LayerNormalization() をモデル先頭に追加 |
サンプル単位で動的に正規化 | あり(γ・β) |
前処理の正規化 vs モデル内正規化の根本的な違い
A・B(固定スケーリング)は、全ピクセルを一律に [0, 1] に収める固定変換です。データセット全体の統計を使わず、「最大値が255」という前提で割り算するだけです。
C(BatchNorm)はミニバッチ内の平均・分散で正規化するため、バッチごとに異なる変換が適用されます。さらに学習可能なスケール(γ)とシフト(β)パラメータを持ちます。
D(LayerNorm)はサンプル1枚ごとにチャンネル軸で正規化します。バッチサイズに依存しないため、バッチサイズが小さい場合でも安定します。
/255 と Rescaling(1./255) は数値的に完全に同等です。違いは「前処理をコード側でやるか、モデル内でやるか」だけ。B はモデルに前処理を内包できるため、推論時に別途正規化コードを書く必要がなくなります。
実験コード
使用環境はGoogle Colab(GPU:T4)、データセットはCIFAR-10です。正規化方法以外の条件はすべて同一にし、正規化の影響だけを取り出します。
環境準備(最初に一度だけ実行)
# ── 環境準備(最初に一度だけ実行)──────────────────────
!apt-get -y install fonts-ipafont-gothic
!rm -rf /root/.cache/matplotlib
!pip install -q japanize_matplotlib
print("環境準備完了")
実行結果をクリックして内容を開く
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
fonts-ipafont-mincho
The following NEW packages will be installed:
fonts-ipafont-gothic fonts-ipafont-mincho
0 upgraded, 2 newly installed, 0 to remove and 42 not upgraded.
Need to get 8,237 kB of archives.
After this operation, 28.7 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-ipafont-gothic all 00303-21ubuntu1 [3,513 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-ipafont-mincho all 00303-21ubuntu1 [4,724 kB]
Fetched 8,237 kB in 0s (30.7 MB/s)
Selecting previously unselected package fonts-ipafont-gothic.
(Reading database ... 122354 files and directories currently installed.)
Preparing to unpack .../fonts-ipafont-gothic_00303-21ubuntu1_all.deb ...
Unpacking fonts-ipafont-gothic (00303-21ubuntu1) ...
Selecting previously unselected package fonts-ipafont-mincho.
Preparing to unpack .../fonts-ipafont-mincho_00303-21ubuntu1_all.deb ...
Unpacking fonts-ipafont-mincho (00303-21ubuntu1) ...
Setting up fonts-ipafont-mincho (00303-21ubuntu1) ...
update-alternatives: using /usr/share/fonts/opentype/ipafont-mincho/ipam.ttf to provide /usr/share/fonts/truetype/fonts-japanese-mincho.ttf (fonts-japanese-mincho.ttf) in auto mode
Setting up fonts-ipafont-gothic (00303-21ubuntu1) ...
update-alternatives: using /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf to provide /usr/share/fonts/truetype/fonts-japanese-gothic.ttf (fonts-japanese-gothic.ttf) in auto mode
Processing triggers for fontconfig (2.13.1-4.2ubuntu5) ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.1/4.1 MB 57.5 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
Building wheel for japanize_matplotlib (setup.py) ... done
環境準備完了
import・データ準備
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import time
# ── データ準備 ──────────────────────────────────────────
(x_train_raw, y_train), (x_test_raw, y_test) = keras.datasets.cifar10.load_data()
# A・B用:/255 で正規化済みデータ
x_train_norm = x_train_raw.astype('float32') / 255.0
x_test_norm = x_test_raw.astype('float32') / 255.0
# C・D用:正規化なし(uint8のまま float32 に変換のみ)
x_train_raw_f = x_train_raw.astype('float32')
x_test_raw_f = x_test_raw.astype('float32')
NUM_CLASSES = 10
print("データ準備完了")
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 614s 4us/step データ準備完了
モデル構築関数
def build_model(norm_type, name):
"""
norm_type:
'manual' → 入力はすでに /255 済み。正規化層なし
'rescale' → モデル先頭に Rescaling(1./255) を追加
'bn' → モデル先頭に BatchNormalization を追加
'ln' → モデル先頭に LayerNormalization を追加
"""
norm_layers = {
'manual': [],
'rescale': [keras.layers.Rescaling(1. / 255)],
'bn': [keras.layers.BatchNormalization()],
'ln': [keras.layers.LayerNormalization()],
}
layers = [keras.layers.Input(shape=(32, 32, 3))]
layers += norm_layers[norm_type]
layers += [
keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
keras.layers.MaxPooling2D((2, 2)),
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(NUM_CLASSES, activation='softmax'),
]
return keras.Sequential(layers, name=name)
def compile_and_fit(model, x_tr, y_tr):
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
start = time.time()
history = model.fit(x_tr, y_tr, epochs=30, batch_size=64,
validation_split=0.2, verbose=1)
return history, time.time() - start
4パターンの学習実行
# (label, norm_type, 使用するx_train, 使用するx_test)
configs = [
('A_manual_255', 'manual', x_train_norm, x_test_norm),
('B_Rescaling', 'rescale', x_train_raw_f, x_test_raw_f),
('C_BatchNorm', 'bn', x_train_raw_f, x_test_raw_f),
('D_LayerNorm', 'ln', x_train_raw_f, x_test_raw_f),
]
histories, times, scores = {}, {}, {}
for label, norm_type, x_tr, x_te in configs:
keras.backend.clear_session()
print(f"\n=== {label} ===")
model = build_model(norm_type, label)
print(model.summary())
h, t = compile_and_fit(model, x_tr, y_tr=y_train)
s = model.evaluate(x_te, y_test, verbose=0)
histories[label] = h
times[label] = t
scores[label] = s
print(f"学習時間:{t:.1f}秒 test_accuracy:{s[1]:.4f}")
実行結果をクリックして内容を開く
=== A_manual_255 === Model: "A_manual_255" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ conv2d (Conv2D) │ (None, 32, 32, 64) │ 1,792 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 16, 16, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 16, 16, 128) │ 73,856 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 8, 8, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ global_average_pooling2d │ (None, 128) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 128) │ 16,512 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 10) │ 1,290 │ └─────────────────────────────────┴────────────────────────┴───────────────┘ Total params: 93,450 (365.04 KB) Trainable params: 93,450 (365.04 KB) Non-trainable params: 0 (0.00 B) None Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 11s 9ms/step - accuracy: 0.2636 - loss: 1.9338 - val_accuracy: 0.3596 - val_loss: 1.7197 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3648 - loss: 1.6899 - val_accuracy: 0.3989 - val_loss: 1.6127 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4119 - loss: 1.5860 - val_accuracy: 0.4346 - val_loss: 1.5430 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4432 - loss: 1.5071 - val_accuracy: 0.4757 - val_loss: 1.4402 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4653 - loss: 1.4490 - val_accuracy: 0.4863 - val_loss: 1.3937 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4877 - loss: 1.3891 - val_accuracy: 0.5150 - val_loss: 1.3380 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5064 - loss: 1.3487 - val_accuracy: 0.5160 - val_loss: 1.3450 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5210 - loss: 1.3091 - val_accuracy: 0.5006 - val_loss: 1.3146 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5354 - loss: 1.2715 - val_accuracy: 0.5455 - val_loss: 1.2366 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5416 - loss: 1.2481 - val_accuracy: 0.5518 - val_loss: 1.2240 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5550 - loss: 1.2151 - val_accuracy: 0.5503 - val_loss: 1.2041 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5646 - loss: 1.1924 - val_accuracy: 0.5734 - val_loss: 1.1558 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5731 - loss: 1.1759 - val_accuracy: 0.5737 - val_loss: 1.1829 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5850 - loss: 1.1479 - val_accuracy: 0.5774 - val_loss: 1.1540 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5907 - loss: 1.1269 - val_accuracy: 0.5967 - val_loss: 1.0955 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5972 - loss: 1.1116 - val_accuracy: 0.6029 - val_loss: 1.0892 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6053 - loss: 1.0887 - val_accuracy: 0.6113 - val_loss: 1.0976 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6135 - loss: 1.0681 - val_accuracy: 0.6070 - val_loss: 1.0783 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6170 - loss: 1.0627 - val_accuracy: 0.6160 - val_loss: 1.0541 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6230 - loss: 1.0404 - val_accuracy: 0.6299 - val_loss: 1.0246 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6308 - loss: 1.0198 - val_accuracy: 0.6166 - val_loss: 1.0492 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6384 - loss: 1.0072 - val_accuracy: 0.6154 - val_loss: 1.0414 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6413 - loss: 0.9957 - val_accuracy: 0.6440 - val_loss: 0.9915 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6495 - loss: 0.9717 - val_accuracy: 0.6412 - val_loss: 0.9981 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6517 - loss: 0.9749 - val_accuracy: 0.6579 - val_loss: 0.9609 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6590 - loss: 0.9496 - val_accuracy: 0.6583 - val_loss: 0.9537 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6585 - loss: 0.9445 - val_accuracy: 0.6553 - val_loss: 0.9702 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6646 - loss: 0.9341 - val_accuracy: 0.6595 - val_loss: 0.9587 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6697 - loss: 0.9168 - val_accuracy: 0.6646 - val_loss: 0.9404 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6745 - loss: 0.9082 - val_accuracy: 0.6613 - val_loss: 0.9487 学習時間:129.7秒 test_accuracy:0.6565 === B_Rescaling === Model: "B_Rescaling" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ rescaling (Rescaling) │ (None, 32, 32, 3) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d (Conv2D) │ (None, 32, 32, 64) │ 1,792 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 16, 16, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 16, 16, 128) │ 73,856 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 8, 8, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ global_average_pooling2d │ (None, 128) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 128) │ 16,512 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 10) │ 1,290 │ └─────────────────────────────────┴────────────────────────┴───────────────┘ Total params: 93,450 (365.04 KB) Trainable params: 93,450 (365.04 KB) Non-trainable params: 0 (0.00 B) None Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2680 - loss: 1.9157 - val_accuracy: 0.3432 - val_loss: 1.7222 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.3623 - loss: 1.6897 - val_accuracy: 0.3933 - val_loss: 1.6190 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4137 - loss: 1.5806 - val_accuracy: 0.4474 - val_loss: 1.5069 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4488 - loss: 1.4948 - val_accuracy: 0.4838 - val_loss: 1.4155 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4797 - loss: 1.4199 - val_accuracy: 0.5009 - val_loss: 1.3662 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4982 - loss: 1.3727 - val_accuracy: 0.5151 - val_loss: 1.3196 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5143 - loss: 1.3319 - val_accuracy: 0.5237 - val_loss: 1.2990 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5298 - loss: 1.2932 - val_accuracy: 0.5222 - val_loss: 1.2999 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5389 - loss: 1.2602 - val_accuracy: 0.5562 - val_loss: 1.2121 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5494 - loss: 1.2367 - val_accuracy: 0.5556 - val_loss: 1.2072 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5643 - loss: 1.2020 - val_accuracy: 0.5639 - val_loss: 1.1953 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5695 - loss: 1.1849 - val_accuracy: 0.5764 - val_loss: 1.1516 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5827 - loss: 1.1518 - val_accuracy: 0.6050 - val_loss: 1.1044 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5875 - loss: 1.1368 - val_accuracy: 0.5964 - val_loss: 1.1033 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5979 - loss: 1.1177 - val_accuracy: 0.6078 - val_loss: 1.0827 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6043 - loss: 1.0926 - val_accuracy: 0.6011 - val_loss: 1.0995 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6094 - loss: 1.0730 - val_accuracy: 0.6224 - val_loss: 1.0437 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6180 - loss: 1.0549 - val_accuracy: 0.6189 - val_loss: 1.0354 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6228 - loss: 1.0414 - val_accuracy: 0.6237 - val_loss: 1.0447 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6299 - loss: 1.0194 - val_accuracy: 0.6400 - val_loss: 1.0036 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6362 - loss: 1.0105 - val_accuracy: 0.6333 - val_loss: 1.0235 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6420 - loss: 0.9929 - val_accuracy: 0.6326 - val_loss: 1.0211 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6499 - loss: 0.9754 - val_accuracy: 0.6405 - val_loss: 0.9904 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6524 - loss: 0.9618 - val_accuracy: 0.6443 - val_loss: 0.9703 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6574 - loss: 0.9491 - val_accuracy: 0.6548 - val_loss: 0.9662 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6611 - loss: 0.9441 - val_accuracy: 0.6627 - val_loss: 0.9289 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6679 - loss: 0.9271 - val_accuracy: 0.6691 - val_loss: 0.9264 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6684 - loss: 0.9187 - val_accuracy: 0.6480 - val_loss: 0.9763 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6724 - loss: 0.9083 - val_accuracy: 0.6637 - val_loss: 0.9385 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6769 - loss: 0.8975 - val_accuracy: 0.6575 - val_loss: 0.9488 学習時間:125.7秒 test_accuracy:0.6549 === C_BatchNorm === Model: "C_BatchNorm" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ batch_normalization │ (None, 32, 32, 3) │ 12 │ │ (BatchNormalization) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d (Conv2D) │ (None, 32, 32, 64) │ 1,792 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 16, 16, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 16, 16, 128) │ 73,856 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 8, 8, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ global_average_pooling2d │ (None, 128) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 128) │ 16,512 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 10) │ 1,290 │ └─────────────────────────────────┴────────────────────────┴───────────────┘ Total params: 93,462 (365.09 KB) Trainable params: 93,456 (365.06 KB) Non-trainable params: 6 (24.00 B) None Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 10ms/step - accuracy: 0.3212 - loss: 1.8223 - val_accuracy: 0.4143 - val_loss: 1.5765 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4467 - loss: 1.5224 - val_accuracy: 0.5011 - val_loss: 1.3863 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5045 - loss: 1.3707 - val_accuracy: 0.5343 - val_loss: 1.2914 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5408 - loss: 1.2768 - val_accuracy: 0.5515 - val_loss: 1.2419 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5654 - loss: 1.2150 - val_accuracy: 0.5794 - val_loss: 1.1609 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5857 - loss: 1.1542 - val_accuracy: 0.5883 - val_loss: 1.1476 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.6015 - loss: 1.1135 - val_accuracy: 0.6031 - val_loss: 1.0899 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6175 - loss: 1.0739 - val_accuracy: 0.6152 - val_loss: 1.0542 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6264 - loss: 1.0421 - val_accuracy: 0.6308 - val_loss: 1.0145 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6344 - loss: 1.0225 - val_accuracy: 0.6248 - val_loss: 1.0362 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6463 - loss: 0.9921 - val_accuracy: 0.6498 - val_loss: 0.9838 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6516 - loss: 0.9725 - val_accuracy: 0.6444 - val_loss: 0.9863 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.6594 - loss: 0.9540 - val_accuracy: 0.6530 - val_loss: 0.9556 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6650 - loss: 0.9338 - val_accuracy: 0.6662 - val_loss: 0.9300 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6720 - loss: 0.9132 - val_accuracy: 0.6725 - val_loss: 0.9105 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6791 - loss: 0.8963 - val_accuracy: 0.6694 - val_loss: 0.9147 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6836 - loss: 0.8848 - val_accuracy: 0.6847 - val_loss: 0.8788 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6918 - loss: 0.8649 - val_accuracy: 0.6838 - val_loss: 0.8889 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6939 - loss: 0.8527 - val_accuracy: 0.6727 - val_loss: 0.9179 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7012 - loss: 0.8433 - val_accuracy: 0.6904 - val_loss: 0.8689 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7050 - loss: 0.8261 - val_accuracy: 0.6791 - val_loss: 0.8926 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.7117 - loss: 0.8117 - val_accuracy: 0.6841 - val_loss: 0.8883 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7183 - loss: 0.7957 - val_accuracy: 0.7059 - val_loss: 0.8348 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7203 - loss: 0.7857 - val_accuracy: 0.6972 - val_loss: 0.8592 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.7242 - loss: 0.7750 - val_accuracy: 0.7090 - val_loss: 0.8231 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7264 - loss: 0.7609 - val_accuracy: 0.7174 - val_loss: 0.8022 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7323 - loss: 0.7483 - val_accuracy: 0.6958 - val_loss: 0.8747 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.7369 - loss: 0.7397 - val_accuracy: 0.7183 - val_loss: 0.8075 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7403 - loss: 0.7323 - val_accuracy: 0.7202 - val_loss: 0.8023 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7446 - loss: 0.7187 - val_accuracy: 0.7080 - val_loss: 0.8383 学習時間:131.8秒 test_accuracy:0.6992 === D_LayerNorm === Model: "D_LayerNorm" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ layer_normalization │ (None, 32, 32, 3) │ 6 │ │ (LayerNormalization) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d (Conv2D) │ (None, 32, 32, 64) │ 1,792 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 16, 16, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 16, 16, 128) │ 73,856 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 8, 8, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ global_average_pooling2d │ (None, 128) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 128) │ 16,512 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 10) │ 1,290 │ └─────────────────────────────────┴────────────────────────┴───────────────┘ Total params: 93,456 (365.06 KB) Trainable params: 93,456 (365.06 KB) Non-trainable params: 0 (0.00 B) None Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 9s 9ms/step - accuracy: 0.2540 - loss: 2.0004 - val_accuracy: 0.3074 - val_loss: 1.8922 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.3334 - loss: 1.8245 - val_accuracy: 0.3705 - val_loss: 1.7488 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3756 - loss: 1.7169 - val_accuracy: 0.3831 - val_loss: 1.6901 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.4017 - loss: 1.6559 - val_accuracy: 0.4068 - val_loss: 1.6202 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4176 - loss: 1.6120 - val_accuracy: 0.4235 - val_loss: 1.5898 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4294 - loss: 1.5760 - val_accuracy: 0.4313 - val_loss: 1.5640 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4410 - loss: 1.5438 - val_accuracy: 0.4504 - val_loss: 1.5235 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4514 - loss: 1.5153 - val_accuracy: 0.4576 - val_loss: 1.5042 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4631 - loss: 1.4945 - val_accuracy: 0.4590 - val_loss: 1.4919 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4708 - loss: 1.4689 - val_accuracy: 0.4748 - val_loss: 1.4626 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4766 - loss: 1.4484 - val_accuracy: 0.4663 - val_loss: 1.4840 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4854 - loss: 1.4345 - val_accuracy: 0.4721 - val_loss: 1.4661 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4893 - loss: 1.4203 - val_accuracy: 0.4796 - val_loss: 1.4466 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4958 - loss: 1.4008 - val_accuracy: 0.4874 - val_loss: 1.4270 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5029 - loss: 1.3835 - val_accuracy: 0.4855 - val_loss: 1.4394 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5067 - loss: 1.3713 - val_accuracy: 0.4785 - val_loss: 1.4607 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5126 - loss: 1.3589 - val_accuracy: 0.4924 - val_loss: 1.4287 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5181 - loss: 1.3417 - val_accuracy: 0.4903 - val_loss: 1.4296 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5203 - loss: 1.3316 - val_accuracy: 0.4942 - val_loss: 1.4160 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5235 - loss: 1.3256 - val_accuracy: 0.4936 - val_loss: 1.4238 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5276 - loss: 1.3096 - val_accuracy: 0.4977 - val_loss: 1.4095 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5322 - loss: 1.3007 - val_accuracy: 0.5026 - val_loss: 1.3982 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5378 - loss: 1.2887 - val_accuracy: 0.4952 - val_loss: 1.4304 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5394 - loss: 1.2782 - val_accuracy: 0.4996 - val_loss: 1.4121 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5448 - loss: 1.2638 - val_accuracy: 0.5106 - val_loss: 1.3751 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5507 - loss: 1.2530 - val_accuracy: 0.5088 - val_loss: 1.3860 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5541 - loss: 1.2434 - val_accuracy: 0.5071 - val_loss: 1.3898 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.5563 - loss: 1.2392 - val_accuracy: 0.5064 - val_loss: 1.3933 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5590 - loss: 1.2268 - val_accuracy: 0.5091 - val_loss: 1.3931 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5626 - loss: 1.2153 - val_accuracy: 0.4986 - val_loss: 1.4326 学習時間:136.3秒 test_accuracy:0.4975
グラフ+サマリー
# ── val_accuracy / val_loss 比較グラフ ───────────────────
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
for label, h in histories.items():
axes[0].plot(h.history['val_accuracy'], label=label)
axes[1].plot(h.history['val_loss'], label=label)
axes[0].set_title('val_accuracy の比較(全30エポック)')
axes[1].set_title('val_loss の比較(全30エポック)')
for ax in axes:
ax.set_xlabel('Epoch'); ax.legend(fontsize=9); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('normalization_comparison.png', dpi=150)
plt.show()
# ── train_loss vs val_loss(過学習の乖離)────────────────
fig2, axes2 = plt.subplots(4, 1, figsize=(7, 18))
for i, (label, h) in enumerate(histories.items()):
axes2[i].plot(h.history['loss'], label='train_loss')
axes2[i].plot(h.history['val_loss'], label='val_loss')
axes2[i].set_title(label)
axes2[i].set_xlabel('Epoch'); axes2[i].legend(); axes2[i].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('normalization_overfit.png', dpi=150)
plt.show()
# ── サマリー ─────────────────────────────────────────────
print("\n===== 最終結果サマリー =====")
print(f"{'Pattern':>20} | {'Val Acc':>8} | {'Test Acc':>9} | {'Val Loss':>9} | {'Time(s)':>8}")
print("-" * 68)
for label, h in histories.items():
val_acc = h.history['val_accuracy'][-1]
val_loss = h.history['val_loss'][-1]
test_acc = scores[label][1]
t = times[label]
print(f"{label:>20} | {val_acc:>8.4f} | {test_acc:>9.4f} | {val_loss:>9.4f} | {t:>8.1f}")
print("-" * 68)
最終結果サマリー
===== 最終結果サマリー =====
Pattern | Val Acc | Test Acc | Val Loss | Time(s)
--------------------------------------------------------------------
A_manual_255 | 0.6613 | 0.6565 | 0.9487 | 129.7
B_Rescaling | 0.6575 | 0.6549 | 0.9488 | 125.7
C_BatchNorm | 0.7080 | 0.6992 | 0.8383 | 131.8
D_LayerNorm | 0.4986 | 0.4975 | 1.4326 | 136.3
--------------------------------------------------------------------
実験結果
実験はGoogle Colab(T4 GPU)、CIFAR-10、エポック数30・バッチサイズ64の条件で実施しました。
精度グラフ
損失グラフ
A_manual_255
B_Rescaling
C_BatchNorm
D_LayerNorm
| パターン | val_accuracy | test_accuracy | val_loss | 学習時間 |
|---|---|---|---|---|
| A:/255(手動) | 66.13% | 65.65% | 0.9487 | 129.7秒 |
| B:Rescaling層 | 65.75% | 65.49% | 0.9488 | 125.7秒 |
| C:BatchNormalization ✅ | 70.80% | 69.92% | 0.8383 | 131.8秒 |
| D:LayerNormalization ⚠️ | 49.86% | 49.75% | 1.4326 | 136.3秒 |
考察
① A と B は「数値的に同一」を実験で確認
A(/255手動)とB(Rescaling層)のtest_accuracyの差はわずか0.16%(65.65% vs 65.49%)、val_lossも0.9487 vs 0.9488とほぼ同値です。x / 255.0 と Rescaling(1./255) は数値的に完全に同等であることが実験でも裏付けられました。
学習時間はBの方が4秒短く(125.7秒 vs 129.7秒)、モデル内で処理する分のオーバーヘッドはほぼ無視できます。推論時に正規化コードを別途書く手間を省きたいならRescaling層を使うのがシンプルな選択です。
② BatchNormalization が圧倒的に高精度だった
最も驚きの結果がC:BatchNormalization(69.92%)です。ベースライン(A:65.65%)と比べて+4.27%という大幅な改善で、val_lossも0.8383と5パターン中最小でした。
今回のCは「モデルの先頭にBatchNormalizationを1層置き、入力は正規化なしの生ピクセル値(0〜255)」という構成です。BatchNormがミニバッチ単位で平均・分散を計算して動的に正規化するため、固定の /255 よりもデータの実際の分布に即した正規化が行われます。結果として収束が安定し、精度が大きく向上したと考えられます。
| 比較 | test_accuracy の差 |
|---|---|
| A(/255)vs C(BatchNorm) | +4.27%(BatchNormが上) |
| A(/255)vs B(Rescaling) | −0.16%(実質同等) |
③ LayerNormalization は画像CNNの先頭には向かない
最も注目すべき結果がD:LayerNormalization(49.75%)です。ランダム予測(10クラスで50%)とほぼ同水準で、実質的に学習が機能していない状態です。val_lossも1.4326と突出して大きく、収束が完全に乱れています。
原因はLayerNormalizationの正規化の方向にあります。LayerNormは1サンプルの全チャンネル・全空間位置にわたって平均と分散を計算します。CIFAR-10の入力(32×32×3)は空間情報が正規化の対象に含まれるため、画像の空間的な特徴(エッジ・テクスチャ)が均されてしまい、CNNが学習すべき局所的なパターンが失われます。
LayerNormalizationはTransformerのように系列データや特徴ベクトル単位で使う場合に本来の力を発揮します。画像CNNの入力正規化には不向きと覚えておきましょう。
④ 「なんとなく /255」より BatchNorm の方が精度が高い理由
/255 はピクセルの最大値(255)で割る固定変換で、データセット全体の統計を考慮しません。一方、BatchNormは学習中にミニバッチの平均(μ)と分散(σ²)を計算し、データの実際の分布に合わせて正規化します。
CIFAR-10のピクセル平均は約0.49(≒125/255)で、/255 後の平均は0に近くなりません。BatchNormはこの偏りをミニバッチ単位で自動補正するため、勾配の流れが改善されて学習が安定します。さらに学習可能なγ・βパラメータが最適なスケールとシフトを自動で学ぶ点も精度向上に貢献しています。
まとめ
| 正規化方法 | test_accuracy | パラメータ | こんな場面におすすめ |
|---|---|---|---|
| A:/255(手動) | 65.65% | なし | シンプルに試したいとき |
| B:Rescaling層 | 65.49% | なし | 前処理をモデルに内包したいとき |
| C:BatchNormalization ✅ | 69.92% | あり(γ・β) | 精度を追求したいとき・バッチサイズが十分なとき |
| D:LayerNormalization ⚠️ | 49.75% | あり(γ・β) | 画像CNNには不向き。Transformerで使う |
「なんとなく /255」よりモデル先頭にBatchNormalizationを置く方が+4%精度が高いことが実験で確認できました。一方、LayerNormalizationを画像CNNの先頭に使うと学習がほぼ機能しなくなります。画像CNNの前処理ならBatchNorm、Transformerや系列モデルならLayerNormと使い分けるのが正解です。
関連記事もあわせてどうぞ:
- BatchNormalizationの効果(あり/なし)→ Batch Normalization は本当に効くのか?MNISTで徹底比較
- BatchNorm × Dropout 比較 → BatchNormalizationはDropoutと併用すべきか?Keras×MNISTで4パターン比較
- Data Augmentation 比較 → Data Augmentationを重ねすぎると精度が下がる?flip〜cropの5パターンをCIFAR-10で比較
- 損失関数の比較 → 損失関数を変えると精度はどう変わる?sparse vs categorical vs Focal Loss【Keras×CIFAR-10実験】







0 件のコメント:
コメントを投稿