KerasでOptimizerを比較!SGD・Adam・RMSpropの精度と学習速度を検証

2025年6月8日日曜日

Adam Google Colab Keras Optimizer RMSprop SGD 画像分類

X f B! P L
アイキャッチ画像 異なるOptimizer(SGD, Adam, RMSprop)の比較実験!

はじめに:Optimizer(SGD・Adam・RMSprop)を比較する意義

ニューラルネットワークでモデル精度や収束速度に強く影響するのがオプティマイザ(Optimizer)です。 本記事では代表的な3種類、SGD・Adam・RMSpropをMNIST画像分類タスクで比較し、 「どのOptimizerがいつ、どう優れるか」を視覚化でわかりやすく解説します。 機械学習初心者から中級者まで、オプティマイザ選定に悩んでいる方に役立つ内容です。

使用環境と前提条件:Google Colab + TensorFlow/Kerasで実験

  • 実行環境:Google Colab(GPU推奨)
  • ライブラリ:TensorFlow / Keras(バージョン指定推奨)

Colabなら初期セットアップ不要で、すぐにGPUを使った深層学習実験を始められます。 本手順はすべてブラウザ上で再現可能です。

データ準備:MNIST手書き数字データセットの読み込みと前処理

from tensorflow import keras
from tensorflow.keras import layers

# MNISTデータの読み込み
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# 正規化とチャンネル次元追加
x_train = x_train.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0
x_train = x_train[..., None]
x_test = x_test[..., None]

MNISTは機械学習入門で定番のデータセットです。ここでは読み込みから正規化、形状変換までを一括処理しています。

モデル定義:汎用CNNの構築関数(Optimizer を引数で切替可能)

def create_model(optimizer):
    model = keras.Sequential([
        layers.Input(shape=(28, 28, 1)),
        layers.Conv2D(32, 3, activation='relu'),
        layers.MaxPooling2D(),
        layers.Flatten(),
        layers.Dense(64, activation='relu'),
        layers.Dense(10, activation='softmax')
    ])

    model.compile(
        optimizer=optimizer,
        loss="sparse_categorical_crossentropy",
        metrics=["accuracy"]
    )
    return model

このモデル定義関数では、Optimizerを引数として渡す設計にすることで、 後続の評価処理がシンプルで汎用的になります。

実験内容:SGD・Adam・RMSprop各Optimizerで学習比較

optimizers = {
    "SGD": keras.optimizers.SGD(),
    "Adam": keras.optimizers.Adam(),
    "RMSprop": keras.optimizers.RMSprop()
}

results = {}
histories = {}

for name, opt in optimizers.items():
    print(f"Training with {name}...")
    model = create_model(opt)
    histories[name] = model.fit(
        x_train, y_train,
        validation_split=0.2,
        epochs=5
    )
    test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
    results[name] = {
        "val_acc": histories[name].history["val_accuracy"][-1],
        "test_acc": test_acc
    }

各Optimizerを用いて学習し、最終の検証精度とテスト精度も合わせて記録します。 比較のための再現性が確保されています。

学習ログ:各Optimizerの収束速度と精度の推移(5エポック)

Training with SGD...
Epoch 1/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 7s 4ms/step - accuracy: 0.7468 - loss: 0.9370 - val_accuracy: 0.9219 - val_loss: 0.2655
Epoch 2/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9203 - loss: 0.2698 - val_accuracy: 0.9400 - val_loss: 0.2035
Epoch 3/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9397 - loss: 0.2011 - val_accuracy: 0.9490 - val_loss: 0.1741
Epoch 4/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9499 - loss: 0.1679 - val_accuracy: 0.9525 - val_loss: 0.1604
Epoch 5/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 0.9568 - loss: 0.1424 - val_accuracy: 0.9572 - val_loss: 0.1406
Training with Adam...
Epoch 1/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 7s 3ms/step - accuracy: 0.8911 - loss: 0.3793 - val_accuracy: 0.9787 - val_loss: 0.0736
Epoch 2/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9814 - loss: 0.0628 - val_accuracy: 0.9821 - val_loss: 0.0569
Epoch 3/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9873 - loss: 0.0394 - val_accuracy: 0.9821 - val_loss: 0.0588
Epoch 4/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9917 - loss: 0.0259 - val_accuracy: 0.9846 - val_loss: 0.0544
Epoch 5/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9948 - loss: 0.0172 - val_accuracy: 0.9838 - val_loss: 0.0565
Training with RMSprop...
Epoch 1/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 6s 3ms/step - accuracy: 0.8923 - loss: 0.3632 - val_accuracy: 0.9778 - val_loss: 0.0769
Epoch 2/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9789 - loss: 0.0682 - val_accuracy: 0.9824 - val_loss: 0.0612
Epoch 3/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9875 - loss: 0.0420 - val_accuracy: 0.9843 - val_loss: 0.0556
Epoch 4/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 0.9914 - loss: 0.0289 - val_accuracy: 0.9862 - val_loss: 0.0533
Epoch 5/5
1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.9927 - loss: 0.0218 - val_accuracy: 0.9858 - val_loss: 0.0564

