CIFAR-10で学ぶ:過学習(オーバーフィッティング)の判定方法と実践的対策

投稿日:2025年11月22日土曜日 最終更新日:

CIFAR-10 Google Colab 過学習

X f B! P L
Flat-style illustration explaining overfitting in deep learning, featuring a neural network diagram and diverging training vs. validation accuracy curves, used for a CIFAR-10 tutorial.

過学習とは?

  過学習(オーバーフィッティング)とは、モデルが訓練データに過度に適合してしまい、未知データ(検証・テスト)で性能が落ちる現象、すなわちモデルの汎化能力が低い状態を指します。   今回は CIFAR-10 (32x32ピクセル)を使い、モデルのキャパシティに比べてデータ量が少ない状況を作り、過学習を意図的に再現して判定方法を確認します。

過学習を判定する代表的な方法(要点)

  1. 学習曲線(training / validation の loss と accuracy)を見る:典型的なサインは「train loss が下がり続ける一方で val loss が上がる」こと。
  2. train accuracy と val accuracy の乖離:差(gap)が明確に大きい(例: 0.05〜0.1 以上の場合は要注意、データ依存)。
  3. 混同行列(confusion matrix)でクラスごとの誤りを確認:特定クラスだけ過適合しているケースもある。
  4. ホールドアウト(未使用テスト)での評価:本当に過学習していればホールドアウトでの性能が低くなる。
  5. 学習率・損失の異常な振動:高学習率での振動が原因のことがある(ReduceLROnPlateau等で改善する場合あり)。

学習を自動で止めたい場合は、
【Keras】EarlyStoppingで過学習防止:精度低下の原因と対策が最も簡単で効果的です。

実験:CIFAR-10 で過学習を意図的に作ってみる(コード)

下記は「簡単に過学習しやすい」モデルを使った例です。まずはこれで学習曲線を観察してください。

# CIFAR-10: 過学習を観察する最小例(Keras)
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
import numpy as np

