RandomZoomはCIFAR-10に効く?0.1〜0.5の5段階で比較実験【Keras・Augmentationシリーズ③】

投稿日:2026年5月6日水曜日 最終更新日:

CIFAR-10 CNN Data Augmentation Google Colab Keras RandomZoom データ拡張 画像分類

X f B! P L
RandomZoomはCIFAR-10に効く?0.1〜0.5の5段階で比較実験【Keras・Augmentationシリーズ③】 アイキャッチ画像

Augmentationシリーズ3回目です。
第1回では「flip + rotation + zoom + cropを重ねるほど精度が下がる」、 第2回では「rotationはどの角度でもCIFAR-10では逆効果」という結果になりました。
今回は RandomZoom の強度だけを5段階に変えて比較します。 rotationと異なりzoomは余白が生まれない変換のため、低解像度でも効果が出る可能性があります。

📘 この記事でわかること

  • RandomZoom の数値が実際にどの程度の拡大・縮小を意味するか
  • rotationと異なりzoomが低解像度でも有効になりうる理由
  • CIFAR-10(32×32)に最適なzoom強度
  • Augmentationシリーズ3回の実験を通じた最終推奨設定

RandomZoom の仕組み──rotationとの決定的な違い

Kerasの RandomZoom(height_factor) は、画像をランダムに拡大・縮小する変換です。 0.2 を指定すると ±20%の範囲でランダムにズーム します。

zoom値拡大・縮小範囲イメージ
0.1±10%わずかに大きく・小さくなる
0.2±20%やや拡大・縮小
0.3±30%明確に被写体サイズが変わる
0.5±50%被写体が半分になるケースも

rotationとの最大の違いは黒い余白が生まれない点です。
縮小時は画像端をコピーして埋め(fill_mode)、拡大時は中央部分をクロップして32×32に戻します。 32×32という小さな画像でもエッジ情報が失われにくく、 rotationより低解像度への影響が緩やかになることが期待できます。

📌 シリーズ前回記事:CIFAR-10にRandomRotationは逆効果?角度を変えて5段階で比較実験した結果【Keras】


実験で比較する5段階

全パターンに RandomFlip('horizontal') を統一適用し、 RandomZoom の値だけを変えます。 モデル構造・エポック数・バッチサイズ・オプティマイザは前回・前々回と同一です。

パターンzoom値拡大・縮小範囲狙い
A:0.0zoomなしなしflipのみのベースライン
B:0.10.1±10%最小限のズーム
C:0.20.2±20%よく使われる標準値
D:0.30.3±30%やや強めのズーム
E:0.50.5±50%強めのズーム(上限確認)

実験コード

環境準備(最初に一度だけ実行)

