なぜDeep LearningではL2正則化が使われるのか？

# はじめに

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での実装例

```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での実装例（詳細版）

先ほどのモデルに対して、実際にデータを用いて学習する例を示します。

```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)
```

---

# 応用：各層で異なる重みを設定する

実際には各層で正則化の強さを調整できます。

例えば、入力層に近い層ほど弱く、
出力層に近い層ほど強く設定するといった方法もあります。

```python
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正則化が広く使われる。**
- **層ごとに正則化の強さを調整することも可能。**

実際のモデル開発時には、正則化係数を調整（チューニング）しながら、
モデルの性能を向上させましょう。