# データ読み込み・正規化
(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

# 過学習を促すため、ラベル数をそのまま使う(10クラス)
y_train = y_train.flatten()
y_test  = y_test.flatten()

# 簡単なCNN(容量はそこそこ大きめ)
def build_overfit_model():
    model = keras.Sequential([
        layers.Input(shape=(32,32,3)),
        layers.Conv2D(64, 3, activation='relu', padding='same'),
        layers.Conv2D(64, 3, activation='relu', padding='same'),
        layers.MaxPooling2D(),
        layers.Conv2D(128, 3, activation='relu', padding='same'),
        layers.Flatten(),
        layers.Dense(256, activation='relu'),
        layers.Dense(10, activation='softmax')
    ])
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    return model

model = build_overfit_model()
history = model.fit(
    x_train, y_train,
    validation_data=(x_test, y_test),
    epochs=30,
    batch_size=128,
    verbose=1
)

上のコードは ドロップアウトなし/正則化なし/データ拡張なし を意図しています。これにより、訓練精度は上がる一方で検証精度が伸び悩む(=過学習)状況が出やすくなります。

実行結果

Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 3s 0us/step
Epoch 1/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 26s 45ms/step - accuracy: 0.4101 - loss: 1.6275 - val_accuracy: 0.6377 - val_loss: 1.0361
Epoch 2/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 23s 17ms/step - accuracy: 0.6976 - loss: 0.8688 - val_accuracy: 0.7063 - val_loss: 0.8294
Epoch 3/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.7731 - loss: 0.6490 - val_accuracy: 0.7176 - val_loss: 0.8325
Epoch 4/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.8495 - loss: 0.4387 - val_accuracy: 0.7302 - val_loss: 0.8379
Epoch 5/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9233 - loss: 0.2264 - val_accuracy: 0.7293 - val_loss: 0.9449
Epoch 6/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9608 - loss: 0.1187 - val_accuracy: 0.7272 - val_loss: 1.1731
Epoch 7/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9810 - loss: 0.0618 - val_accuracy: 0.7261 - val_loss: 1.3242
Epoch 8/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9846 - loss: 0.0491 - val_accuracy: 0.7324 - val_loss: 1.4748
Epoch 9/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9852 - loss: 0.0430 - val_accuracy: 0.7232 - val_loss: 1.6118
Epoch 10/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 9s 23ms/step - accuracy: 0.9864 - loss: 0.0430 - val_accuracy: 0.7134 - val_loss: 1.6947
Epoch 11/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 8s 20ms/step - accuracy: 0.9855 - loss: 0.0444 - val_accuracy: 0.7195 - val_loss: 1.8150
Epoch 12/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9867 - loss: 0.0427 - val_accuracy: 0.7302 - val_loss: 1.7343
Epoch 13/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9883 - loss: 0.0341 - val_accuracy: 0.7204 - val_loss: 1.8102
Epoch 14/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9899 - loss: 0.0308 - val_accuracy: 0.7164 - val_loss: 2.1454
Epoch 15/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9923 - loss: 0.0233 - val_accuracy: 0.7195 - val_loss: 1.7841
Epoch 16/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9893 - loss: 0.0320 - val_accuracy: 0.7198 - val_loss: 1.9830
Epoch 17/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9906 - loss: 0.0281 - val_accuracy: 0.7183 - val_loss: 2.2332
Epoch 18/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9891 - loss: 0.0357 - val_accuracy: 0.7102 - val_loss: 2.1783
Epoch 19/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9931 - loss: 0.0238 - val_accuracy: 0.7174 - val_loss: 2.2118
Epoch 20/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9929 - loss: 0.0221 - val_accuracy: 0.7134 - val_loss: 2.3343
Epoch 21/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9913 - loss: 0.0268 - val_accuracy: 0.7208 - val_loss: 2.2652
Epoch 22/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9929 - loss: 0.0207 - val_accuracy: 0.7175 - val_loss: 2.4275
Epoch 23/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9925 - loss: 0.0233 - val_accuracy: 0.7098 - val_loss: 2.3908
Epoch 24/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9916 - loss: 0.0254 - val_accuracy: 0.7100 - val_loss: 2.2662
Epoch 25/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9923 - loss: 0.0235 - val_accuracy: 0.7218 - val_loss: 2.6457
Epoch 26/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9944 - loss: 0.0170 - val_accuracy: 0.7210 - val_loss: 2.5831
Epoch 27/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9924 - loss: 0.0240 - val_accuracy: 0.7141 - val_loss: 2.5018
Epoch 28/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9918 - loss: 0.0246 - val_accuracy: 0.7154 - val_loss: 2.6567
Epoch 29/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - accuracy: 0.9948 - loss: 0.0166 - val_accuracy: 0.7160 - val_loss: 2.7957
Epoch 30/30
391/391 ━━━━━━━━━━━━━━━━━━━━ 7s 17ms/step - accuracy: 0.9938 - loss: 0.0191 - val_accuracy: 0.7118 - val_loss: 2.7851

学習曲線を描いて判定する(可視化コード)

# 学習曲線(Loss / Accuracy)の描画

# Loss
plt.figure(figsize=(10,5))
plt.plot(history.history['loss'], label='train_loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.title('Loss')
plt.show()

# Accuracy
plt.figure(figsize=(10,5))
plt.plot(history.history['accuracy'], label='train_acc')
plt.plot(history.history['val_accuracy'], label='val_acc')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.title('Accuracy')
plt.show()

典型的な過学習のパターンは:

  • train_loss が下降し続ける
  • val_loss が途中から上昇または横ばい
  • train_acc − val_acc の差が拡大する

学習曲線

損失グラフ

過学習 損失グラフ

精度グラフ

過学習 精度グラフ

訓練精度、訓練損失はそれぞれ改善していますが、検証精度、検証損失が伸び悩んでいることがわかります。

混同行列でクラス毎の過学習を確認する

# 混同行列(例)
from sklearn.metrics import confusion_matrix
import seaborn as sns

y_pred = np.argmax(model.predict(x_test), axis=1)
cm = confusion_matrix(y_test, y_pred)

plt.figure(figsize=(8,6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Confusion Matrix')
plt.show()

特定クラスだけ誤りが多い場合、クラス不均衡やモデルの偏りを疑います。過学習していると、一部クラスでだけ高精度に学習している、というパターンも見られます。

過学習 混同行列

混同行列(Confusion Matrix)の読み方

混同行列(Confusion Matrix)は、クラスごとの予測の正解/間違いを一覧で確認できる表です。 CIFAR-10 のような多クラス分類では、過学習や偏りを見抜くために非常に役立ちます。

基本の見方

  • 行(row)=実際の正解ラベル
  • 列(column)=モデルの予測結果

つまり、対角線(左上→右下)は「正しく分類された数」です。 対角線から離れるほど、誤分類されていることを意味します。

過学習を混同行列で見つけるポイント

  • 特定のクラスだけ分類精度が極端に悪い
  • 似ているクラス(例:cat と dog)がまとめて誤分類されている
  • 訓練 accuracy が高いのに、混同行列の対角線が弱い

これらが見られる場合、モデルは「訓練データには強いが未知データを正しく一般化できていない(=過学習)」と判断できます。

実用的な「過学習判定ルール(目安)」

  • 訓練精度 − 検証精度 ≥ 0.05(5%) が継続的に見られる → 過学習の疑い。
  • val_loss が一定期間(例: 3〜5 epoch)で増加傾向 → 過学習が進んでいる可能性。
  • ホールドアウト評価で性能が大幅に落ちる → 過学習確定に近い。
  • ただし閾値はデータ・タスク依存。厳密には複数回実行して統計的に確認(n=3〜10)することを推奨。

過学習を防ぐための実践的対策(チェックリスト)

  1. データ拡張(Data Augmentation):回転・平行移動・色合い変更などで汎化能力を高める。
  2. ドロップアウト(Dropout)やバッチ正規化(BatchNorm):過学習を抑制。
  3. L2正則化(Weight Decay):大きすぎる重みを抑える。
  4. EarlyStopping:検証データで改善しないときに学習を止める。
  5. ReduceLROnPlateau:停滞時に学習率を下げる。
  6. モデルの縮小:パラメータ数を減らして単純なモデルにする。
  7. データを増やす(追加データ・ラベリング)

簡単に試せる“正則化あり”のコード例

# 改善版:DataAugment + Dropout + EarlyStopping
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau

datagen = ImageDataGenerator(
    rotation_range=15, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True
)
datagen.fit(x_train)

def build_reg_model():
    model = keras.Sequential([
        layers.Input(shape=(32,32,3)),
        layers.Conv2D(64,3,activation='relu',padding='same'),
        layers.MaxPooling2D(),
        layers.Conv2D(128,3,activation='relu',padding='same'),
        layers.Flatten(),
        layers.Dense(256, activation='relu'),
        layers.Dropout(0.5),
        layers.Dense(10, activation='softmax')
    ])
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    return model

model_reg = build_reg_model()
callbacks = [
    EarlyStopping(monitor='val_loss', patience=8, restore_best_weights=True),
    ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-6)
]

history_reg = model_reg.fit(
    datagen.flow(x_train, y_train, batch_size=128),
    validation_data=(x_test, y_test),
    epochs=50,
    callbacks=callbacks
)
    

TensorFlow / Keras でモデルを学習させていると、以下のような警告が表示されることがあります:

/usr/local/lib/python3.12/dist-packages/keras/src/trainers/data_adapters/py_dataset_adapter.py:121: 
UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. 
`**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. 
Do not pass these arguments to `fit()`, as they will be ignored.

初めて見ると原因が分かりにくく不安になりますが、この警告は 自作のデータセットを定義した時だけ意味を持つ ものです。 多くのケースでは “無視して問題なし” です。

/usr/local/lib/python3.12/dist-packages/keras/src/trainers/data_adapters/py_dataset_adapter.py:121: UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. `**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. Do not pass these arguments to `fit()`, as they will be ignored.
  self._warn_if_super_not_called()
Epoch 1/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 35s 77ms/step - accuracy: 0.2637 - loss: 2.0746 - val_accuracy: 0.4693 - val_loss: 1.4384 - learning_rate: 0.0010
Epoch 2/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 71ms/step - accuracy: 0.4520 - loss: 1.5204 - val_accuracy: 0.5414 - val_loss: 1.2742 - learning_rate: 0.0010
Epoch 3/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 78ms/step - accuracy: 0.4937 - loss: 1.4157 - val_accuracy: 0.5895 - val_loss: 1.1379 - learning_rate: 0.0010
Epoch 4/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 31s 80ms/step - accuracy: 0.5312 - loss: 1.3151 - val_accuracy: 0.6136 - val_loss: 1.0840 - learning_rate: 0.0010
Epoch 5/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 31s 80ms/step - accuracy: 0.5452 - loss: 1.2811 - val_accuracy: 0.6382 - val_loss: 1.0255 - learning_rate: 0.0010
Epoch 6/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 31s 80ms/step - accuracy: 0.5701 - loss: 1.2127 - val_accuracy: 0.6458 - val_loss: 1.0099 - learning_rate: 0.0010
Epoch 7/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 41s 80ms/step - accuracy: 0.5830 - loss: 1.1820 - val_accuracy: 0.6493 - val_loss: 1.0180 - learning_rate: 0.0010
Epoch 8/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 77ms/step - accuracy: 0.5945 - loss: 1.1482 - val_accuracy: 0.6580 - val_loss: 0.9750 - learning_rate: 0.0010
Epoch 9/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 31s 80ms/step - accuracy: 0.6061 - loss: 1.1172 - val_accuracy: 0.6817 - val_loss: 0.9210 - learning_rate: 0.0010
Epoch 10/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 77ms/step - accuracy: 0.6070 - loss: 1.1167 - val_accuracy: 0.6839 - val_loss: 0.9056 - learning_rate: 0.0010
Epoch 11/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 77ms/step - accuracy: 0.6232 - loss: 1.0736 - val_accuracy: 0.6875 - val_loss: 0.8864 - learning_rate: 0.0010
Epoch 12/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6248 - loss: 1.0647 - val_accuracy: 0.6962 - val_loss: 0.8673 - learning_rate: 0.0010
Epoch 13/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.6341 - loss: 1.0487 - val_accuracy: 0.6979 - val_loss: 0.8659 - learning_rate: 0.0010
Epoch 14/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.6386 - loss: 1.0351 - val_accuracy: 0.7047 - val_loss: 0.8570 - learning_rate: 0.0010
Epoch 15/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 72ms/step - accuracy: 0.6405 - loss: 1.0285 - val_accuracy: 0.6970 - val_loss: 0.8631 - learning_rate: 0.0010
Epoch 16/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 72ms/step - accuracy: 0.6412 - loss: 1.0297 - val_accuracy: 0.7025 - val_loss: 0.8692 - learning_rate: 0.0010
Epoch 17/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6502 - loss: 0.9888 - val_accuracy: 0.7087 - val_loss: 0.8382 - learning_rate: 0.0010
Epoch 18/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 73ms/step - accuracy: 0.6535 - loss: 0.9839 - val_accuracy: 0.7017 - val_loss: 0.8611 - learning_rate: 0.0010
Epoch 19/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6584 - loss: 0.9741 - val_accuracy: 0.7137 - val_loss: 0.8342 - learning_rate: 0.0010
Epoch 20/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.6641 - loss: 0.9664 - val_accuracy: 0.7254 - val_loss: 0.7898 - learning_rate: 0.0010
Epoch 21/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 73ms/step - accuracy: 0.6599 - loss: 0.9607 - val_accuracy: 0.7250 - val_loss: 0.7796 - learning_rate: 0.0010
Epoch 22/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 75ms/step - accuracy: 0.6694 - loss: 0.9429 - val_accuracy: 0.7274 - val_loss: 0.7791 - learning_rate: 0.0010
Epoch 23/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 73ms/step - accuracy: 0.6688 - loss: 0.9416 - val_accuracy: 0.7190 - val_loss: 0.8139 - learning_rate: 0.0010
Epoch 24/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 72ms/step - accuracy: 0.6814 - loss: 0.9175 - val_accuracy: 0.7366 - val_loss: 0.7627 - learning_rate: 0.0010
Epoch 25/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6797 - loss: 0.9127 - val_accuracy: 0.7351 - val_loss: 0.7698 - learning_rate: 0.0010
Epoch 26/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.6853 - loss: 0.9007 - val_accuracy: 0.7429 - val_loss: 0.7489 - learning_rate: 0.0010
Epoch 27/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 73ms/step - accuracy: 0.6823 - loss: 0.9066 - val_accuracy: 0.7170 - val_loss: 0.8393 - learning_rate: 0.0010
Epoch 28/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.6863 - loss: 0.8988 - val_accuracy: 0.7381 - val_loss: 0.7720 - learning_rate: 0.0010
Epoch 29/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 73ms/step - accuracy: 0.6877 - loss: 0.8964 - val_accuracy: 0.7403 - val_loss: 0.7443 - learning_rate: 0.0010
Epoch 30/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6906 - loss: 0.8869 - val_accuracy: 0.7232 - val_loss: 0.8073 - learning_rate: 0.0010
Epoch 31/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 78ms/step - accuracy: 0.6890 - loss: 0.8883 - val_accuracy: 0.7496 - val_loss: 0.7313 - learning_rate: 0.0010
Epoch 32/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 77ms/step - accuracy: 0.6946 - loss: 0.8755 - val_accuracy: 0.7523 - val_loss: 0.7120 - learning_rate: 0.0010
Epoch 33/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 78ms/step - accuracy: 0.6993 - loss: 0.8661 - val_accuracy: 0.7331 - val_loss: 0.7905 - learning_rate: 0.0010
Epoch 34/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.6949 - loss: 0.8680 - val_accuracy: 0.7269 - val_loss: 0.8186 - learning_rate: 0.0010
Epoch 35/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 77ms/step - accuracy: 0.7015 - loss: 0.8561 - val_accuracy: 0.7527 - val_loss: 0.7224 - learning_rate: 0.0010
Epoch 36/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 75ms/step - accuracy: 0.7143 - loss: 0.8226 - val_accuracy: 0.7569 - val_loss: 0.7176 - learning_rate: 5.0000e-04
Epoch 37/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 30s 76ms/step - accuracy: 0.7165 - loss: 0.8066 - val_accuracy: 0.7528 - val_loss: 0.7273 - learning_rate: 5.0000e-04
Epoch 38/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.7201 - loss: 0.8088 - val_accuracy: 0.7562 - val_loss: 0.7218 - learning_rate: 5.0000e-04
Epoch 39/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 28s 73ms/step - accuracy: 0.7270 - loss: 0.7838 - val_accuracy: 0.7519 - val_loss: 0.7299 - learning_rate: 2.5000e-04
Epoch 40/50
391/391 ━━━━━━━━━━━━━━━━━━━━ 29s 74ms/step - accuracy: 0.7270 - loss: 0.7779 - val_accuracy: 0.7481 - val_loss: 0.7464 - learning_rate: 2.5000e-04

損失グラフ

過学習対策済み損失グラフ

精度グラフ

過学習対策済み精度グラフ

訓練精度、訓練損失はそれぞれ改善していると同時に、検証精度、検証損失も改善していることがわかります。

最後に:実験メモと注意点

  • 同じ条件でもシードやミニバッチの順序で結果は変わります。厳密な結論を出すには複数回実行して比較してください(n=3〜10)。
  • 判定ルール(閾値)はタスクごとに調整してください。画像認識と自然言語処理では基準が異なり得ます。
  • 本番デプロイではホールドアウト評価/交差検証を必ず行い、過学習の抑制策を組み込むことを推奨します。