過学習とは?
過学習(オーバーフィッティング)とは、モデルが訓練データに過度に適合してしまい、未知データ(検証・テスト)で性能が落ちる現象、すなわちモデルの汎化能力が低い状態を指します。 今回は CIFAR-10 (32x32ピクセル)を使い、モデルのキャパシティに比べてデータ量が少ない状況を作り、過学習を意図的に再現して判定方法を確認します。
過学習を判定する代表的な方法(要点)
- 学習曲線(training / validation の loss と accuracy)を見る:典型的なサインは「train loss が下がり続ける一方で val loss が上がる」こと。
- train accuracy と val accuracy の乖離:差(gap)が明確に大きい(例: 0.05〜0.1 以上の場合は要注意、データ依存)。
- 混同行列(confusion matrix)でクラスごとの誤りを確認:特定クラスだけ過適合しているケースもある。
- ホールドアウト(未使用テスト)での評価:本当に過学習していればホールドアウトでの性能が低くなる。
- 学習率・損失の異常な振動:高学習率での振動が原因のことがある(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)することを推奨。
過学習を防ぐための実践的対策(チェックリスト)
- データ拡張(Data Augmentation):回転・平行移動・色合い変更などで汎化能力を高める。
- ドロップアウト(Dropout)やバッチ正規化(BatchNorm):過学習を抑制。
- L2正則化(Weight Decay):大きすぎる重みを抑える。
- EarlyStopping:検証データで改善しないときに学習を止める。
- ReduceLROnPlateau:停滞時に学習率を下げる。
- モデルの縮小:パラメータ数を減らして単純なモデルにする。
- データを増やす(追加データ・ラベリング)
簡単に試せる“正則化あり”のコード例
# 改善版: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)。
- 判定ルール(閾値)はタスクごとに調整してください。画像認識と自然言語処理では基準が異なり得ます。
- 本番デプロイではホールドアウト評価/交差検証を必ず行い、過学習の抑制策を組み込むことを推奨します。






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