第3章:学習アルゴリズム

勾配降下法、誤差逆伝播法、学習ダイナミクスを理解する

📖 読了時間: 35-40分 💻 コード例: 9個 📝 演習: 7問 📊 難易度: 中級
この章では、ニューラルネットワークがデータからどのように学習するかを学びます。勾配降下法による最適化、勾配計算のための誤差逆伝播法、ミニバッチ学習戦略、そして学習進捗のモニタリングと可視化の技術を理解します。

学習目標

1. 勾配降下法(Gradient Descent)

1.1 最適化の基本概念

最適化とは、目的関数を最小化(または最大化)するパラメータ値を見つけるプロセスです。ディープラーニングでは、損失関数を最小化する重みとバイアスを見つけたいのです。

最適化問題は次のように書けます:

$$\boldsymbol{\theta}^* = \arg\min_{\boldsymbol{\theta}} \mathcal{L}(\boldsymbol{\theta})$$

1.2 バッチ勾配降下法

勾配降下法は、勾配(最急上昇方向)の反対方向にパラメータを更新する反復アルゴリズムです。

更新則

$$\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta \nabla_{\boldsymbol{\theta}} \mathcal{L}(\boldsymbol{\theta})$$

ここで:

import numpy as np

def gradient_descent_demo():
    """
    二次関数での勾配降下法デモ
    f(x) = x^2, 最小値は x = 0
    """
    x = 5.0  # 初期点
    learning_rate = 0.1
    history = [x]

    for i in range(20):
        gradient = 2 * x  # df/dx = 2x
        x = x - learning_rate * gradient
        history.append(x)

        if i < 5 or i == 19:
            print(f"反復 {i+1}: x = {x:.6f}, f(x) = {x**2:.6f}")

    return history

print("f(x) = x^2 での勾配降下法")
print("=" * 40)
history = gradient_descent_demo()

1.3 勾配の幾何学的意味

勾配 $\nabla \mathcal{L}$ は損失関数の最急上昇方向を指すベクトルです。したがって、損失を減少させるには反対方向に移動します。

勾配の重要な性質

2. 誤差逆伝播法(Backpropagation)

2.1 連鎖律(Chain Rule)の復習

連鎖律により合成関数の微分が計算できます。$y = f(g(x))$ のとき:

$$\frac{dy}{dx} = \frac{dy}{dg} \cdot \frac{dg}{dx}$$

2.2 出力層から入力層への勾配伝播

誤差逆伝播法は、誤差をネットワークの後方に伝播させることで勾配を効率的に計算するアルゴリズムです。

2.3 各層での勾配計算

ReLU活性化を持つ全結合層の場合:

順伝播

逆伝播

3. ミニバッチ学習とSGD

3.1 バッチサイズの影響

バッチタイプ サイズ 勾配品質 速度 メモリ
バッチGD 全データ 最も正確 更新が遅い 高い
ミニバッチ 32-256 良いバランス 速い 中程度
SGD 1 非常にノイジー 最速の更新 低い

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

SGDは一度に単一のサンプル(または小さなバッチ)を使用してパラメータを更新し、局所最小値からの脱出を助けるノイズを導入します。

3.3 モメンタム

モメンタムは一貫した勾配方向に速度ベクトルを蓄積することでSGDを加速します。

更新則

$$\mathbf{v} \leftarrow \beta \mathbf{v} + (1-\beta) \nabla_{\boldsymbol{\theta}} \mathcal{L}$$

$$\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta \mathbf{v}$$

ここで $\beta$(通常0.9)はモメンタム係数です。

4. 学習率とエポック数

4.1 学習率の選択

学習率 $\eta$ は最も重要なハイパーパラメータの一つです。

学習率 挙動 症状
小さすぎる 収束が遅い 損失がゆっくり減少
適切 スムーズに収束 損失が安定して減少
大きすぎる オーバーシュート 損失が振動または発散

4.2 エポック数の決定

エポックとは、学習データ全体を1回通過することです。

4.3 学習曲線の解釈

学習曲線は、学習反復またはエポックに対する損失(および/または精度)をプロットします。

5. 学習の可視化

5.1 損失関数の推移

import numpy as np

class TrainingHistory:
    """学習メトリクスの追跡と保存"""

    def __init__(self):
        self.train_loss = []
        self.val_loss = []
        self.train_acc = []
        self.val_acc = []

    def log(self, train_loss, val_loss=None, train_acc=None, val_acc=None):
        self.train_loss.append(train_loss)
        if val_loss is not None:
            self.val_loss.append(val_loss)
        if train_acc is not None:
            self.train_acc.append(train_acc)
        if val_acc is not None:
            self.val_acc.append(val_acc)

    def summary(self):
        print("\n学習サマリー:")
        print(f"  最終訓練損失: {self.train_loss[-1]:.4f}")
        if self.val_loss:
            print(f"  最終検証損失: {self.val_loss[-1]:.4f}")

5.2 訓練/検証損失の比較

訓練損失と検証損失を比較することで:

演習問題

演習1:勾配チェックの実装

問題:誤差逆伝播法が正しいことを検証するための数値勾配チェックを実装してください。

演習2:学習率ファインダー

問題:最適な学習率を見つけるための学習率ファインダーを実装してください。

演習3:モメンタムの変種

問題:標準的なモメンタムとNesterov加速勾配(NAG)を実装し比較してください。

演習4:バッチサイズ実験

問題:バッチサイズ[1, 8, 32, 128, 全バッチ]で同じネットワークを訓練し比較してください。

演習5:早期終了

問題:検証損失を監視し、改善がなければ訓練を停止する早期終了を実装してください。

演習6:勾配クリッピング

問題:勾配爆発を防ぐための勾配クリッピングを実装してください。

演習7:XOR問題での訓練

問題:XOR問題を解くニューラルネットワークを訓練してください。

まとめ

この章では、ニューラルネットワークがどのように学習するかを学びました:

次章の予告:第4章では、正則化手法(L1、L2、Dropout、Batch Normalization)と、モデルの汎化と学習の安定性を向上させる高度な最適化アルゴリズム(Adam、RMSprop)を学びます。

免責事項