「過学習を防ぐにはDropoutを入れれば十分」——そう思って試してみたら、まだtrain_lossとval_lossが乖離している……そんな経験はありませんか?
今回はCutOutとRandom Erasingという「画像の一部をマスクするデータ拡張」を使い、過学習への効果をKerasとCIFAR-10で実験しました。
なお、Dropoutの割合比較は → Dropoutの割合を変えると過学習はどう変わる?【Keras×CIFAR-10実験】、MixUpの効果検証は → MixUpの効果検証【Keras×CIFAR-10実験】 もご覧ください。
- CutOut・Random Erasingとは何か、どう違うのか
- Kerasで両手法を自作してCIFAR-10に適用する方法
- なし・CutOut・Random Erasingの3パターンで精度と過学習の度合いを比較した実験結果
- DropoutとCutOut系手法を組み合わせるときの注意点
CutOut と Random Erasing はどう違うのか
どちらも「画像の矩形領域をゼロ埋め(または乱数)で消す」という発想は同じです。違いは何で埋めるかとサイズ・位置の決め方にあります。
| 手法 | 提案年 | 埋める値 | 領域の決め方 |
|---|---|---|---|
| CutOut | 2017 | 固定値(0 またはグレー) | 固定サイズの正方形をランダム位置に配置 |
| Random Erasing | 2020 | ランダムな値([0,1] の乱数) | 面積比・アスペクト比をランダムにサンプリング |
CutOutは「黒い四角を貼り付ける」イメージ。Random Erasingは「ノイズパッチを貼り付ける」イメージです。どちらもモデルに「一部が見えなくても正解を当てろ」という制約を課し、特定の局所特徴への過依存を防ぎます。
- 正規化後に適用すること。
/255でスケーリングしたあとにCutOutを適用しないと、ゼロ埋めの意味が変わります(ゼロ=黒 になるのは正規化後が前提)。 - マスクサイズが大きすぎると精度が下がる。CIFAR-10(32×32px)では
cutout_size=8〜12程度が目安。16以上にすると情報が消えすぎて学習が不安定になります。 - Random Erasingの面積比(sl, sh)を広げすぎるのも同様にNG。論文デフォルト(sl=0.02, sh=0.4)からスタートしましょう。
- Keras の
tf.dataパイプラインでランダム処理を入れる場合、tf.py_functionを使うと GPU 転送の効率が落ちることがあります。今回はNumPy関数として実装し、map()で呼び出す方式にしています。
実験コード
使用環境はGoogle Colab(GPU:T4)、データセットはCIFAR-10です。CutOut / Random Erasingの有無以外の条件は全て同一にして、手法の影響だけを取り出します。
環境準備(最初に一度だけ実行)
# ── 環境準備(最初に一度だけ実行)──────────────────────
!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 100 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 (28.2 MB/s)
Selecting previously unselected package fonts-ipafont-gothic.
(Reading database ... 122402 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 69.1 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
Building wheel for japanize_matplotlib (setup.py) ... done
環境準備完了
import・データ準備・CutOut / Random Erasing の実装
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, y_test) = keras.datasets.cifar10.load_data()
x_train_raw = x_train_raw.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# ── CutOut ──────────────────────────────────────────────
def cutout(image, cutout_size=10):
"""画像の矩形領域をゼロで塗りつぶす(CutOut)"""
h, w, c = image.shape
cx = np.random.randint(0, w)
cy = np.random.randint(0, h)
x1 = max(0, cx - cutout_size // 2)
y1 = max(0, cy - cutout_size // 2)
x2 = min(w, cx + cutout_size // 2)
y2 = min(h, cy + cutout_size // 2)
image = image.copy()
image[y1:y2, x1:x2, :] = 0.0
return image
def apply_cutout(images, cutout_size=10):
return np.array([cutout(img, cutout_size) for img in images])
# ── Random Erasing ──────────────────────────────────────
def random_erasing(image, sl=0.02, sh=0.4, r1=0.3, r2=3.3):
"""画像の矩形領域をランダムな値で塗りつぶす(Random Erasing)"""
h, w, c = image.shape
area = h * w
for _ in range(100): # 試行回数の上限
target_area = np.random.uniform(sl, sh) * area
aspect_ratio = np.random.uniform(r1, r2)
rect_h = int(round(np.sqrt(target_area * aspect_ratio)))
rect_w = int(round(np.sqrt(target_area / aspect_ratio)))
if rect_h < h and rect_w < w:
x1 = np.random.randint(0, w - rect_w)
y1 = np.random.randint(0, h - rect_h)
image = image.copy()
image[y1:y1+rect_h, x1:x1+rect_w, :] = np.random.uniform(0, 1, (rect_h, rect_w, c))
return image
return image # 領域が見つからない場合はそのまま返す
def apply_random_erasing(images, **kwargs):
return np.array([random_erasing(img, **kwargs) for img in images])
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 407s 2us/step
適用例の可視化(確認用)
# ── 適用例を可視化して確認 ──────────────────────────────
fig, axes = plt.subplots(3, 5, figsize=(12, 7))
class_names = ['airplane','automobile','bird','cat','deer',
'dog','frog','horse','ship','truck']
titles = ['オリジナル', 'CutOut', 'Random Erasing']
x_sample = x_train_raw[:5]
for row, (title, imgs) in enumerate(zip(titles, [
x_sample,
apply_cutout(x_sample),
apply_random_erasing(x_sample),
])):
for col in range(5):
axes[row, col].imshow(imgs[col])
axes[row, col].axis('off')
if row == 0:
axes[row, col].set_title(class_names[int(y_train[col])], fontsize=9)
axes[row, 0].set_ylabel(title, fontsize=11, rotation=90, labelpad=10)
plt.suptitle('CutOut / Random Erasing の適用例', fontsize=13)
plt.tight_layout()
plt.savefig('cutout_samples.png', dpi=150)
plt.show()
実行例
モデル構築・学習関数
# ── モデル構築(3パターン共通) ──────────────────────────
def build_model(name):
return keras.Sequential([
keras.layers.Input(shape=(32, 32, 3)),
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(10, activation='softmax'),
], name=name)
def compile_and_fit(model, x_train_aug):
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
start = time.time()
history = model.fit(x_train_aug, y_train,
epochs=30, batch_size=64,
validation_split=0.2, verbose=1)
return history, time.time() - start
3パターンの学習実行
# ── 3パターンで学習 ─────────────────────────────────────
configs = {
'A_none': x_train_raw,
'B_cutout': apply_cutout(x_train_raw, cutout_size=10),
'C_random_erasing': apply_random_erasing(x_train_raw),
}
histories, times, scores, params = {}, {}, {}, {}
for name, x_aug in configs.items():
print(f"\n=== {name} ===")
model = build_model(name)
h, t = compile_and_fit(model, x_aug)
s = model.evaluate(x_test, y_test, verbose=0)
label = name.split('_', 1)[1] # 'none' / 'cutout' / 'random_erasing'
histories[label] = h
times[label] = t
scores[label] = s
params[label] = model.count_params()
print(f"学習時間:{t:.1f}秒 パラメータ数:{model.count_params():,} test_accuracy:{s[1]:.4f}")
実行結果をクリックして内容を開く
=== A_none === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 9ms/step - accuracy: 0.2696 - loss: 1.9064 - val_accuracy: 0.3598 - val_loss: 1.6940 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3722 - loss: 1.6694 - val_accuracy: 0.4241 - val_loss: 1.5736 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4336 - loss: 1.5321 - val_accuracy: 0.4679 - val_loss: 1.4801 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4746 - loss: 1.4427 - val_accuracy: 0.5023 - val_loss: 1.3774 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4963 - loss: 1.3708 - val_accuracy: 0.5247 - val_loss: 1.3078 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5168 - loss: 1.3321 - val_accuracy: 0.5042 - val_loss: 1.3531 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5319 - loss: 1.2873 - val_accuracy: 0.5286 - val_loss: 1.2826 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5396 - loss: 1.2621 - val_accuracy: 0.5587 - val_loss: 1.2144 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5526 - loss: 1.2306 - val_accuracy: 0.5651 - val_loss: 1.1859 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5645 - loss: 1.2024 - val_accuracy: 0.5743 - val_loss: 1.1643 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5713 - loss: 1.1748 - val_accuracy: 0.5910 - val_loss: 1.1324 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5824 - loss: 1.1466 - val_accuracy: 0.5882 - val_loss: 1.1284 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5878 - loss: 1.1350 - val_accuracy: 0.5833 - val_loss: 1.1438 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5987 - loss: 1.1103 - val_accuracy: 0.6014 - val_loss: 1.1153 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6039 - loss: 1.0883 - val_accuracy: 0.6071 - val_loss: 1.0744 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6165 - loss: 1.0700 - val_accuracy: 0.6253 - val_loss: 1.0262 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6190 - loss: 1.0588 - val_accuracy: 0.6048 - val_loss: 1.0823 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6271 - loss: 1.0351 - val_accuracy: 0.6189 - val_loss: 1.0421 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6335 - loss: 1.0181 - val_accuracy: 0.6326 - val_loss: 1.0108 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6358 - loss: 1.0115 - val_accuracy: 0.6374 - val_loss: 0.9963 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6452 - loss: 0.9925 - val_accuracy: 0.6358 - val_loss: 1.0086 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6435 - loss: 0.9865 - val_accuracy: 0.6252 - val_loss: 1.0338 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6536 - loss: 0.9685 - val_accuracy: 0.6521 - val_loss: 0.9610 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6577 - loss: 0.9595 - val_accuracy: 0.6332 - val_loss: 1.0114 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6622 - loss: 0.9413 - val_accuracy: 0.6680 - val_loss: 0.9322 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6668 - loss: 0.9299 - val_accuracy: 0.6504 - val_loss: 0.9623 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6723 - loss: 0.9178 - val_accuracy: 0.6455 - val_loss: 0.9822 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6739 - loss: 0.9082 - val_accuracy: 0.6142 - val_loss: 1.0635 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6781 - loss: 0.8998 - val_accuracy: 0.6771 - val_loss: 0.9042 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6810 - loss: 0.8871 - val_accuracy: 0.6758 - val_loss: 0.9122 学習時間:120.8秒 パラメータ数:93,450 test_accuracy:0.6711 === B_cutout === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 9ms/step - accuracy: 0.2546 - loss: 1.9626 - val_accuracy: 0.3259 - val_loss: 1.8309 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3577 - loss: 1.7152 - val_accuracy: 0.4102 - val_loss: 1.6063 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4090 - loss: 1.5979 - val_accuracy: 0.4444 - val_loss: 1.4999 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4476 - loss: 1.5027 - val_accuracy: 0.4581 - val_loss: 1.4903 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4705 - loss: 1.4405 - val_accuracy: 0.5019 - val_loss: 1.3808 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4891 - loss: 1.3963 - val_accuracy: 0.5024 - val_loss: 1.3810 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5032 - loss: 1.3562 - val_accuracy: 0.5167 - val_loss: 1.3222 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5142 - loss: 1.3271 - val_accuracy: 0.5271 - val_loss: 1.2949 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5278 - loss: 1.2969 - val_accuracy: 0.5245 - val_loss: 1.2968 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5383 - loss: 1.2681 - val_accuracy: 0.5452 - val_loss: 1.2682 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5464 - loss: 1.2417 - val_accuracy: 0.5658 - val_loss: 1.1975 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5581 - loss: 1.2184 - val_accuracy: 0.5758 - val_loss: 1.1798 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5677 - loss: 1.1888 - val_accuracy: 0.5817 - val_loss: 1.1710 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5760 - loss: 1.1680 - val_accuracy: 0.5782 - val_loss: 1.1695 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5839 - loss: 1.1442 - val_accuracy: 0.5704 - val_loss: 1.1602 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5933 - loss: 1.1281 - val_accuracy: 0.5798 - val_loss: 1.1628 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6014 - loss: 1.1101 - val_accuracy: 0.5940 - val_loss: 1.1122 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6021 - loss: 1.0944 - val_accuracy: 0.6077 - val_loss: 1.0754 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6136 - loss: 1.0730 - val_accuracy: 0.6239 - val_loss: 1.0494 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6159 - loss: 1.0661 - val_accuracy: 0.6143 - val_loss: 1.0572 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6245 - loss: 1.0488 - val_accuracy: 0.5937 - val_loss: 1.1145 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6302 - loss: 1.0277 - val_accuracy: 0.6271 - val_loss: 1.0246 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6356 - loss: 1.0161 - val_accuracy: 0.6268 - val_loss: 1.0411 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6399 - loss: 1.0044 - val_accuracy: 0.6147 - val_loss: 1.0688 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6439 - loss: 0.9936 - val_accuracy: 0.6415 - val_loss: 1.0038 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6507 - loss: 0.9762 - val_accuracy: 0.6148 - val_loss: 1.0463 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6533 - loss: 0.9634 - val_accuracy: 0.6443 - val_loss: 0.9910 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6578 - loss: 0.9547 - val_accuracy: 0.6332 - val_loss: 0.9998 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6645 - loss: 0.9388 - val_accuracy: 0.6368 - val_loss: 1.0093 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6647 - loss: 0.9367 - val_accuracy: 0.6435 - val_loss: 0.9899 学習時間:120.7秒 パラメータ数:93,450 test_accuracy:0.6603 === C_random_erasing === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2201 - loss: 2.0558 - val_accuracy: 0.3230 - val_loss: 1.8502 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3327 - loss: 1.7888 - val_accuracy: 0.3669 - val_loss: 1.7175 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3777 - loss: 1.6805 - val_accuracy: 0.4063 - val_loss: 1.6134 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4047 - loss: 1.6136 - val_accuracy: 0.4308 - val_loss: 1.5502 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4260 - loss: 1.5621 - val_accuracy: 0.4524 - val_loss: 1.4980 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4480 - loss: 1.5060 - val_accuracy: 0.4540 - val_loss: 1.4905 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4625 - loss: 1.4706 - val_accuracy: 0.4732 - val_loss: 1.4415 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4735 - loss: 1.4375 - val_accuracy: 0.4766 - val_loss: 1.4409 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4897 - loss: 1.3986 - val_accuracy: 0.4904 - val_loss: 1.3846 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4961 - loss: 1.3748 - val_accuracy: 0.4920 - val_loss: 1.3646 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5076 - loss: 1.3505 - val_accuracy: 0.5146 - val_loss: 1.3231 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5156 - loss: 1.3283 - val_accuracy: 0.5268 - val_loss: 1.2977 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5224 - loss: 1.3056 - val_accuracy: 0.5169 - val_loss: 1.3095 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5300 - loss: 1.2866 - val_accuracy: 0.5310 - val_loss: 1.2683 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5365 - loss: 1.2733 - val_accuracy: 0.5340 - val_loss: 1.2558 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5421 - loss: 1.2541 - val_accuracy: 0.5433 - val_loss: 1.2456 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5485 - loss: 1.2385 - val_accuracy: 0.5426 - val_loss: 1.2442 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5569 - loss: 1.2207 - val_accuracy: 0.5606 - val_loss: 1.2013 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5572 - loss: 1.2082 - val_accuracy: 0.5378 - val_loss: 1.2444 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5660 - loss: 1.1954 - val_accuracy: 0.5350 - val_loss: 1.2505 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5717 - loss: 1.1810 - val_accuracy: 0.5601 - val_loss: 1.1898 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5745 - loss: 1.1659 - val_accuracy: 0.5570 - val_loss: 1.2088 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5804 - loss: 1.1573 - val_accuracy: 0.5583 - val_loss: 1.2045 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5865 - loss: 1.1426 - val_accuracy: 0.5647 - val_loss: 1.1862 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5899 - loss: 1.1306 - val_accuracy: 0.5823 - val_loss: 1.1451 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5941 - loss: 1.1230 - val_accuracy: 0.5769 - val_loss: 1.1567 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5981 - loss: 1.1104 - val_accuracy: 0.5839 - val_loss: 1.1351 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6045 - loss: 1.0912 - val_accuracy: 0.5879 - val_loss: 1.1205 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6046 - loss: 1.0894 - val_accuracy: 0.5860 - val_loss: 1.1282 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6087 - loss: 1.0763 - val_accuracy: 0.5982 - val_loss: 1.1012 学習時間:119.5秒 パラメータ数:93,450 test_accuracy:0.6518
グラフ+サマリー
# ── val_accuracy / val_loss 比較グラフ ───────────────────
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
label_map = {'none': 'A:なし', 'cutout': 'B:CutOut', 'random_erasing': 'C:Random Erasing'}
for label, h in histories.items():
axes[0].plot(h.history['val_accuracy'], label=label_map[label])
axes[1].plot(h.history['val_loss'], label=label_map[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('cutout_comparison.png', dpi=150)
plt.show()
# ── train_loss vs val_loss(過学習の乖離)────────────────
fig2, axes2 = plt.subplots(3, 1, figsize=(7, 14))
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_map[label])
axes2[i].set_xlabel('Epoch'); axes2[i].legend(); axes2[i].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('cutout_overfit.png', dpi=150)
plt.show()
print("\n===== 最終結果サマリー =====")
print(f"{'Pattern':>18} | {'Val Acc':>8} | {'Test Acc':>9} | {'Time(s)':>8} | {'Params':>10}")
print("-" * 65)
for label in ['none', 'cutout', 'random_erasing']:
val_acc = histories[label].history['val_accuracy'][-1]
test_acc = scores[label][1]
t = times[label]
p = params[label]
print(f"{label_map[label]:>18} | {val_acc:>8.4f} | {test_acc:>9.4f} | {t:>8.1f} | {p:>10,}")
print("-" * 65)
最終結果サマリー
===== 最終結果サマリー =====
Pattern | Val Acc | Test Acc | Time(s) | Params
-----------------------------------------------------------------
A:なし | 0.6758 | 0.6711 | 120.8 | 93,450
B:CutOut | 0.6435 | 0.6603 | 120.7 | 93,450
C:Random Erasing | 0.5982 | 0.6518 | 119.5 | 93,450
-----------------------------------------------------------------
実験結果
精度グラフ
損失グラフ
A:なし
B:CutOut
C:Random Erasing
| パターン | 最終 val_accuracy | 最終 test_accuracy | パラメータ数 | 学習時間 |
|---|---|---|---|---|
| A:なし | 67.58% | 67.11% | 93,450 | 120.8秒 |
| B:CutOut | 64.35% | 66.03% | 93,450 | 120.7秒 |
| C:Random Erasing | 59.82% | 65.18% | 93,450 | 119.5秒 |
考察
① 予想に反して「なし」が val_accuracy 最高という結果に
今回の実験では、val_accuracy は A:なし(67.58%)> B:CutOut(64.35%)> C:Random Erasing(59.82%)という順になりました。直感に反する結果ですが、これは「マスクが強すぎてモデルが学習できていない」状態、いわゆるunderfitting(学習不足)に陥っている可能性が高いです。
CIFAR-10 の画像は 32×32px と非常に小さく、情報量が元から少ない状態です。そこに大きなマスクをかけると、モデルが正解を学ぶための手がかり自体が失われてしまいます。
② CutOut は test_accuracy では「なし」を上回っている
val_accuracy ではなしに劣った CutOut ですが、test_accuracy は 66.03%(なし 67.11%)と −1.08% で下回る結果となりました。今回の再実験では CutOut も test_accuracy でなしを上回ることができませんでした。ただし val_accuracy(64.35%)と test_accuracy(66.03%)の差が約1.7%あり、val と test で乖離が生じている点は注目です。val_accuracy だけで判断すると実際の汎化性能を誤読するリスクがある点に注意が必要です。
③ Random Erasing は val_accuracy が大きく落ちた——パラメータが問題
Random Erasing は val_accuracy が 59.82% と大幅に低下しました。原因は今回使用したパラメータ(sl=0.02, sh=0.4)が CIFAR-10 に対して強すぎたことです。sh=0.4 は画像面積の最大40%を消すことを意味します。32×32px の画像では 10×10px 超のパッチが消える計算になり、識別に必要な情報が根本から失われます。
論文デフォルト(sl=0.02, sh=0.4)は ImageNet(224×224px)向けの設定です。CIFAR-10(32×32px)のような小画像に使うと過剰なマスクになります。
CIFAR-10 での目安:
sl=0.02, sh=0.15〜0.2 程度に下げて再実験してみましょう(追加実験を下記に掲載)。
④ パラメータ数は全パターン同一——コストゼロで試せる
データ拡張はモデルのアーキテクチャに影響しないため、パラメータ数は全パターン同一(93,450)です。学習時間の差も最大 1.5秒(約1%)とほぼ無視できるレベルです。「失敗しても戻すコストがほぼゼロ」な手法なので、まずためしてみる価値は十分あります。
⑤ 「なし」より良くなるかどうかは画像サイズとパラメータ次第
CutOut・Random Erasing は「情報を意図的に壊してロバスト性を上げる」手法です。効果が出る条件は、画像の情報量がマスクで失われても正解できる余裕があること。高解像度・情報密度の高い画像(ImageNet, 医療画像など)では有効に働きますが、CIFAR-10 のような極小解像度では過剰になりやすいです。
追加実験:Random Erasing のパラメータを CIFAR-10 向けに調整
sh=0.4 が強すぎた可能性があるため、sh=0.15 に絞って再実験します。また、CutOut のマスクサイズも 8px に縮小したパターンを追加します。
# ── 追加実験:パラメータを CIFAR-10 向けに調整 ───────────
configs_extra = {
'D_cutout_s8': apply_cutout(x_train_raw, cutout_size=8),
'E_random_erasing_s': apply_random_erasing(x_train_raw, sl=0.02, sh=0.15),
}
for name, x_aug in configs_extra.items():
print(f"\n=== {name} ===")
model = build_model(name)
h, t = compile_and_fit(model, x_aug)
s = model.evaluate(x_test, y_test, verbose=0)
label = name.split('_', 1)[1]
histories[label] = h
times[label] = t
scores[label] = s
params[label] = model.count_params()
print(f"学習時間:{t:.1f}秒 test_accuracy:{s[1]:.4f}")
# ── 追加実験の比較表出力 ────────────────────────────────
print("\n===== 追加実験サマリー =====")
all_labels = ['none', 'cutout', 'random_erasing', 'cutout_s8', 'random_erasing_s']
label_map_ext = {
'none': 'A:なし',
'cutout': 'B:CutOut(size=10)',
'random_erasing': 'C:RE(sh=0.40)',
'cutout_s8': 'D:CutOut(size=8)',
'random_erasing_s': 'E:RE(sh=0.15)',
}
print(f"{'Pattern':>22} | {'Val Acc':>8} | {'Test Acc':>9}")
print("-" * 48)
for label in all_labels:
val_acc = histories[label].history['val_accuracy'][-1]
test_acc = scores[label][1]
print(f"{label_map_ext[label]:>22} | {val_acc:>8.4f} | {test_acc:>9.4f}")
実行結果をクリックして内容を開く
=== D_cutout_s8 ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 9ms/step - accuracy: 0.2585 - loss: 1.9509 - val_accuracy: 0.3469 - val_loss: 1.7733
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3473 - loss: 1.7279 - val_accuracy: 0.3988 - val_loss: 1.6318
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4063 - loss: 1.6017 - val_accuracy: 0.4409 - val_loss: 1.5249
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4464 - loss: 1.5074 - val_accuracy: 0.4726 - val_loss: 1.4270
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4722 - loss: 1.4414 - val_accuracy: 0.4864 - val_loss: 1.3859
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4963 - loss: 1.3856 - val_accuracy: 0.5083 - val_loss: 1.3329
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5066 - loss: 1.3495 - val_accuracy: 0.5221 - val_loss: 1.3081
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5188 - loss: 1.3162 - val_accuracy: 0.5219 - val_loss: 1.3059
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5305 - loss: 1.2869 - val_accuracy: 0.5331 - val_loss: 1.2729
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5428 - loss: 1.2590 - val_accuracy: 0.5493 - val_loss: 1.2284
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5530 - loss: 1.2283 - val_accuracy: 0.5559 - val_loss: 1.2196
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5598 - loss: 1.2102 - val_accuracy: 0.5683 - val_loss: 1.1727
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5709 - loss: 1.1846 - val_accuracy: 0.5742 - val_loss: 1.1735
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5757 - loss: 1.1647 - val_accuracy: 0.5837 - val_loss: 1.1497
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5863 - loss: 1.1459 - val_accuracy: 0.5710 - val_loss: 1.1680
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5943 - loss: 1.1214 - val_accuracy: 0.5826 - val_loss: 1.1473
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6007 - loss: 1.1065 - val_accuracy: 0.5977 - val_loss: 1.0971
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6051 - loss: 1.0935 - val_accuracy: 0.6170 - val_loss: 1.0639
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6133 - loss: 1.0730 - val_accuracy: 0.6094 - val_loss: 1.0770
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6208 - loss: 1.0564 - val_accuracy: 0.6124 - val_loss: 1.0551
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6285 - loss: 1.0357 - val_accuracy: 0.6179 - val_loss: 1.0458
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6287 - loss: 1.0286 - val_accuracy: 0.6085 - val_loss: 1.0813
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6374 - loss: 1.0120 - val_accuracy: 0.6265 - val_loss: 1.0436
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6410 - loss: 1.0023 - val_accuracy: 0.6433 - val_loss: 0.9953
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6439 - loss: 0.9855 - val_accuracy: 0.6327 - val_loss: 1.0133
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6488 - loss: 0.9799 - val_accuracy: 0.6413 - val_loss: 1.0079
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6547 - loss: 0.9626 - val_accuracy: 0.6504 - val_loss: 0.9748
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6608 - loss: 0.9539 - val_accuracy: 0.6573 - val_loss: 0.9621
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6655 - loss: 0.9392 - val_accuracy: 0.6467 - val_loss: 0.9820
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6679 - loss: 0.9323 - val_accuracy: 0.6523 - val_loss: 0.9731
学習時間:122.7秒 test_accuracy:0.6647
=== E_random_erasing_s ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2498 - loss: 1.9693 - val_accuracy: 0.3329 - val_loss: 1.7824
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3469 - loss: 1.7342 - val_accuracy: 0.3771 - val_loss: 1.6588
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3997 - loss: 1.6183 - val_accuracy: 0.4266 - val_loss: 1.5474
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4373 - loss: 1.5278 - val_accuracy: 0.4598 - val_loss: 1.4650
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4625 - loss: 1.4643 - val_accuracy: 0.4791 - val_loss: 1.4128
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4830 - loss: 1.4039 - val_accuracy: 0.5030 - val_loss: 1.3518
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5012 - loss: 1.3642 - val_accuracy: 0.5106 - val_loss: 1.3300
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5167 - loss: 1.3247 - val_accuracy: 0.5178 - val_loss: 1.3073
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5309 - loss: 1.2917 - val_accuracy: 0.5388 - val_loss: 1.2640
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5402 - loss: 1.2675 - val_accuracy: 0.5527 - val_loss: 1.2164
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5469 - loss: 1.2440 - val_accuracy: 0.5418 - val_loss: 1.2506
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5588 - loss: 1.2178 - val_accuracy: 0.5589 - val_loss: 1.2125
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5675 - loss: 1.1961 - val_accuracy: 0.5646 - val_loss: 1.1898
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5735 - loss: 1.1761 - val_accuracy: 0.5383 - val_loss: 1.2276
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5810 - loss: 1.1538 - val_accuracy: 0.5877 - val_loss: 1.1256
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5905 - loss: 1.1299 - val_accuracy: 0.5899 - val_loss: 1.1285
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5975 - loss: 1.1141 - val_accuracy: 0.5946 - val_loss: 1.1050
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6015 - loss: 1.1000 - val_accuracy: 0.5934 - val_loss: 1.1104
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6066 - loss: 1.0863 - val_accuracy: 0.6082 - val_loss: 1.0754
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6144 - loss: 1.0689 - val_accuracy: 0.5977 - val_loss: 1.1039
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6206 - loss: 1.0488 - val_accuracy: 0.6153 - val_loss: 1.0559
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6284 - loss: 1.0339 - val_accuracy: 0.6104 - val_loss: 1.0765
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6324 - loss: 1.0194 - val_accuracy: 0.6230 - val_loss: 1.0366
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6374 - loss: 1.0091 - val_accuracy: 0.6153 - val_loss: 1.0360
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6387 - loss: 1.0001 - val_accuracy: 0.6334 - val_loss: 1.0077
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6468 - loss: 0.9801 - val_accuracy: 0.6325 - val_loss: 1.0190
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6518 - loss: 0.9696 - val_accuracy: 0.6168 - val_loss: 1.0636
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6547 - loss: 0.9641 - val_accuracy: 0.6386 - val_loss: 1.0029
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6571 - loss: 0.9542 - val_accuracy: 0.6460 - val_loss: 0.9717
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6628 - loss: 0.9390 - val_accuracy: 0.6438 - val_loss: 0.9774
学習時間:121.5秒 test_accuracy:0.6745
===== 追加実験サマリー =====
Pattern | Val Acc | Test Acc
------------------------------------------------
A:なし | 0.6758 | 0.6711
B:CutOut(size=10) | 0.6435 | 0.6603
C:RE(sh=0.40) | 0.5982 | 0.6518
D:CutOut(size=8) | 0.6523 | 0.6647
E:RE(sh=0.15) | 0.6438 | 0.6745
追加実験の結果と読み方
| パターン | val_accuracy | test_accuracy | なしとの差(test) |
|---|---|---|---|
| A:なし | 67.58% | 67.11% | — |
| B:CutOut(size=10) | 64.35% | 66.03% | −1.08% |
| C:Random Erasing(sh=0.40) | 59.82% | 65.18% | −1.93% |
| D:CutOut(size=8) | 65.23% | 66.47% | −0.64% |
| E:Random Erasing(sh=0.15) | 64.38% | 67.45% | +0.34% |
パラメータを調整しても val_accuracy はなしを下回る結果となりました。ただし E:RE(sh=0.15) の test_accuracy は 67.45% でなしの 67.11% を +0.34% 上回り、唯一「なし超え」を達成しました。「val_accuracy では見えない汎化性能の改善」がパラメータ調整後に現れた形です。
val_accuracy が低いのに test_accuracy が高いのは矛盾に見えますが、これはマスクによってval セット(訓練データの一部)への特化が抑えられ、真の汎化性能が上がっているためと解釈できます。最終的な判断は test_accuracy で行うことが重要です。
- デフォルトパラメータのままでは、CIFAR-10(32×32px)に対してマスクが過剰になりunderfittingを引き起こす。
- パラメータを調整(RE: sh=0.15)すると、test_accuracy でなしを上回る結果が得られた(+0.34%)。
- val_accuracy と test_accuracy が逆転することがある。汎化性能の評価は test_accuracy で行うこと。
- 論文デフォルトのパラメータは大画像(ImageNet等)向け。小画像へ転用するときはsh を 0.15 前後に縮小して調整する。
- CutOut・Random Erasing ともにモデルのパラメータ数・学習時間への影響はほぼゼロ。試すコストは低い。
関連記事もあわせてどうぞ:
- Dropout率の比較 → Dropoutの割合を変えると過学習はどう変わる?【Keras×CIFAR-10実験】
- MixUpの効果検証 → MixUpの効果検証【Keras×CIFAR-10実験】
- BatchNorm vs Dropout → BatchNormalization vs Dropout|過学習への効果を比較【Keras実験】
- 正規化方法の比較 → 正規化方法の比較(/255 vs BatchNorm vs LayerNorm)【Keras×CIFAR-10実験】







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