# ── 環境準備(最初に一度だけ実行)──────────────────────
!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 (64.3 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 59.1 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
  Building wheel for japanize_matplotlib (setup.py) ... done
環境準備完了

import・データ準備・Augmentationレイヤーの定義

import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import japanize_matplotlib
import time

# ── データ読み込みと正規化 ──────────────────────────────
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.0
x_test  = x_test.astype('float32')  / 255.0

# ── zoom値ごとのAugmentation定義 ────────────────────────
def get_augmentation(zoom_factor):
    layers = [keras.layers.RandomFlip('horizontal')]
    if zoom_factor > 0:
        layers.append(keras.layers.RandomZoom(zoom_factor))
    return keras.Sequential(layers, name=f'aug_zoom{zoom_factor}')
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 238s 1us/step

モデル構築関数

# ── モデル構築関数 ─────────────────────────────────────
def build_model(zoom_factor, name):
    augmentation = get_augmentation(zoom_factor)
    model = keras.Sequential([
        keras.layers.Input(shape=(32, 32, 3)),
        augmentation,
        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(256, activation='relu'),
        keras.layers.Dropout(0.2),
        keras.layers.Dense(10, activation='softmax'),
    ], name=name)
    model.compile(
        optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy']
    )
    return model

5パターンの学習実行

EPOCHS = 30
BATCH  = 64

configs = [
    (0.0, 'A_zoom0.0'),
    (0.1, 'B_zoom0.1'),
    (0.2, 'C_zoom0.2'),
    (0.3, 'D_zoom0.3'),
    (0.5, 'E_zoom0.5'),
]

histories, scores, times = {}, {}, {}

for zoom, name in configs:
    print(f"\n=== {name} ===")
    model = build_model(zoom, name)
    start = time.time()
    h = model.fit(
        x_train, y_train,
        epochs=EPOCHS,
        batch_size=BATCH,
        validation_split=0.2,
        verbose=1
    )
    elapsed = time.time() - start
    score = model.evaluate(x_test, y_test, verbose=0)
    label = name.split('_')[1]   # 'zoom0.0' / 'zoom0.1' / ...
    histories[label] = h
    scores[label]    = score
    times[label]     = elapsed
    print(f"学習時間:{elapsed:.1f}秒 test_accuracy:{score[1]:.4f}")
実行結果をクリックして内容を開く
=== A_zoom0.0 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 11ms/step - accuracy: 0.2887 - loss: 1.8719 - val_accuracy: 0.3702 - val_loss: 1.7261
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.4026 - loss: 1.6086 - val_accuracy: 0.4296 - val_loss: 1.5420
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4531 - loss: 1.4815 - val_accuracy: 0.4851 - val_loss: 1.4071
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4883 - loss: 1.3986 - val_accuracy: 0.5138 - val_loss: 1.3421
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5074 - loss: 1.3419 - val_accuracy: 0.5333 - val_loss: 1.2914
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5267 - loss: 1.2961 - val_accuracy: 0.5434 - val_loss: 1.2512
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5385 - loss: 1.2636 - val_accuracy: 0.5572 - val_loss: 1.2196
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5526 - loss: 1.2269 - val_accuracy: 0.5600 - val_loss: 1.2073
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5651 - loss: 1.1938 - val_accuracy: 0.5738 - val_loss: 1.1677
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5782 - loss: 1.1593 - val_accuracy: 0.5870 - val_loss: 1.1387
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5894 - loss: 1.1357 - val_accuracy: 0.5925 - val_loss: 1.1275
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5983 - loss: 1.1147 - val_accuracy: 0.5969 - val_loss: 1.1115
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6062 - loss: 1.0915 - val_accuracy: 0.6001 - val_loss: 1.0892
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6174 - loss: 1.0659 - val_accuracy: 0.6210 - val_loss: 1.0474
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6238 - loss: 1.0475 - val_accuracy: 0.6095 - val_loss: 1.1099
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6287 - loss: 1.0319 - val_accuracy: 0.6326 - val_loss: 1.0193
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6374 - loss: 1.0126 - val_accuracy: 0.6387 - val_loss: 0.9998
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6434 - loss: 0.9934 - val_accuracy: 0.6467 - val_loss: 0.9910
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6513 - loss: 0.9763 - val_accuracy: 0.6618 - val_loss: 0.9571
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6525 - loss: 0.9666 - val_accuracy: 0.6573 - val_loss: 0.9542
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6596 - loss: 0.9462 - val_accuracy: 0.6529 - val_loss: 0.9674
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6650 - loss: 0.9351 - val_accuracy: 0.6638 - val_loss: 0.9323
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6704 - loss: 0.9176 - val_accuracy: 0.6617 - val_loss: 0.9423
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6732 - loss: 0.9101 - val_accuracy: 0.6671 - val_loss: 0.9264
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6804 - loss: 0.8964 - val_accuracy: 0.6763 - val_loss: 0.9017
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6846 - loss: 0.8828 - val_accuracy: 0.6762 - val_loss: 0.9034
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6880 - loss: 0.8688 - val_accuracy: 0.6776 - val_loss: 0.9010
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6909 - loss: 0.8589 - val_accuracy: 0.6712 - val_loss: 0.9184
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6952 - loss: 0.8480 - val_accuracy: 0.6901 - val_loss: 0.8706
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6974 - loss: 0.8421 - val_accuracy: 0.6831 - val_loss: 0.8887
学習時間:133.8秒 test_accuracy:0.6810

=== B_zoom0.1 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 10ms/step - accuracy: 0.2621 - loss: 1.9290 - val_accuracy: 0.3570 - val_loss: 1.7243
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3715 - loss: 1.6740 - val_accuracy: 0.4169 - val_loss: 1.5716
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4317 - loss: 1.5489 - val_accuracy: 0.4411 - val_loss: 1.5032
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4707 - loss: 1.4550 - val_accuracy: 0.4861 - val_loss: 1.4018
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4914 - loss: 1.3965 - val_accuracy: 0.5130 - val_loss: 1.3227
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5081 - loss: 1.3474 - val_accuracy: 0.5248 - val_loss: 1.3173
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5225 - loss: 1.3119 - val_accuracy: 0.5459 - val_loss: 1.2563
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5393 - loss: 1.2717 - val_accuracy: 0.5502 - val_loss: 1.2330
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.5508 - loss: 1.2489 - val_accuracy: 0.5495 - val_loss: 1.2418
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5616 - loss: 1.2115 - val_accuracy: 0.5693 - val_loss: 1.1681
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5705 - loss: 1.1897 - val_accuracy: 0.5783 - val_loss: 1.1719
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 11s 17ms/step - accuracy: 0.5749 - loss: 1.1740 - val_accuracy: 0.5815 - val_loss: 1.1594
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 22ms/step - accuracy: 0.5843 - loss: 1.1493 - val_accuracy: 0.5972 - val_loss: 1.1259
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 23ms/step - accuracy: 0.5916 - loss: 1.1297 - val_accuracy: 0.5817 - val_loss: 1.1649
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 24ms/step - accuracy: 0.5998 - loss: 1.1127 - val_accuracy: 0.6186 - val_loss: 1.0697
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 12s 18ms/step - accuracy: 0.6079 - loss: 1.0880 - val_accuracy: 0.6028 - val_loss: 1.0937
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 17s 13ms/step - accuracy: 0.6120 - loss: 1.0777 - val_accuracy: 0.5546 - val_loss: 1.2294
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 13ms/step - accuracy: 0.6229 - loss: 1.0587 - val_accuracy: 0.6302 - val_loss: 1.0256
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 8ms/step - accuracy: 0.6208 - loss: 1.0500 - val_accuracy: 0.6296 - val_loss: 1.0463
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6316 - loss: 1.0319 - val_accuracy: 0.6352 - val_loss: 1.0143
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6362 - loss: 1.0112 - val_accuracy: 0.6249 - val_loss: 1.0500
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6378 - loss: 1.0057 - val_accuracy: 0.6361 - val_loss: 1.0178
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 8ms/step - accuracy: 0.6463 - loss: 0.9921 - val_accuracy: 0.6406 - val_loss: 0.9997
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6490 - loss: 0.9786 - val_accuracy: 0.6281 - val_loss: 1.0434
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6554 - loss: 0.9683 - val_accuracy: 0.6569 - val_loss: 0.9597
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6578 - loss: 0.9569 - val_accuracy: 0.6631 - val_loss: 0.9493
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6599 - loss: 0.9467 - val_accuracy: 0.6680 - val_loss: 0.9424
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6603 - loss: 0.9493 - val_accuracy: 0.6620 - val_loss: 0.9484
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6665 - loss: 0.9306 - val_accuracy: 0.6330 - val_loss: 1.0167
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 12s 19ms/step - accuracy: 0.6695 - loss: 0.9194 - val_accuracy: 0.6659 - val_loss: 0.9331
学習時間:228.8秒 test_accuracy:0.6671

=== C_zoom0.2 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 10ms/step - accuracy: 0.2655 - loss: 1.9275 - val_accuracy: 0.3778 - val_loss: 1.6807
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3821 - loss: 1.6585 - val_accuracy: 0.4117 - val_loss: 1.5975
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4382 - loss: 1.5361 - val_accuracy: 0.4430 - val_loss: 1.5510
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4719 - loss: 1.4505 - val_accuracy: 0.4882 - val_loss: 1.3885
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4961 - loss: 1.3876 - val_accuracy: 0.5262 - val_loss: 1.3197
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5129 - loss: 1.3431 - val_accuracy: 0.5151 - val_loss: 1.3107
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5236 - loss: 1.3134 - val_accuracy: 0.5167 - val_loss: 1.3101
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5401 - loss: 1.2771 - val_accuracy: 0.5555 - val_loss: 1.2310
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5497 - loss: 1.2524 - val_accuracy: 0.5404 - val_loss: 1.2634
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5597 - loss: 1.2218 - val_accuracy: 0.5585 - val_loss: 1.2321
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5714 - loss: 1.1975 - val_accuracy: 0.5775 - val_loss: 1.1478
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5793 - loss: 1.1739 - val_accuracy: 0.5898 - val_loss: 1.1372
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5852 - loss: 1.1544 - val_accuracy: 0.5939 - val_loss: 1.1237
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5912 - loss: 1.1355 - val_accuracy: 0.5956 - val_loss: 1.1214
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6007 - loss: 1.1197 - val_accuracy: 0.6099 - val_loss: 1.0918
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6069 - loss: 1.1031 - val_accuracy: 0.6048 - val_loss: 1.1137
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6120 - loss: 1.0826 - val_accuracy: 0.6323 - val_loss: 1.0461
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6163 - loss: 1.0656 - val_accuracy: 0.6365 - val_loss: 1.0261
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6255 - loss: 1.0475 - val_accuracy: 0.6394 - val_loss: 1.0141
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6307 - loss: 1.0383 - val_accuracy: 0.6333 - val_loss: 1.0285
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6358 - loss: 1.0213 - val_accuracy: 0.6480 - val_loss: 1.0041
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6369 - loss: 1.0093 - val_accuracy: 0.6171 - val_loss: 1.0765
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6402 - loss: 1.0048 - val_accuracy: 0.6644 - val_loss: 0.9465
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6488 - loss: 0.9860 - val_accuracy: 0.6639 - val_loss: 0.9407
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6510 - loss: 0.9833 - val_accuracy: 0.6737 - val_loss: 0.9238
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6549 - loss: 0.9670 - val_accuracy: 0.6624 - val_loss: 0.9619
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6612 - loss: 0.9532 - val_accuracy: 0.6713 - val_loss: 0.9323
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6608 - loss: 0.9573 - val_accuracy: 0.6768 - val_loss: 0.9191
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6664 - loss: 0.9366 - val_accuracy: 0.6735 - val_loss: 0.9314
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6684 - loss: 0.9303 - val_accuracy: 0.6795 - val_loss: 0.9074
学習時間:164.3秒 test_accuracy:0.6759

=== D_zoom0.3 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 9ms/step - accuracy: 0.2564 - loss: 1.9481 - val_accuracy: 0.3420 - val_loss: 1.7478
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3586 - loss: 1.7144 - val_accuracy: 0.3913 - val_loss: 1.6480
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4055 - loss: 1.6109 - val_accuracy: 0.4349 - val_loss: 1.5120
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4401 - loss: 1.5267 - val_accuracy: 0.4769 - val_loss: 1.4239
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4673 - loss: 1.4621 - val_accuracy: 0.4967 - val_loss: 1.3760
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4809 - loss: 1.4182 - val_accuracy: 0.5086 - val_loss: 1.3278
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4981 - loss: 1.3763 - val_accuracy: 0.5194 - val_loss: 1.3058
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5137 - loss: 1.3468 - val_accuracy: 0.5284 - val_loss: 1.2809
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5245 - loss: 1.3143 - val_accuracy: 0.5417 - val_loss: 1.2579
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5313 - loss: 1.2954 - val_accuracy: 0.5368 - val_loss: 1.2848
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5437 - loss: 1.2651 - val_accuracy: 0.5646 - val_loss: 1.1878
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.5509 - loss: 1.2450 - val_accuracy: 0.5701 - val_loss: 1.1766
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5617 - loss: 1.2173 - val_accuracy: 0.5863 - val_loss: 1.1495
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5638 - loss: 1.2073 - val_accuracy: 0.5895 - val_loss: 1.1266
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5782 - loss: 1.1734 - val_accuracy: 0.5945 - val_loss: 1.1157
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5819 - loss: 1.1608 - val_accuracy: 0.5916 - val_loss: 1.1322
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5869 - loss: 1.1471 - val_accuracy: 0.6107 - val_loss: 1.0742
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5957 - loss: 1.1297 - val_accuracy: 0.6148 - val_loss: 1.0582
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6037 - loss: 1.1074 - val_accuracy: 0.6196 - val_loss: 1.0487
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6068 - loss: 1.0887 - val_accuracy: 0.6104 - val_loss: 1.0813
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6108 - loss: 1.0878 - val_accuracy: 0.6261 - val_loss: 1.0433
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6172 - loss: 1.0692 - val_accuracy: 0.6324 - val_loss: 1.0224
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 9ms/step - accuracy: 0.6222 - loss: 1.0558 - val_accuracy: 0.6274 - val_loss: 1.0285
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6264 - loss: 1.0468 - val_accuracy: 0.6164 - val_loss: 1.0609
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6304 - loss: 1.0387 - val_accuracy: 0.6451 - val_loss: 0.9854
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6310 - loss: 1.0351 - val_accuracy: 0.6265 - val_loss: 1.0527
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6343 - loss: 1.0203 - val_accuracy: 0.6553 - val_loss: 0.9653
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6398 - loss: 1.0114 - val_accuracy: 0.6510 - val_loss: 0.9706
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6444 - loss: 1.0001 - val_accuracy: 0.6550 - val_loss: 0.9734
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6463 - loss: 0.9969 - val_accuracy: 0.6392 - val_loss: 1.0068
学習時間:167.2秒 test_accuracy:0.6394

=== E_zoom0.5 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 9ms/step - accuracy: 0.2549 - loss: 1.9579 - val_accuracy: 0.3366 - val_loss: 1.7445
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.3503 - loss: 1.7416 - val_accuracy: 0.4073 - val_loss: 1.6336
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3997 - loss: 1.6325 - val_accuracy: 0.4445 - val_loss: 1.5129
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4283 - loss: 1.5610 - val_accuracy: 0.4564 - val_loss: 1.4715
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4538 - loss: 1.5022 - val_accuracy: 0.4936 - val_loss: 1.3912
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4708 - loss: 1.4526 - val_accuracy: 0.5098 - val_loss: 1.3494
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.4868 - loss: 1.4195 - val_accuracy: 0.5328 - val_loss: 1.2903
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4997 - loss: 1.3801 - val_accuracy: 0.5352 - val_loss: 1.2697
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5092 - loss: 1.3566 - val_accuracy: 0.5529 - val_loss: 1.2342
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5217 - loss: 1.3314 - val_accuracy: 0.5333 - val_loss: 1.2654
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5278 - loss: 1.3070 - val_accuracy: 0.5699 - val_loss: 1.1893
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5346 - loss: 1.2840 - val_accuracy: 0.5722 - val_loss: 1.1899
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5481 - loss: 1.2604 - val_accuracy: 0.5860 - val_loss: 1.1424
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5530 - loss: 1.2444 - val_accuracy: 0.5903 - val_loss: 1.1302
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5594 - loss: 1.2212 - val_accuracy: 0.5871 - val_loss: 1.1408
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5677 - loss: 1.2068 - val_accuracy: 0.5770 - val_loss: 1.1768
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5689 - loss: 1.2025 - val_accuracy: 0.6053 - val_loss: 1.0983
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5783 - loss: 1.1822 - val_accuracy: 0.6222 - val_loss: 1.0595
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5841 - loss: 1.1660 - val_accuracy: 0.6208 - val_loss: 1.0621
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5871 - loss: 1.1513 - val_accuracy: 0.6208 - val_loss: 1.0639
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5903 - loss: 1.1446 - val_accuracy: 0.6120 - val_loss: 1.0826
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5965 - loss: 1.1319 - val_accuracy: 0.6378 - val_loss: 1.0154
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6012 - loss: 1.1205 - val_accuracy: 0.6162 - val_loss: 1.0740
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6028 - loss: 1.1091 - val_accuracy: 0.6346 - val_loss: 1.0260
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6082 - loss: 1.0979 - val_accuracy: 0.6342 - val_loss: 1.0226
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6106 - loss: 1.0903 - val_accuracy: 0.6350 - val_loss: 1.0214
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6139 - loss: 1.0841 - val_accuracy: 0.6480 - val_loss: 0.9889
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6212 - loss: 1.0695 - val_accuracy: 0.6521 - val_loss: 0.9642
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6248 - loss: 1.0590 - val_accuracy: 0.6527 - val_loss: 0.9891
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6264 - loss: 1.0548 - val_accuracy: 0.6537 - val_loss: 0.9681
学習時間:162.6秒 test_accuracy:0.6535

グラフ描画・サマリー

# ── 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(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('zoom_val.png', dpi=150)
plt.show()

# ── train vs val(過学習の乖離)────────────────────────
fig2, axes2 = plt.subplots(1, 2, figsize=(14, 5))
for ax, label in zip(axes2, ['zoom0.0', 'zoom0.2']):
    h = histories[label]
    ax.plot(h.history['loss'],     label='train_loss')
    ax.plot(h.history['val_loss'], label='val_loss')
    ax.set_title(f'{label}:train vs val loss')
    ax.set_xlabel('Epoch'); ax.legend(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('zoom_overfit.png', dpi=150)
plt.show()

# ── サマリー ─────────────────────────────────────────────
print("\n===== 最終結果サマリー =====")
print(f"{'Pattern':>10} | {'Zoom Range':>12} | {'Val Acc':>8} | {'Test Acc':>9} | {'Time(s)':>8}")
print("-" * 60)
range_map = {'zoom0.0': 'なし', 'zoom0.1': '±10%',
             'zoom0.2': '±20%', 'zoom0.3': '±30%', 'zoom0.5': '±50%'}
for label, h in histories.items():
    val_acc  = h.history['val_accuracy'][-1]
    test_acc = scores[label][1]
    t        = times[label]
    rng      = range_map[label]
    print(f"{label:>10} | {rng:>12} | {val_acc:>8.4f} | {test_acc:>9.4f} | {t:>8.1f}")
print("-" * 60)

最終結果サマリー

===== 最終結果サマリー =====
   Pattern |   Zoom Range |  Val Acc |  Test Acc |  Time(s)
------------------------------------------------------------
   zoom0.0 |           なし |   0.6831 |    0.6810 |    133.8
   zoom0.1 |         ±10% |   0.6659 |    0.6671 |    228.8
   zoom0.2 |         ±20% |   0.6795 |    0.6759 |    164.3
   zoom0.3 |         ±30% |   0.6392 |    0.6394 |    167.2
   zoom0.5 |         ±50% |   0.6537 |    0.6535 |    162.6
------------------------------------------------------------

実験結果

精度グラフ

精度グラフ

損失グラフ

損失グラフ

zoom0.0

zoom0.0

zoom0.2

zoom0.2
パターン 拡大・縮小範囲 最終 val_accuracy 最終 test_accuracy 学習時間
A:zoom0.0なし(flipのみ)68.31%68.10%133.8秒
B:zoom0.1±10%66.59%66.71%228.8秒
C:zoom0.2±20%67.95%67.59%164.3秒
D:zoom0.3±30%63.92%63.94%167.2秒
E:zoom0.5±50%65.37%65.35%162.6秒

最も良かったのはrotation実験と同様にzoomなし(flipのみ)のパターンAでした。
ただしrotationと異なり、zoom0.2はベースラインとの差がわずか0.5ポイントに留まっており、 zoomはrotationより低解像度への影響が緩やかであることが確認できます。
また、zoom0.1よりzoom0.2の方が精度が高いという逆転現象も見られました。


考察

① zoomはrotationより低解像度への影響が緩やかだった

rotationでは最小の0.03(±10.8度)でさえ精度が約3.1ポイント低下しましたが、 zoom0.2では低下幅が約0.5ポイントに留まりました。 この差は余白の有無によるものです。 rotationはコーナーに黒い余白が生まれ被写体が歪みますが、 zoomは拡大・縮小後に32×32にリサイズするため余白が生まれません。 被写体の形そのものは維持されやすいという特性が、 低解像度での影響を小さくしています。

② zoom0.1よりzoom0.2の方が精度が高かった理由

zoom0.1(±10%)よりzoom0.2(±20%)の方が精度が高いという逆転は、 zoom0.1の変化が小さすぎてAugmentationとして機能しきれていない可能性を示しています。 わずかな拡大・縮小はモデルにとって「ほぼ同じ画像」に見えるため、 過学習抑制の効果が薄くなります。 一方zoom0.2は変化量が適度で、モデルが「スケールの違う被写体」として認識できる ちょうどよい強さだったと考えられます。

③ zoom0.3・0.5で精度が落ちた理由

zoom0.3(±30%)以上では縮小方向に振れた場合、 32×32という小さなCIFAR-10の画像がさらに小さくなり、 被写体が数ピクセルに収まってしまうケースが増えます。 モデルが学ぶべき特徴量が失われ、精度が低下します。 また拡大方向では中央部のみがクロップされるため、 被写体が画像の端にある場合に特徴が欠落します。

④ zoom0.5でzoom0.3より精度が高い逆転について

zoom0.3(63.94%)よりzoom0.5(65.35%)の方が若干精度が高い点は一見不思議ですが、 これはランダム性による実行ごとのばらつきの範囲内と考えられます。 30エポック・単一実験での比較であるため、複数回実行した平均で比較すると 差が逆転する可能性もあります。

⑤ 学習時間の異常値:zoom0.1で228秒

zoom0.1の学習時間(228.8秒)はzoom0.2〜0.5(約163〜167秒)と比較して 約65秒も長くなっています。これはColabのGPU割り当て状況や セッション初期化のタイミングによる実行環境のばらつきと考えられます。 zoom強度と学習時間には本来相関がなく、zoomレイヤーの有無による 追加コストはどのzoom値でもほぼ同等のはずです。


Augmentationシリーズ3回の総まとめ

3回の実験(flip・rotation・zoom)を通じた結果を集約します。

実験 最良パターン test_accuracy 結論
第1回:flip〜crop比較 flip のみ 69.35% 重ねるほど逆効果
第2回:rotation角度比較 rotation なし(flip のみ) 68.42% どの角度でも逆効果
第3回:zoom強度比較 zoom なし(flip のみ) 68.10% rotationより影響は緩やか。zoom0.2はベースラインに迫る

CIFAR-10(32×32)向けの最終推奨設定

Augmentation推奨理由
RandomFlip✅ 使う余白なし・コスト小・効果あり(最良)
RandomZoom⚠️ 0.2以下なら検討余地ありrotationより影響が緩やか。ただしflipのみより精度は下がる
RandomRotation❌ 使わないどの角度でも精度が下がる
RandomCrop❌ 単独では使わない他の変換との重ね掛けで最悪化

3回の実験を通じた最終結論は「CIFAR-10ではRandomFlipのみが最善」です。
zoomはrotationと異なり影響が緩やかで、zoom0.2ならベースラインとの差が0.5ポイント程度に留まります。 ただし精度を最優先するなら、flipのみのシンプルな構成が最も安定しています。
Augmentationはデータセットの解像度と特性に合った手法を選ぶことが、実験を通じた一貫した教訓です。


関連記事もあわせてどうぞ: