モデルの過学習を防ぐテクニック(正則化、ドロップアウト)
過学習(オーバーフィッティング)とは、モデルが訓練データに適合しすぎてしまい、未知のデータに対する予測性能が低下する状態です。訓練データでは高い精度を示していても、テストデータや実際の運用データで性能が落ちる場合は、過学習が疑われます。
過学習を防ぐためには、モデルの複雑さを抑え、特定のデータに依存しすぎないようにすることが重要です。代表的な方法として、正則化とドロップアウトがあります。
過学習を防ぐ仕組みを図で理解する

過学習とは
過学習は、モデルが訓練データの細かいノイズや偶然のパターンまで覚えてしまう状態です。
- 訓練データでは高い精度になる
- テストデータでは精度が下がる
- 未知のデータに弱くなる
- モデルが複雑すぎる場合に起こりやすい
正則化とは
正則化は、モデルの重みが大きくなりすぎないように制約を加える方法です。重みが大きくなりすぎると、モデルが訓練データに過度に適合しやすくなります。
正則化を行うことで、モデルを適度に単純に保ち、未知のデータに対する汎化性能を高めやすくなります。
L1正則化(Lasso)
L1正則化は、重みの絶対値にペナルティを加える方法です。不要な特徴量の重みを0にしやすいため、特徴量選択の効果もあります。
- 不要な特徴量を除外しやすい
- モデルをシンプルにできる
- 特徴量選択にも使える
Lasso回帰の実装例
from sklearn.linear_model import Lasso
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
# データのロード
data = load_diabetes()
X = data.data
y = data.target
# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.2,
random_state=42
)
# Lassoモデルの作成
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)
# モデルの性能評価
train_score = lasso.score(X_train, y_train)
test_score = lasso.score(X_test, y_test)
print(f"訓練データのスコア: {train_score:.3f}")
print(f"テストデータのスコア: {test_score:.3f}")
alphaは正則化の強さを表します。値が大きいほど強い正則化がかかります。
L2正則化(Ridge)
L2正則化は、重みの二乗にペナルティを加える方法です。L1正則化のように重みを0にしやすいわけではありませんが、全体の重みを小さく抑えることで、モデルを安定させます。
- 重みの極端な大きさを抑える
- すべての特徴量を活かしやすい
- モデルを安定させやすい
Ridge回帰の実装例
from sklearn.linear_model import Ridge
# Ridgeモデルの作成
ridge = Ridge(alpha=0.1)
ridge.fit(X_train, y_train)
# モデルの性能評価
train_score = ridge.score(X_train, y_train)
test_score = ridge.score(X_test, y_test)
print(f"訓練データのスコア: {train_score:.3f}")
print(f"テストデータのスコア: {test_score:.3f}")
Ridge回帰では、特徴量を残したまま重みを抑えるため、過学習を防ぎながら安定した予測を行いやすくなります。
L1正則化とL2正則化の違い
| 項目 | L1正則化(Lasso) | L2正則化(Ridge) |
|---|---|---|
| ペナルティ | 重みの絶対値 | 重みの二乗 |
| 重みが0になるか | なりやすい | なりにくい |
| 特徴量選択 | できる | 基本的にはできない |
| 特徴 | モデルをよりシンプルにしやすい | モデルを安定させやすい |
ドロップアウトとは
ドロップアウトは、主にニューラルネットワークで使われる過学習防止の手法です。学習中に一部のニューロンをランダムに無効化し、特定のニューロンに依存しすぎないようにします。
これにより、ネットワーク全体がより汎用的な特徴を学習しやすくなります。
- 学習中に一部のニューロンを無効化する
- 特定の経路への依存を防ぐ
- ニューラルネットワークの過学習を抑える
- 複数の弱いモデルを組み合わせるような効果がある
ドロップアウトの実装例
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
# データのロード
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# データの前処理
X_train = X_train.reshape(-1, 28 * 28) / 255.0
X_test = X_test.reshape(-1, 28 * 28) / 255.0
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
# モデルの作成
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(28 * 28,)))
model.add(Dropout(0.5))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
# モデルのコンパイル
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy']
)
# モデルの学習
model.fit(
X_train,
y_train,
epochs=10,
batch_size=128,
validation_split=0.2
)
Dropout(0.5)は、学習中に50%のニューロンをランダムに無効化する設定です。
正則化とドロップアウトの違い
| 項目 | 正則化 | ドロップアウト |
|---|---|---|
| 主な対象 | 回帰モデル、線形モデル、ニューラルネットワーク | ニューラルネットワーク |
| 考え方 | 重みに制約を加える | 一部のニューロンを無効化する |
| 目的 | モデルの複雑さを抑える | 特定のニューロンへの依存を防ぐ |
| 代表例 | L1正則化、L2正則化 | Dropout層 |
正則化の強さを調整する
正則化の効果は、alphaなどのハイパーパラメータによって変わります。強すぎるとアンダーフィッティングになり、弱すぎると過学習を防ぎきれないことがあります。
GridSearchCVによる調整例
from sklearn.model_selection import GridSearchCV
# 探索するalphaの候補
param_grid = {
'alpha': [0.01, 0.1, 1.0, 10.0]
}
# グリッドサーチ
grid_search = GridSearchCV(
Lasso(),
param_grid,
cv=5
)
grid_search.fit(X_train, y_train)
print("最適なalpha:", grid_search.best_params_)
複数の候補を比較することで、データに合った正則化の強さを選びやすくなります。
過学習を防ぐその他の方法
- データを増やす: 学習データを増やすことで、汎化性能を高めやすくなります。
- 早期終了: 検証データの性能が悪化し始めた時点で学習を止めます。
- モデルを単純にする: パラメータ数や層の数を減らします。
- 交差検証: 複数の分割で性能を確認し、過学習を見つけやすくします。