はじめに
Deep Learningは非常に強力なモデルを作れる一方で、
学習データに対して過剰に適合(過学習)することがあります。
これを防ぐために用いられる手法の一つが「正則化(Regularization)」です。
この記事では、Deep Learning初心者向けに、
正則化の基本概念とその代表的な手法である「L1正則化」「L2正則化」について解説し、
Pythonでの具体的な実装例を紹介します。
正則化とは
正則化とは、モデルの複雑さに制約を設けて過学習を防ぐための手法です。
Deep Learningモデルはパラメータ(重み)を多く持つため、
訓練データに対して非常に柔軟に適合できますが、
その結果、未知のデータに対する予測性能が落ちることがあります。
これが過学習です。
正則化は、モデルの重みにペナルティを与えることでモデルの複雑さを抑え、
一般化性能(未知データへの対応能力)を向上させます。
L1正則化
L1正則化(Lasso Regularization)は、
重みの絶対値の合計をペナルティ項として損失関数に加えます。
具体的には次のような損失関数となります。
$$\text{損失関数(L1)} = \text{元の損失関数} + \lambda \sum |w|$$
- $\lambda$:正則化係数(大きいほど正則化が強くなる)
- $\sum |w|$:全重みの絶対値の合計(L1ノルム)
L1正則化の特徴は、「重みが0になる」ことです。
これにより重要でない特徴量を自動的に選択(特徴選択)する効果があります。
L2正則化
L2正則化(Ridge Regularization)は、
重みの二乗の合計をペナルティ項として損失関数に加えます。
具体的には次のようになります。
$$\text{損失関数(L2)} = \text{元の損失関数} + \lambda \sum w^2$$
- $\lambda$:正則化係数(大きいほど正則化が強くなる)
- $\sum w^2$:全重みの二乗の合計(L2ノルム)
L2正則化は、全体の重みが小さくなるように調整します。
そのため、特徴選択の効果は弱いですが、過学習を抑える効果が高いです。
Deep LearningにおけるL2正則化
Deep Learningでは一般にL2正則化がよく利用されます。
特にニューラルネットワークは重みの数が非常に多いため、
過学習を防ぐためには適度なL2正則化が有効です。
Kerasを用いた具体的な実装例を示します。
Pythonでの実装例
import tensorflow as tf
from tensorflow.keras import layers, models, regularizers
# モデルの定義
model = models.Sequential([
layers.Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
layers.Dense(32, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()
上記のkernel_regularizer=regularizers.l2(0.01)
の部分で、
L2正則化を設定しています。
係数0.01
は調整が可能です。
大きくすると強力な正則化、小さくすると弱い正則化になります。
重みが大きいとモデルが複雑な理由
重みが大きくなると、モデルは特定の入力に強く反応するようになります。
その結果、微小な変化にも敏感に反応してしまい、
ノイズや偶然のパターンにも対応しようとします。
これが「複雑なモデル」となり、過学習を引き起こします。
逆に、重みを小さく抑えることで、入力に対して滑らかな反応を示し、ノイズに強くなります。
これにより一般化性能が向上します。
Pythonでの実装例(詳細版)
先ほどのモデルに対して、実際にデータを用いて学習する例を示します。
# データセットの準備(例として架空のデータ)
import numpy as np
# 入力データ(100サンプル、20特徴量)
X = np.random.rand(100, 20)
# 出力データ(2クラス分類)
y = np.random.randint(0, 2, 100)
# モデルの定義(L2正則化)
model = models.Sequential([
layers.Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
layers.Dense(32, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# モデルの学習
history = model.fit(X, y, epochs=20, batch_size=16, validation_split=0.2)
応用:各層で異なる重みを設定する
実際には各層で正則化の強さを調整できます。
例えば、入力層に近い層ほど弱く、
出力層に近い層ほど強く設定するといった方法もあります。
model = models.Sequential([
layers.Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
layers.Dense(32, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
layers.Dense(16, activation='relu', kernel_regularizer=regularizers.l2(0.1)),
layers.Dense(1, activation='sigmoid')
])
こうすることで、層ごとに適した複雑さを調整できます。
まとめ
この記事ではDeep Learning初心者向けに、
正則化の基本的な考え方と具体的な実装例を紹介しました。
- 正則化とは:過学習を防ぎ、一般化性能を向上させるための手法。
- L1正則化:特徴選択効果がある。
- L2正則化:一般的に利用され、モデルの重みを小さく保つ。
- Deep LearningにおいてはL2正則化が広く使われる。
- 層ごとに正則化の強さを調整することも可能。
実際のモデル開発時には、正則化係数を調整(チューニング)しながら、
モデルの性能を向上させましょう。