ログには各Epochごとの訓練精度、検証精度、損失の推移が表示されています。 SGD → 安定だが収束が緩やか
Adam → 初動が非常に速く精度向上が大きい
RMSprop → 高精度ながら滑らかな収束という傾向が見られました。

可視化:検証精度と損失のグラフで性能比較

以下のコードで学習結果と精度と損失をグラフ化します

import matplotlib.pyplot as plt

for name, opt in optimizers.items():
    print(f"{name}: {results[name]}")

for name, history in histories.items():
    plt.plot(history.history['val_accuracy'], label=f'{name} val_accuracy')

plt.title('Validation Accuracy per Epoch')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.show()

for name, history in histories.items():
    plt.plot(history.history['val_loss'], label=f'{name} val_loss')

plt.title('Validation Loss per Epoch')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.show()

グラフ化により、収束の速さや安定性、過学習の兆候などが視覚的に把握できます。

学習結果の確認

SGD: {'val_acc': 0.984416663646698, 'test_acc': 0.9605000019073486}
Adam: {'val_acc': 0.984416663646698, 'test_acc': 0.9846000075340271}
RMSprop: {'val_acc': 0.984416663646698, 'test_acc': 0.9858999848365784}

精度と損失のグラフ確認

精度グラフ

オプティマイザごとの精度グラフ

損失グラフ

オプティマイザごとの損失グラフ

結果比較:Optimizer別パフォーマンスまとめ表

Optimizer最終EpochのVal AccuracyTest Accuracy特性
SGD~0.957~0.960安定だが収束緩やか
Adam~0.984~0.985高速収束、やや揺れ
RMSprop~0.986~0.986高精度、安定

各オプティマイザの詳細分析

◆ SGD(確率的勾配降下法)

  • 初期精度は低め(0.74)が、エポックごとに安定して向上。
  • 最終的に val_accuracy = 95.7% に到達。
  • 学習率に敏感だが、ロスが順調に下がり過学習は少ない。
  • 安定型で、長期訓練向け。

◆ Adam(適応的モーメンタム)

  • 初回から精度が非常に高く(0.89→0.98)急速に収束。
  • val_accuracy ≒ 98.3% と非常に高い。
  • ただし val_loss にやや揺れがあり、過学習傾向あり。
  • 学習初期で効果大、ハイパラ調整も少なめ。

◆ RMSprop(勾配平方平均調整)

  • Adamに近いが、学習曲線がやや滑らか。
  • val_accuracy ≒ 98.6% と最も良好。
  • やや安定性が高く、過学習にも強め。
  • 画像認識など汎用的におすすめ。

総合比較表

Optimizer 学習速度 汎化性能 安定性 コメント
SGD △ 遅め 安定・堅実。微調整に向く
Adam ◎ 非常に速い △ やや不安定 初期学習や高速トライに
RMSprop ◎ 速い 高性能・汎用向け

まとめ:タスクに応じたOptimizer選定のポイント

本実験ではAdamは収束速度重視、RMSpropは安定性と高精度、SGDは堅実性といった傾向が確認できました。 タスクによっては以下を意識すると効果的です:

  • 高速初期収束を狙う→ Adam
  • 安定した精度重視→ RMSprop
  • 細かい調整・過学習対策→ SGD

今後は学習率スケジューラやEarlyStoppingとの併用もおすすめです。次回記事で詳しく解説予定です!

おすすめ記事:Optimizer・EarlyStopping・ハイパーパラメータ自動調整

このブログを検索

このブログのまとめページ

自己紹介

はじめまして、機械学習を独学中のSHOU TAKEと申します。本ブログでは、Python・Keras・Google Colabを活用した画像分類やニューラルネットワークの実験記事を中心に発信しています。初学者の方にも分かりやすく、学んだことをそのまま実験形式でまとめるスタイルです。これまで取り組んだテーマには、学習率やOptimizerの比較、Batch Sizeの検証、事前学習の活用などがあります。ご質問やご感想は、お問い合わせフォームからお気軽にどうぞ。

お問い合わせフォーム

名前

メール *

メッセージ *

プライバシーポリシー

QooQ