KerasのEarlyStoppingは「過学習を自動で止めてくれる便利なcallback」として有名ですが、実際にどれくらい精度が変わるのか、数値で確認したことはありますか?
特に restore_best_weights=True と False の差は「設定の説明」として目にすることが多いですが、実験で精度の差を見た記事はあまりありません。今回はGoogle ColabとCIFAR-10を使い、2つの観点から実験します。
- 実験①:
restore_best_weights=TruevsFalse— 最良重みの復元は精度にどう影響するか - 実験②:
patience=3vspatience=10vs EarlyStoppingなし — patienceの長さで何が変わるか
EarlyStoppingの基本的な仕組みや patience / monitor の選び方については既存記事をご参照ください。
→ 【Keras】EarlyStopping の使い方|patience・monitor の設定と誤作動の原因
📘 この記事でわかること
- restore_best_weights=True/Falseで精度がどれだけ変わるか
- patienceを短くすると何が起きるか・長くすると何が変わるか
- EarlyStoppingなしとの精度・エポック数の比較
実験①:restore_best_weights の効果を数値で確認
実験設定
EarlyStoppingを使い、restore_best_weights=True と False の2パターンを比較します。それ以外の条件(patience・モデル構成・エポック数)は同一です。
restore_best_weights=True の場合、EarlyStopping発動時に「学習中で最もval_lossが低かったエポックの重み」に自動で戻ります。False の場合は停止直前(改善が止まった後)の重みがそのまま残ります。
実験コード
環境準備(最初に一度だけ実行)
# ── 環境準備(最初に一度だけ実行)──────────────────────
!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 2s (3,968 kB/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 82.0 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 matplotlib.pyplot as plt
import japanize_matplotlib
import time
# CIFAR-10データの読み込み・前処理
(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
# 共通モデル(全実験で同じ構成を使う)
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, callbacks=None, epochs=50):
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
start = time.time()
history = model.fit(
x_train, y_train,
epochs=epochs,
batch_size=64,
validation_split=0.2,
callbacks=callbacks,
verbose=1
)
elapsed = time.time() - start
return history, elapsed
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 20s 0us/step
restore_best_weights 比較実験
from tensorflow.keras.callbacks import EarlyStopping
# Pattern A:restore_best_weights=True
print("\n=== Pattern A:restore_best_weights=True ===")
model_A = build_model('A_restore_true')
es_A = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True, verbose=1)
history_A, time_A = compile_and_fit(model_A, callbacks=[es_A], epochs=50)
score_A = model_A.evaluate(x_test, y_test, verbose=0)
print(f"停止エポック:{len(history_A.history['loss'])} test_accuracy:{score_A[1]:.4f}")
# Pattern B:restore_best_weights=False
print("\n=== Pattern B:restore_best_weights=False ===")
model_B = build_model('B_restore_false')
es_B = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=False, verbose=1)
history_B, time_B = compile_and_fit(model_B, callbacks=[es_B], epochs=50)
score_B = model_B.evaluate(x_test, y_test, verbose=0)
print(f"停止エポック:{len(history_B.history['loss'])} test_accuracy:{score_B[1]:.4f}")
実行結果をクリックして内容を開く
=== Pattern A:restore_best_weights=True === Epoch 1/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 13s 11ms/step - accuracy: 0.2558 - loss: 1.9466 - val_accuracy: 0.3541 - val_loss: 1.7310 Epoch 2/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 13s 6ms/step - accuracy: 0.3668 - loss: 1.6893 - val_accuracy: 0.4106 - val_loss: 1.5880 Epoch 3/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4212 - loss: 1.5711 - val_accuracy: 0.4459 - val_loss: 1.4930 Epoch 4/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4557 - loss: 1.4818 - val_accuracy: 0.4787 - val_loss: 1.4218 Epoch 5/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4825 - loss: 1.4173 - val_accuracy: 0.4982 - val_loss: 1.3770 Epoch 6/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5023 - loss: 1.3681 - val_accuracy: 0.4959 - val_loss: 1.3526 Epoch 7/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5152 - loss: 1.3229 - val_accuracy: 0.5330 - val_loss: 1.2808 Epoch 8/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5296 - loss: 1.2914 - val_accuracy: 0.5453 - val_loss: 1.2440 Epoch 9/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5377 - loss: 1.2632 - val_accuracy: 0.5448 - val_loss: 1.2746 Epoch 10/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5510 - loss: 1.2354 - val_accuracy: 0.5680 - val_loss: 1.1839 Epoch 11/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5599 - loss: 1.2072 - val_accuracy: 0.5606 - val_loss: 1.2088 Epoch 12/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5701 - loss: 1.1851 - val_accuracy: 0.5607 - val_loss: 1.2009 Epoch 13/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5756 - loss: 1.1667 - val_accuracy: 0.5818 - val_loss: 1.1405 Epoch 14/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5840 - loss: 1.1454 - val_accuracy: 0.5889 - val_loss: 1.1373 Epoch 15/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5929 - loss: 1.1221 - val_accuracy: 0.5989 - val_loss: 1.1070 Epoch 16/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5991 - loss: 1.1033 - val_accuracy: 0.6007 - val_loss: 1.0922 Epoch 17/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6112 - loss: 1.0829 - val_accuracy: 0.6171 - val_loss: 1.0611 Epoch 18/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6162 - loss: 1.0670 - val_accuracy: 0.6217 - val_loss: 1.0423 Epoch 19/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6187 - loss: 1.0513 - val_accuracy: 0.6294 - val_loss: 1.0265 Epoch 20/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6266 - loss: 1.0338 - val_accuracy: 0.6289 - val_loss: 1.0322 Epoch 21/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6331 - loss: 1.0193 - val_accuracy: 0.6430 - val_loss: 0.9961 Epoch 22/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6390 - loss: 1.0057 - val_accuracy: 0.6326 - val_loss: 1.0154 Epoch 23/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6467 - loss: 0.9872 - val_accuracy: 0.6425 - val_loss: 0.9945 Epoch 24/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6488 - loss: 0.9774 - val_accuracy: 0.6429 - val_loss: 0.9900 Epoch 25/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6555 - loss: 0.9609 - val_accuracy: 0.6311 - val_loss: 1.0125 Epoch 26/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6567 - loss: 0.9554 - val_accuracy: 0.6607 - val_loss: 0.9440 Epoch 27/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6622 - loss: 0.9416 - val_accuracy: 0.6616 - val_loss: 0.9423 Epoch 28/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6672 - loss: 0.9254 - val_accuracy: 0.6629 - val_loss: 0.9498 Epoch 29/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6696 - loss: 0.9226 - val_accuracy: 0.6631 - val_loss: 0.9368 Epoch 30/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6747 - loss: 0.9032 - val_accuracy: 0.6667 - val_loss: 0.9317 Epoch 31/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6812 - loss: 0.8869 - val_accuracy: 0.6671 - val_loss: 0.9296 Epoch 32/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6829 - loss: 0.8900 - val_accuracy: 0.6709 - val_loss: 0.9245 Epoch 33/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6868 - loss: 0.8744 - val_accuracy: 0.6643 - val_loss: 0.9247 Epoch 34/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6902 - loss: 0.8682 - val_accuracy: 0.6789 - val_loss: 0.8940 Epoch 35/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6954 - loss: 0.8523 - val_accuracy: 0.6839 - val_loss: 0.8833 Epoch 36/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6955 - loss: 0.8487 - val_accuracy: 0.6764 - val_loss: 0.8961 Epoch 37/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6998 - loss: 0.8375 - val_accuracy: 0.6866 - val_loss: 0.8785 Epoch 38/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7032 - loss: 0.8293 - val_accuracy: 0.6840 - val_loss: 0.8771 Epoch 39/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7063 - loss: 0.8201 - val_accuracy: 0.6849 - val_loss: 0.8846 Epoch 40/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7112 - loss: 0.8104 - val_accuracy: 0.6830 - val_loss: 0.8961 Epoch 41/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7117 - loss: 0.8082 - val_accuracy: 0.6815 - val_loss: 0.8920 Epoch 42/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7176 - loss: 0.7926 - val_accuracy: 0.6869 - val_loss: 0.8619 Epoch 43/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7200 - loss: 0.7860 - val_accuracy: 0.6986 - val_loss: 0.8515 Epoch 44/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7207 - loss: 0.7851 - val_accuracy: 0.6961 - val_loss: 0.8462 Epoch 45/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7232 - loss: 0.7743 - val_accuracy: 0.6914 - val_loss: 0.8621 Epoch 46/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7276 - loss: 0.7615 - val_accuracy: 0.7061 - val_loss: 0.8319 Epoch 47/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7261 - loss: 0.7664 - val_accuracy: 0.6857 - val_loss: 0.8897 Epoch 48/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7302 - loss: 0.7574 - val_accuracy: 0.6957 - val_loss: 0.8547 Epoch 49/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.7325 - loss: 0.7498 - val_accuracy: 0.7093 - val_loss: 0.8179 Epoch 50/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7345 - loss: 0.7411 - val_accuracy: 0.7106 - val_loss: 0.8287 Restoring model weights from the end of the best epoch: 49. 停止エポック:50 test_accuracy:0.7058 === Pattern B:restore_best_weights=False === Epoch 1/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 8ms/step - accuracy: 0.2746 - loss: 1.9073 - val_accuracy: 0.3586 - val_loss: 1.7019 Epoch 2/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.3874 - loss: 1.6436 - val_accuracy: 0.4234 - val_loss: 1.5604 Epoch 3/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4437 - loss: 1.5118 - val_accuracy: 0.4683 - val_loss: 1.4729 Epoch 4/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4751 - loss: 1.4372 - val_accuracy: 0.4850 - val_loss: 1.4217 Epoch 5/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4940 - loss: 1.3830 - val_accuracy: 0.5237 - val_loss: 1.3183 Epoch 6/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5117 - loss: 1.3316 - val_accuracy: 0.5048 - val_loss: 1.3159 Epoch 7/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5281 - loss: 1.2932 - val_accuracy: 0.5461 - val_loss: 1.2515 Epoch 8/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5414 - loss: 1.2581 - val_accuracy: 0.5478 - val_loss: 1.2530 Epoch 9/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5584 - loss: 1.2216 - val_accuracy: 0.5663 - val_loss: 1.1858 Epoch 10/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5660 - loss: 1.1921 - val_accuracy: 0.5743 - val_loss: 1.1671 Epoch 11/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5774 - loss: 1.1663 - val_accuracy: 0.5761 - val_loss: 1.1601 Epoch 12/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5882 - loss: 1.1400 - val_accuracy: 0.5968 - val_loss: 1.1202 Epoch 13/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5943 - loss: 1.1221 - val_accuracy: 0.6068 - val_loss: 1.0891 Epoch 14/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6048 - loss: 1.0984 - val_accuracy: 0.6054 - val_loss: 1.0979 Epoch 15/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6126 - loss: 1.0828 - val_accuracy: 0.6242 - val_loss: 1.0507 Epoch 16/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6194 - loss: 1.0540 - val_accuracy: 0.6298 - val_loss: 1.0377 Epoch 17/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6268 - loss: 1.0398 - val_accuracy: 0.6308 - val_loss: 1.0193 Epoch 18/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6321 - loss: 1.0236 - val_accuracy: 0.6355 - val_loss: 1.0299 Epoch 19/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6389 - loss: 1.0064 - val_accuracy: 0.6327 - val_loss: 1.0135 Epoch 20/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6431 - loss: 0.9897 - val_accuracy: 0.6340 - val_loss: 1.0208 Epoch 21/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6485 - loss: 0.9778 - val_accuracy: 0.6502 - val_loss: 0.9811 Epoch 22/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6578 - loss: 0.9596 - val_accuracy: 0.6515 - val_loss: 0.9658 Epoch 23/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6611 - loss: 0.9493 - val_accuracy: 0.6654 - val_loss: 0.9360 Epoch 24/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6622 - loss: 0.9378 - val_accuracy: 0.6647 - val_loss: 0.9390 Epoch 25/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6683 - loss: 0.9235 - val_accuracy: 0.6477 - val_loss: 0.9954 Epoch 26/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6761 - loss: 0.9096 - val_accuracy: 0.6710 - val_loss: 0.9121 Epoch 27/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6798 - loss: 0.8982 - val_accuracy: 0.6813 - val_loss: 0.9028 Epoch 28/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6820 - loss: 0.8902 - val_accuracy: 0.6716 - val_loss: 0.9398 Epoch 29/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6870 - loss: 0.8775 - val_accuracy: 0.6781 - val_loss: 0.9000 Epoch 30/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6916 - loss: 0.8650 - val_accuracy: 0.6856 - val_loss: 0.8902 Epoch 31/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6966 - loss: 0.8534 - val_accuracy: 0.6857 - val_loss: 0.8852 Epoch 32/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6982 - loss: 0.8439 - val_accuracy: 0.6808 - val_loss: 0.9080 Epoch 33/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7043 - loss: 0.8297 - val_accuracy: 0.6952 - val_loss: 0.8634 Epoch 34/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7061 - loss: 0.8244 - val_accuracy: 0.6949 - val_loss: 0.8715 Epoch 35/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.7103 - loss: 0.8166 - val_accuracy: 0.6912 - val_loss: 0.8799 Epoch 36/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7126 - loss: 0.8068 - val_accuracy: 0.6897 - val_loss: 0.8708 Epoch 37/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7188 - loss: 0.7955 - val_accuracy: 0.7012 - val_loss: 0.8482 Epoch 38/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7208 - loss: 0.7873 - val_accuracy: 0.6867 - val_loss: 0.8926 Epoch 39/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7207 - loss: 0.7856 - val_accuracy: 0.6967 - val_loss: 0.8480 Epoch 40/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7255 - loss: 0.7705 - val_accuracy: 0.7094 - val_loss: 0.8197 Epoch 41/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7275 - loss: 0.7633 - val_accuracy: 0.7107 - val_loss: 0.8252 Epoch 42/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7312 - loss: 0.7523 - val_accuracy: 0.7069 - val_loss: 0.8353 Epoch 43/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7360 - loss: 0.7397 - val_accuracy: 0.7038 - val_loss: 0.8466 Epoch 44/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7355 - loss: 0.7409 - val_accuracy: 0.7149 - val_loss: 0.8031 Epoch 45/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7398 - loss: 0.7341 - val_accuracy: 0.7087 - val_loss: 0.8333 Epoch 46/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7419 - loss: 0.7290 - val_accuracy: 0.7074 - val_loss: 0.8234 Epoch 47/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7425 - loss: 0.7246 - val_accuracy: 0.7085 - val_loss: 0.8268 Epoch 48/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7479 - loss: 0.7131 - val_accuracy: 0.7085 - val_loss: 0.8178 Epoch 49/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7473 - loss: 0.7067 - val_accuracy: 0.7179 - val_loss: 0.8077 Epoch 49: early stopping 停止エポック:49 test_accuracy:0.7110
グラフ
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
for label, h in [('A:restore=True', history_A), ('B:restore=False', history_B)]:
axes[0].plot(h.history['val_accuracy'], label=label)
axes[1].plot(h.history['val_loss'], label=label)
axes[0].set_title('val_accuracy の比較')
axes[1].set_title('val_loss の比較')
for ax in axes:
ax.set_xlabel('Epoch'); ax.legend(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('earlystopping_restore.png', dpi=150)
plt.show()
実験①の結果
精度グラフ
損失グラフ
| パターン | 停止エポック | test_accuracy | 備考 |
|---|---|---|---|
| A:restore_best_weights=True | 50 | 70.58% | 最良重みに復元して終了 |
| B:restore_best_weights=False | 49 | 71.10% | 停止直前の重みをそのまま使用 |
実験②:patienceの長さで何が変わるか
実験設定
restore_best_weights=True で固定し、patience=3 / patience=10 / EarlyStoppingなし(50エポック固定)の3パターンを比較します。
| パターン | patience | 期待される挙動 |
|---|---|---|
| C:patience=3 | 3 | 早めに停止。過学習前に止まるが、収束しきれない可能性あり |
| D:patience=10 | 10 | ゆっくり停止。収束を待てるが、過学習が進む可能性も |
| E:EarlyStoppingなし | — | 50エポック固定。過学習が進んだ状態で終了する可能性あり |
patience 比較実験
# Pattern C:patience=3
print("\n=== Pattern C:patience=3 ===")
model_C = build_model('C_patience3')
es_C = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True, verbose=1)
history_C, time_C = compile_and_fit(model_C, callbacks=[es_C], epochs=50)
score_C = model_C.evaluate(x_test, y_test, verbose=0)
print(f"停止エポック:{len(history_C.history['loss'])} test_accuracy:{score_C[1]:.4f}")
# Pattern D:patience=10
print("\n=== Pattern D:patience=10 ===")
model_D = build_model('D_patience10')
es_D = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True, verbose=1)
history_D, time_D = compile_and_fit(model_D, callbacks=[es_D], epochs=50)
score_D = model_D.evaluate(x_test, y_test, verbose=0)
print(f"停止エポック:{len(history_D.history['loss'])} test_accuracy:{score_D[1]:.4f}")
# Pattern E:EarlyStoppingなし(50エポック固定)
print("\n=== Pattern E:EarlyStoppingなし ===")
model_E = build_model('E_no_earlystop')
history_E, time_E = compile_and_fit(model_E, callbacks=None, epochs=50)
score_E = model_E.evaluate(x_test, y_test, verbose=0)
print(f"停止エポック:50(固定) test_accuracy:{score_E[1]:.4f}")
実行結果をクリックして内容を開く
=== Pattern C:patience=3 === Epoch 1/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 16ms/step - accuracy: 0.2580 - loss: 1.9365 - val_accuracy: 0.3324 - val_loss: 1.7495 Epoch 2/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.3660 - loss: 1.6774 - val_accuracy: 0.3862 - val_loss: 1.6134 Epoch 3/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.4209 - loss: 1.5694 - val_accuracy: 0.4530 - val_loss: 1.4880 Epoch 4/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4584 - loss: 1.4740 - val_accuracy: 0.4702 - val_loss: 1.4439 Epoch 5/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4889 - loss: 1.3960 - val_accuracy: 0.5165 - val_loss: 1.3261 Epoch 6/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5082 - loss: 1.3482 - val_accuracy: 0.5160 - val_loss: 1.3168 Epoch 7/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 7ms/step - accuracy: 0.5217 - loss: 1.3079 - val_accuracy: 0.5413 - val_loss: 1.2499 Epoch 8/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 11ms/step - accuracy: 0.5346 - loss: 1.2690 - val_accuracy: 0.5506 - val_loss: 1.2341 Epoch 9/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.5441 - loss: 1.2466 - val_accuracy: 0.5482 - val_loss: 1.2327 Epoch 10/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 8ms/step - accuracy: 0.5572 - loss: 1.2146 - val_accuracy: 0.5660 - val_loss: 1.1807 Epoch 11/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5687 - loss: 1.1870 - val_accuracy: 0.5578 - val_loss: 1.1901 Epoch 12/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5732 - loss: 1.1707 - val_accuracy: 0.5732 - val_loss: 1.1609 Epoch 13/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5839 - loss: 1.1400 - val_accuracy: 0.5918 - val_loss: 1.1092 Epoch 14/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5939 - loss: 1.1186 - val_accuracy: 0.6033 - val_loss: 1.0832 Epoch 15/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5993 - loss: 1.1046 - val_accuracy: 0.5896 - val_loss: 1.1132 Epoch 16/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6108 - loss: 1.0852 - val_accuracy: 0.6009 - val_loss: 1.1045 Epoch 17/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6119 - loss: 1.0696 - val_accuracy: 0.6176 - val_loss: 1.0507 Epoch 18/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6194 - loss: 1.0550 - val_accuracy: 0.6192 - val_loss: 1.0454 Epoch 19/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6238 - loss: 1.0442 - val_accuracy: 0.6264 - val_loss: 1.0286 Epoch 20/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6317 - loss: 1.0214 - val_accuracy: 0.6296 - val_loss: 1.0140 Epoch 21/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6356 - loss: 1.0086 - val_accuracy: 0.6342 - val_loss: 1.0051 Epoch 22/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6405 - loss: 0.9976 - val_accuracy: 0.6388 - val_loss: 1.0067 Epoch 23/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6461 - loss: 0.9835 - val_accuracy: 0.6472 - val_loss: 0.9924 Epoch 24/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6508 - loss: 0.9693 - val_accuracy: 0.6538 - val_loss: 0.9564 Epoch 25/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6535 - loss: 0.9626 - val_accuracy: 0.6303 - val_loss: 1.0078 Epoch 26/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6598 - loss: 0.9453 - val_accuracy: 0.6599 - val_loss: 0.9458 Epoch 27/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6644 - loss: 0.9359 - val_accuracy: 0.6542 - val_loss: 0.9526 Epoch 28/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6679 - loss: 0.9240 - val_accuracy: 0.6656 - val_loss: 0.9320 Epoch 29/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6718 - loss: 0.9155 - val_accuracy: 0.6373 - val_loss: 0.9935 Epoch 30/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6755 - loss: 0.8995 - val_accuracy: 0.6697 - val_loss: 0.9220 Epoch 31/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6820 - loss: 0.8908 - val_accuracy: 0.6767 - val_loss: 0.9002 Epoch 32/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6837 - loss: 0.8830 - val_accuracy: 0.6763 - val_loss: 0.9075 Epoch 33/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6865 - loss: 0.8759 - val_accuracy: 0.6706 - val_loss: 0.9148 Epoch 34/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6926 - loss: 0.8609 - val_accuracy: 0.6790 - val_loss: 0.8949 Epoch 35/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6952 - loss: 0.8566 - val_accuracy: 0.6648 - val_loss: 0.9316 Epoch 36/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6996 - loss: 0.8456 - val_accuracy: 0.6773 - val_loss: 0.8962 Epoch 37/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6992 - loss: 0.8369 - val_accuracy: 0.6835 - val_loss: 0.8889 Epoch 38/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7052 - loss: 0.8210 - val_accuracy: 0.6829 - val_loss: 0.8901 Epoch 39/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7084 - loss: 0.8213 - val_accuracy: 0.6811 - val_loss: 0.8960 Epoch 40/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7103 - loss: 0.8120 - val_accuracy: 0.6749 - val_loss: 0.9063 Epoch 40: early stopping Restoring model weights from the end of the best epoch: 37. 停止エポック:40 test_accuracy:0.6789 === Pattern D:patience=10 === Epoch 1/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2731 - loss: 1.8996 - val_accuracy: 0.3517 - val_loss: 1.7210 Epoch 2/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3721 - loss: 1.6749 - val_accuracy: 0.4040 - val_loss: 1.6279 Epoch 3/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4348 - loss: 1.5455 - val_accuracy: 0.4639 - val_loss: 1.4569 Epoch 4/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4711 - loss: 1.4481 - val_accuracy: 0.4785 - val_loss: 1.4087 Epoch 5/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4987 - loss: 1.3821 - val_accuracy: 0.5082 - val_loss: 1.3407 Epoch 6/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5131 - loss: 1.3327 - val_accuracy: 0.5272 - val_loss: 1.2870 Epoch 7/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5293 - loss: 1.2918 - val_accuracy: 0.5538 - val_loss: 1.2344 Epoch 8/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5412 - loss: 1.2610 - val_accuracy: 0.5572 - val_loss: 1.2171 Epoch 9/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5524 - loss: 1.2284 - val_accuracy: 0.5518 - val_loss: 1.2141 Epoch 10/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 7ms/step - accuracy: 0.5624 - loss: 1.2048 - val_accuracy: 0.5709 - val_loss: 1.1797 Epoch 11/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5742 - loss: 1.1740 - val_accuracy: 0.5763 - val_loss: 1.1706 Epoch 12/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5849 - loss: 1.1495 - val_accuracy: 0.5780 - val_loss: 1.1481 Epoch 13/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5932 - loss: 1.1246 - val_accuracy: 0.6051 - val_loss: 1.0896 Epoch 14/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5993 - loss: 1.1053 - val_accuracy: 0.5996 - val_loss: 1.1032 Epoch 15/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6112 - loss: 1.0868 - val_accuracy: 0.6078 - val_loss: 1.0791 Epoch 16/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6176 - loss: 1.0642 - val_accuracy: 0.6232 - val_loss: 1.0388 Epoch 17/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6233 - loss: 1.0447 - val_accuracy: 0.6189 - val_loss: 1.0509 Epoch 18/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6329 - loss: 1.0235 - val_accuracy: 0.6282 - val_loss: 1.0350 Epoch 19/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6376 - loss: 1.0148 - val_accuracy: 0.6370 - val_loss: 1.0015 Epoch 20/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6397 - loss: 1.0001 - val_accuracy: 0.6353 - val_loss: 1.0138 Epoch 21/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6497 - loss: 0.9786 - val_accuracy: 0.6498 - val_loss: 0.9659 Epoch 22/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6507 - loss: 0.9708 - val_accuracy: 0.6354 - val_loss: 1.0086 Epoch 23/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6582 - loss: 0.9558 - val_accuracy: 0.6499 - val_loss: 0.9668 Epoch 24/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6640 - loss: 0.9383 - val_accuracy: 0.6444 - val_loss: 0.9913 Epoch 25/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6661 - loss: 0.9318 - val_accuracy: 0.6575 - val_loss: 0.9498 Epoch 26/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6707 - loss: 0.9149 - val_accuracy: 0.6590 - val_loss: 0.9416 Epoch 27/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6772 - loss: 0.9049 - val_accuracy: 0.6570 - val_loss: 0.9467 Epoch 28/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6794 - loss: 0.8923 - val_accuracy: 0.6758 - val_loss: 0.9033 Epoch 29/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6862 - loss: 0.8766 - val_accuracy: 0.6616 - val_loss: 0.9384 Epoch 30/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6839 - loss: 0.8754 - val_accuracy: 0.6621 - val_loss: 0.9298 Epoch 31/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6895 - loss: 0.8674 - val_accuracy: 0.6649 - val_loss: 0.9298 Epoch 32/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6947 - loss: 0.8541 - val_accuracy: 0.6748 - val_loss: 0.9158 Epoch 33/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6963 - loss: 0.8437 - val_accuracy: 0.6783 - val_loss: 0.8953 Epoch 34/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7006 - loss: 0.8318 - val_accuracy: 0.6840 - val_loss: 0.8759 Epoch 35/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7055 - loss: 0.8179 - val_accuracy: 0.6844 - val_loss: 0.8947 Epoch 36/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7080 - loss: 0.8136 - val_accuracy: 0.6889 - val_loss: 0.8759 Epoch 37/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7136 - loss: 0.7998 - val_accuracy: 0.6762 - val_loss: 0.9050 Epoch 38/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7137 - loss: 0.7984 - val_accuracy: 0.6932 - val_loss: 0.8604 Epoch 39/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7183 - loss: 0.7825 - val_accuracy: 0.7024 - val_loss: 0.8351 Epoch 40/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7207 - loss: 0.7804 - val_accuracy: 0.6944 - val_loss: 0.8610 Epoch 41/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7262 - loss: 0.7716 - val_accuracy: 0.7022 - val_loss: 0.8376 Epoch 42/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7268 - loss: 0.7649 - val_accuracy: 0.6970 - val_loss: 0.8482 Epoch 43/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7341 - loss: 0.7495 - val_accuracy: 0.7120 - val_loss: 0.8317 Epoch 44/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7310 - loss: 0.7515 - val_accuracy: 0.7084 - val_loss: 0.8247 Epoch 45/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7354 - loss: 0.7428 - val_accuracy: 0.6984 - val_loss: 0.8548 Epoch 46/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7382 - loss: 0.7332 - val_accuracy: 0.7017 - val_loss: 0.8489 Epoch 47/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7426 - loss: 0.7194 - val_accuracy: 0.7047 - val_loss: 0.8478 Epoch 48/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7451 - loss: 0.7149 - val_accuracy: 0.7084 - val_loss: 0.8333 Epoch 49/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7445 - loss: 0.7149 - val_accuracy: 0.7135 - val_loss: 0.8216 Epoch 50/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7501 - loss: 0.7008 - val_accuracy: 0.7183 - val_loss: 0.8167 Restoring model weights from the end of the best epoch: 50. 停止エポック:50 test_accuracy:0.7128 === Pattern E:EarlyStoppingなし === Epoch 1/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2720 - loss: 1.9188 - val_accuracy: 0.3502 - val_loss: 1.7200 Epoch 2/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3819 - loss: 1.6538 - val_accuracy: 0.4302 - val_loss: 1.5504 Epoch 3/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4369 - loss: 1.5305 - val_accuracy: 0.4643 - val_loss: 1.4698 Epoch 4/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4763 - loss: 1.4303 - val_accuracy: 0.4986 - val_loss: 1.3715 Epoch 5/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4962 - loss: 1.3803 - val_accuracy: 0.5089 - val_loss: 1.3309 Epoch 6/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5133 - loss: 1.3317 - val_accuracy: 0.5273 - val_loss: 1.2994 Epoch 7/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5344 - loss: 1.2908 - val_accuracy: 0.5440 - val_loss: 1.2557 Epoch 8/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5429 - loss: 1.2543 - val_accuracy: 0.5404 - val_loss: 1.2816 Epoch 9/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5562 - loss: 1.2246 - val_accuracy: 0.5617 - val_loss: 1.2166 Epoch 10/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5661 - loss: 1.1972 - val_accuracy: 0.5731 - val_loss: 1.1748 Epoch 11/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5729 - loss: 1.1789 - val_accuracy: 0.5853 - val_loss: 1.1423 Epoch 12/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5849 - loss: 1.1502 - val_accuracy: 0.5962 - val_loss: 1.1192 Epoch 13/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5925 - loss: 1.1266 - val_accuracy: 0.5999 - val_loss: 1.0957 Epoch 14/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6010 - loss: 1.1033 - val_accuracy: 0.6146 - val_loss: 1.0690 Epoch 15/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6099 - loss: 1.0873 - val_accuracy: 0.6155 - val_loss: 1.0754 Epoch 16/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6162 - loss: 1.0671 - val_accuracy: 0.6159 - val_loss: 1.0598 Epoch 17/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.6217 - loss: 1.0524 - val_accuracy: 0.6162 - val_loss: 1.0527 Epoch 18/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6269 - loss: 1.0351 - val_accuracy: 0.6391 - val_loss: 1.0140 Epoch 19/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6371 - loss: 1.0161 - val_accuracy: 0.6321 - val_loss: 1.0237 Epoch 20/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6391 - loss: 1.0016 - val_accuracy: 0.6310 - val_loss: 1.0161 Epoch 21/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6449 - loss: 0.9890 - val_accuracy: 0.6405 - val_loss: 0.9980 Epoch 22/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6520 - loss: 0.9688 - val_accuracy: 0.6449 - val_loss: 0.9983 Epoch 23/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6557 - loss: 0.9610 - val_accuracy: 0.6526 - val_loss: 0.9651 Epoch 24/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6600 - loss: 0.9455 - val_accuracy: 0.6519 - val_loss: 0.9698 Epoch 25/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6661 - loss: 0.9360 - val_accuracy: 0.6542 - val_loss: 0.9699 Epoch 26/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6704 - loss: 0.9214 - val_accuracy: 0.6545 - val_loss: 0.9674 Epoch 27/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6730 - loss: 0.9119 - val_accuracy: 0.6584 - val_loss: 0.9447 Epoch 28/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6794 - loss: 0.8960 - val_accuracy: 0.6747 - val_loss: 0.9159 Epoch 29/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6829 - loss: 0.8820 - val_accuracy: 0.6756 - val_loss: 0.9056 Epoch 30/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6861 - loss: 0.8761 - val_accuracy: 0.6762 - val_loss: 0.9052 Epoch 31/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6921 - loss: 0.8643 - val_accuracy: 0.6744 - val_loss: 0.9200 Epoch 32/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6953 - loss: 0.8519 - val_accuracy: 0.6686 - val_loss: 0.9131 Epoch 33/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6961 - loss: 0.8490 - val_accuracy: 0.6845 - val_loss: 0.8969 Epoch 34/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 7ms/step - accuracy: 0.7016 - loss: 0.8375 - val_accuracy: 0.6677 - val_loss: 0.9156 Epoch 35/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7027 - loss: 0.8283 - val_accuracy: 0.6871 - val_loss: 0.8746 Epoch 36/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7091 - loss: 0.8191 - val_accuracy: 0.6878 - val_loss: 0.8801 Epoch 37/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7099 - loss: 0.8087 - val_accuracy: 0.6852 - val_loss: 0.8855 Epoch 38/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.7119 - loss: 0.8001 - val_accuracy: 0.6982 - val_loss: 0.8490 Epoch 39/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7187 - loss: 0.7884 - val_accuracy: 0.7015 - val_loss: 0.8351 Epoch 40/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7187 - loss: 0.7850 - val_accuracy: 0.6946 - val_loss: 0.8468 Epoch 41/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7230 - loss: 0.7715 - val_accuracy: 0.6977 - val_loss: 0.8642 Epoch 42/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.7230 - loss: 0.7697 - val_accuracy: 0.7007 - val_loss: 0.8607 Epoch 43/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7288 - loss: 0.7577 - val_accuracy: 0.7116 - val_loss: 0.8205 Epoch 44/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7318 - loss: 0.7534 - val_accuracy: 0.7030 - val_loss: 0.8381 Epoch 45/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7335 - loss: 0.7438 - val_accuracy: 0.7063 - val_loss: 0.8321 Epoch 46/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7379 - loss: 0.7348 - val_accuracy: 0.7114 - val_loss: 0.8196 Epoch 47/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7411 - loss: 0.7266 - val_accuracy: 0.6988 - val_loss: 0.8499 Epoch 48/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7410 - loss: 0.7198 - val_accuracy: 0.7086 - val_loss: 0.8242 Epoch 49/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.7449 - loss: 0.7148 - val_accuracy: 0.6982 - val_loss: 0.8621 Epoch 50/50 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7482 - loss: 0.7063 - val_accuracy: 0.7062 - val_loss: 0.8403 停止エポック:50(固定) test_accuracy:0.7050
グラフ
histories2 = {
'C:patience=3': history_C,
'D:patience=10': history_D,
'E:EarlyStoppingなし': history_E,
}
fig2, axes2 = plt.subplots(1, 2, figsize=(14, 5))
for label, h in histories2.items():
axes2[0].plot(h.history['val_accuracy'], label=label)
axes2[1].plot(h.history['val_loss'], label=label)
axes2[0].set_title('val_accuracy の比較')
axes2[1].set_title('val_loss の比較')
for ax in axes2:
ax.set_xlabel('Epoch'); ax.legend(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('earlystopping_patience.png', dpi=150)
plt.show()
# ── サマリー出力 ─────────────────────────────────
print("\n===== 実験②:最終結果サマリー =====")
results = [
('C:patience=3', len(history_C.history['loss']), score_C[1], time_C),
('D:patience=10', len(history_D.history['loss']), score_D[1], time_D),
('E:EarlyStoppingなし', 50, score_E[1], time_E),
]
print(f"{'Pattern':>24} | {'停止Ep':>6} | {'Test Acc':>9} | {'Time(s)':>8}")
print("-" * 58)
for name, ep, acc, t in results:
print(f"{name:>24} | {ep:>6} | {acc:>9.4f} | {t:>8.1f}")
実験②の結果
精度グラフ
損失グラフ
| パターン | 停止エポック | test_accuracy | 学習時間 |
|---|---|---|---|
| C:patience=3 | 40 | 67.89% | 180.2秒 |
| D:patience=10 | 50 | 71.28% | 201.1秒 |
| E:EarlyStoppingなし | 50(固定) | 70.50% | 208.2秒 |
考察
① restore_best_weights の効果:予想外の逆転結果
実験①の結果は B(False)の71.10%がA(True)の70.58%を上回るという予想外の逆転になりました。「restore_best_weights=Trueの方が精度が高いはず」という直感とは逆です。
この結果の背景を考えます。AはEp50まで学習し、EarlyStoppingが発動した時点で「学習中に最もval_lossが低かったエポックの重み」に戻されています。一方BはEp49で停止し、その時点の重みをそのまま使っています。
実験②のログからわかるように、このモデルはval_lossが50エポック時点でもまだ緩やかに改善中です。そのため「最良エポック」がEp50に近い後半に来ており、Aで復元される重みとBの最終重みがほぼ同じエポックのものになっている可能性があります。差が0.52%と小さい点もこれを裏付けています。
この結果は「restore_best_weightsが不要」という意味ではありません。今回のモデルは50エポック時点で過学習しておらず、最良重みと最終重みの差が小さかったため差が出にくかっただけです。過学習が進むモデルでは効果が顕著に現れます。実際、実験②のDとEの比較(同条件で0.78%差)がその証拠です。
② EarlyStoppingが「早期停止」として機能しなかった理由
今回の実験では、3パターンとも50エポック付近まで走りました。EarlyStoppingが「早めに打ち切る」という期待通りには動かなかったことになります。
理由はモデルの収束速度にあります。今回のGAP+Dropout=0.2構成はval_lossが50エポック時点でもまだ緩やかに下降中でした。Dのログを見るとEp50でもval_lossが0.8167と最良値を更新し続けており、「改善が止まる」タイミング自体が50エポック以降に来るモデルです。つまりepochsの上限設定(50)が先に来てしまったという状況です。
EarlyStoppingを「早期停止」として活用するには、epochs=100〜200のように上限を十分大きく設定した上で使うのが本来の使い方です。今回の実験はその前提が揃っていませんでした。
③ patience=3 の早期停止は「誤検知」だったか
Cのログを見ると、Ep37でval_loss=0.8889の最良値を記録した後、Ep38・39・40と3エポック連続で改善がなかったため停止しています。これは正常な動作ですが、問題はEp37時点でモデルがまだ収束途中だったことです。
実際、DとEはそこから学習を続けてEp39〜50でval_lossをさらに0.82〜0.83台まで改善しています。patience=3は「短すぎてモデルの伸びしろを切り捨ててしまった」結果、test_accuracyがD比で約3.4%低くなりました。
④ D(patience=10)とE(EarlyStoppingなし)の差はrestore_best_weightsの効果
DとEは同じ50エポックを走りましたが、test_accuracyに差が出ました(D:71.28% vs E:70.50%)。
Dは restore_best_weights=True により、50エポック中の最良重み(Ep50のval_loss=0.8167)に自動で戻っています。一方EはEp50の最終重みをそのまま使用しており、val_loss=0.8403でDより悪い状態です。
同じエポック数でも restore_best_weights=True があるだけで約0.8%の精度差が生まれました。設定1つの違いがこれだけ影響することが数値で確認できます。
⑤ このモデルでEarlyStoppingを有効に使うには
今回の結果から、CIFAR-10+GAP+Dropout=0.2の構成でEarlyStoppingを本来の用途(無駄なエポックのカット)として使うには以下の設定が適切です。
early_stopping = EarlyStopping(
monitor='val_loss',
patience=10, # ← 短すぎると収束前に止まる
restore_best_weights=True, # ← 必須。精度に直接影響する
verbose=1
)
history = model.fit(
x_train, y_train,
epochs=200, # ← 上限を十分大きくする
batch_size=64,
validation_split=0.2,
callbacks=[early_stopping]
)
epochsを200に増やせば、学習が本当に頭打ちになったタイミングで自動停止し、計算コストの削減効果が得られます。
まとめ
- EarlyStoppingはepochsの上限を十分大きく設定して使うのが前提。上限が低すぎると早期停止として機能しない
patience=3は収束途中で止まり、DよりもTest Accが約3.4%低くなった。このモデルでは短すぎるrestore_best_weights=Trueは同じ50エポックでもEなしと比べ約0.8%の精度差を生んだ。必ず設定すべき- GAP+Dropout=0.2構成ではval_lossの収束が遅いため、patience=10以上・epochs=100〜200が実用的な設定
関連記事もあわせてどうぞ:
- EarlyStoppingの基本・patience・monitor の選び方 → 【Keras】EarlyStopping の使い方|patience・monitor の設定と誤作動の原因
- EarlyStoppingの入門記事 → 【Keras】EarlyStoppingで過学習防止:精度低下の原因と対策
- Dropout率の比較実験 → Dropoutの割合(0.0 vs 0.2 vs 0.5)を変えると過学習はどう変わる?【Keras×CIFAR-10実験】
- 過学習の判定方法と対策 → CIFAR-10で学ぶ:過学習(オーバーフィッティング)の判定方法と実践的対策





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