目次[非表示]
はじめに
こんにちは、SHOUです。
以前ご紹介した以下の記事:
5エポック→40エポック!学習回数でAIの精度はどこまで伸びる?【Keras転移学習で検証】では、学習回数を増やすことで精度が上がることを確認しました。
しかし、学習を続けすぎると、ある問題が発生することがあります。それが過学習(オーバーフィッティング)です。
過学習とは、訓練データにだけ極端に適合してしまい、未知のデータ(テストデータ)への汎用性が低下する現象です。AIが「覚えすぎてしまう」状態とも言えます。
今回は、Kerasで実装可能なEarlyStopping(早期終了)という手法を使って、この過学習をどのように防げるかを試してみます。
学習の準備
Google Driveのマウント
学習用のデータを読み込むために、Google Driveをマウントします。
from google.colab import drive
drive.mount('/content/drive')
ベースモデルの作成(MNISTで事前学習)
まずはKerasのMNISTデータセットで、シンプルなベースモデルを作成・学習します。
import tensorflow as tf
from tensorflow import keras
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0
model = keras.Sequential([
keras.Input(shape=(28, 28, 1)),
keras.layers.Flatten(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# MNISTで事前学習
model.fit(x_train, y_train, epochs=5)
Dropoutによる過学習対策について
ベースモデルの構築時に、以下のように Dropout(0.2)
を設定しています:
keras.layers.Dropout(0.2)
この Dropout(ドロップアウト) 層は、学習時にランダムに20%のニューロンを無効化(出力をゼロ)することで、特定のニューロンへの依存を減らし、 過学習を防ぐために用いられます。
モデルが訓練データに過度に適合してしまうと、未知のデータに対する性能が低下する(=過学習)傾向があります。 Dropoutを使うことで、学習中にモデルがさまざまな経路を通って情報を伝えるようになり、より汎化性能の高いモデルが構築されやすくなります。
今回の実験では、DropoutとEarlyStoppingを組み合わせることで、過学習の抑制効果をより強化しています。
EarlyStoppingを導入した転移学習
画像データの読み込みと前処理
次に、独自の手書き画像データ(digits)を使って転移学習を行います。ここでは白地に黒文字の画像を黒地に白文字に変換しています。
from tensorflow.keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rescale=1./255,
preprocessing_function=lambda x: 1.0 - x, # 白黒反転
validation_split=0.2
)
train_generator = datagen.flow_from_directory(
'/content/drive/MyDrive/Colab/digits',
target_size=(28, 28),
color_mode='grayscale',
batch_size=32,
class_mode='sparse',
subset='training'
)
val_generator = datagen.flow_from_directory(
'/content/drive/MyDrive/Colab/digits',
target_size=(28, 28),
color_mode='grayscale',
batch_size=32,
class_mode='sparse',
subset='validation'
)
EarlyStoppingの設定と学習
from tensorflow.keras.callbacks import EarlyStopping
# EarlyStopping のコールバックを定義
early_stopping = EarlyStopping(
monitor='val_loss', # モニター対象(val_loss または val_accuracy)
patience=3, # 何エポック待つか(改善がなければ停止)
restore_best_weights=True # 最良モデルの重みを復元
)
# モデルの学習
history = model.fit(
train_generator,
epochs=40,
validation_data=val_generator,
callbacks=[early_stopping] # コールバックに渡す
)
val_lossを監視対象にした理由は、損失の方が過学習の兆候を早く捉えられるケースがあるためです。 精度(accuracy)では過学習を見逃す可能性もあるため、通常はval_lossを使うのが一般的です。
学習結果
40回学習するところを19回で終了しています。
- /usr/local/lib/python3.11/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/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 13s 5s/step - accuracy: 0.1172 - loss: 59.9990 - val_accuracy: 0.2500 - val_loss: 27.6637
- Epoch 2/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 8s 174ms/step - accuracy: 0.1823 - loss: 26.6123 - val_accuracy: 0.4000 - val_loss: 14.0175
- Epoch 3/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 175ms/step - accuracy: 0.2646 - loss: 18.4386 - val_accuracy: 0.2000 - val_loss: 18.6816
- Epoch 4/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 1s 146ms/step - accuracy: 0.2242 - loss: 19.3921 - val_accuracy: 0.4500 - val_loss: 12.4235
- Epoch 5/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 148ms/step - accuracy: 0.4187 - loss: 9.3592 - val_accuracy: 0.3000 - val_loss: 12.3827
- ・・・
- Epoch 15/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 144ms/step - accuracy: 0.6914 - loss: 0.7664 - val_accuracy: 0.6500 - val_loss: 1.1976
- Epoch 16/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 174ms/step - accuracy: 0.7948 - loss: 0.4655 - val_accuracy: 0.6500 - val_loss: 1.1874
- Epoch 17/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 145ms/step - accuracy: 0.7688 - loss: 0.4918 - val_accuracy: 0.5500 - val_loss: 1.2928
- Epoch 18/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 142ms/step - accuracy: 0.9302 - loss: 0.3289 - val_accuracy: 0.5500 - val_loss: 1.5007
- Epoch 19/40
- 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 199ms/step - accuracy: 0.9115 - loss: 0.3047 - val_accuracy: 0.5500 - val_loss: 1.4863
学習をプロット
import matplotlib.pyplot as plt
# 精度をプロット
plt.plot(history.history['accuracy'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.show()
# 損失をプロット
plt.plot(history.history['loss'])
plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.show()
精度のプロット
損失のプロット
予測
from tensorflow.keras.preprocessing import image
import numpy as np
img_path = '/content/drive/MyDrive/Colab/handwritten_digit.png'
img = image.load_img(img_path, target_size=(28, 28), color_mode='grayscale')
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0) / 255.0
img_array = 1.0 - img_array # ←★ 追加:白黒反転
prediction = model.predict(img_array)
print('予測ラベル:', np.argmax(prediction))
実行結果は以下です:
- 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 73ms/step
- 予測ラベル: 4
予測の結果、「4」と書かれた画像が「4」と認識されました。
今回のEarlyStoppingの導入により、必要以上に学習を続けず、汎用性のあるモデルを目指せた点は大きな成果です。
まとめ
- 過学習とは、「覚えすぎ」によって新しいデータに弱くなる現象
- EarlyStoppingを使うことで、過学習を防ぎ、より実用的なモデルが作れる
- 誤認識の原因は、データの多様性や前処理の精度にも関係する
AIの精度を高めるには、モデル構造だけでなく「いつ学習を止めるか」も重要なポイントです。今後はEarlyStoppingだけでなく、Fine-tuningやデータ拡張なども組み合わせて、さらに高精度なモデル構築にチャレンジしてみます。
参考リンク:
Keras公式:EarlyStoppingコールバック
0 件のコメント:
コメントを投稿