Dropoutはなぜ必要?効果を実験で見てみよう

2025年6月1日日曜日

Google Colab Keras 画像分類

X f B! P L
Dropoutはなぜ必要?効果を実験で見てみよう アイキャッチ画像

はじめに

こんにちは、SHOU です!

ディープラーニングでは、モデルが訓練データに過剰に適応してしまい、未知のデータに対して性能が落ちる「過学習」が起こることがあります。その対策としてよく使われる手法のひとつが Dropout です。

本記事では、Dropoutの有無によってどれほど性能に差が出るかを、Kerasを使って実験してみます。

Dropoutとは?

Dropoutは、訓練中にランダムに一部のニューロンを無効化(0に)する正則化手法です。

  • ニューロンの co-adaptation(共同適応)を防ぐ
  • 汎化性能を向上させる(特定の重みだけに依存しない)
  • 「訓練時のみ」有効、推論時には全ノードを使用

データの準備

今回はMNISTの手書き数字画像を使います。

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
x_train = x_train[..., None]  # チャンネル次元を追加
x_test = x_test[..., None]

Dropoutなしのモデル

28×28のグレースケール画像(例:手書き数字画像) を入力として、10クラス分類(例:0~9の数字) を行うためのシンプルなCNN(畳み込みニューラルネットワーク)を定義します。

  1. 入力層:入力データの形を指定(高さ28 × 幅28、1チャンネルの白黒画像)
  2. 畳み込み層:3×3のフィルターを32個適用し、特徴マップを抽出
  3. プーリング層:2×2で、空間サイズを半分に縮小。位置情報の粗視化と計算量削減
  4. 平坦化層:3次元の特徴マップ(13×13×32)を1次元に変換して全結合層に渡す
  5. 全結合層(隠れ層):5408個の入力を128次元に圧縮(情報抽出)
  6. 出力層:10個のクラスに分類(0~9)

また、訓練では訓練データのうち 20% を検証データ(バリデーション)として使用し、全データを20回学習させて、Dropoutあり・なしで比較します。

以下が実際のコードです。

from tensorflow.keras import layers

model_no_dropout = keras.Sequential([
    layers.Input(shape=(28, 28, 1)),
    layers.Conv2D(32, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(10, activation='softmax')
])

model_no_dropout.compile(optimizer='adam',
                         loss='sparse_categorical_crossentropy',
                         metrics=['accuracy'])

history_no_dropout = model_no_dropout.fit(
    x_train, y_train, validation_split=0.2, epochs=20
)

Dropoutありのモデル

以下のDropout層を追加します。

layers.Dropout(0.5)
  • Dropout:訓練時にランダムにニューロンの出力を0にして、一部のユニットを「無効化」する層。
  • 0.5:50%の確率でユニットを無効化する、という意味です。

実際のコードは以下です:

from tensorflow.keras import layers

model_with_dropout = keras.Sequential([
    layers.Input(shape=(28, 28, 1)),
    layers.Conv2D(32, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5),  # ★ Dropout 層を追加
    layers.Dense(10, activation='softmax')
])

model_with_dropout.compile(optimizer='adam',
                           loss='sparse_categorical_crossentropy',
                           metrics=['accuracy'])

history_with_dropout = model_with_dropout.fit(
    x_train, y_train, validation_split=0.2, epochs=20
)

学習の様子を比較

Dropoutあり・なしの精度・損失を比較してみましょう。

import matplotlib.pyplot as plt

# 精度プロット
plt.plot(history_no_dropout.history['accuracy'], label='No Dropout Train Accuracy')
plt.plot(history_no_dropout.history['val_accuracy'], label='No Dropout Val Accuracy')
plt.plot(history_with_dropout.history['accuracy'], label='Dropout Train Accuracy')
plt.plot(history_with_dropout.history['val_accuracy'], label='Dropout Val Accuracy')
plt.title('Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

# 損失をプロット
plt.plot(history_no_dropout.history['loss'], label='No Dropout Train Loss')
plt.plot(history_no_dropout.history['val_loss'], label='No Dropout Val Loss')
plt.plot(history_with_dropout.history['loss'], label='Dropout Train Loss')
plt.plot(history_with_dropout.history['val_loss'], label='Dropout Val Loss')
plt.title('Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

以下が精度プロットしたものです。

以下が損失プロットしたものです。

結果からわかること

1. Dropoutなし:精度は高いが過学習が発生

Dropoutなしのモデルでは、学習が進むにつれて 訓練精度が1.0(100%)に達し、一見すると完璧なモデルに見えます。 しかし、検証損失(val_loss)が徐々に悪化していく様子が確認されました。

このパターンは典型的な過学習であり、モデルが訓練データに「暗記」的に適応してしまったことを示しています。

2. Dropoutあり:やや精度が下がるが安定性あり

Dropoutを使ったモデルでは、訓練精度は完全には達しませんが(最大でも約99.5%)、検証損失の推移が安定し、汎化性能が高いことが確認されました。

Dropoutによって、学習中にランダムにノードが無効化されることで、特定のノードへの依存が減り、 よりロバストで汎化能力のある学習が可能になります。


結論:Dropoutは汎化性能の向上に効果的

Dropoutを用いることで、バランスの取れたモデルが得られることがわかりました。

実務や未知のデータに強いモデルを作るためには、少しの精度を犠牲にしてでもDropoutを使う価値があると言えるでしょう。

まとめ

  • Dropoutは過学習の抑制に有効
  • 特に全結合層に追加するのが一般的
  • パラメータ(rate)は0.3〜0.5程度が多い

少ないデータや深いネットワークを使う場合は、Dropoutの導入を検討すると良いでしょう。

このブログを検索

自己紹介

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

お問い合わせフォーム

名前

メール *

メッセージ *

プライバシーポリシー

QooQ