💨

Deep Learning資格試験 深層学習 最適化アルゴリズム

2022/01/25に公開

はじめに

日本ディープラーニング協会の Deep Learning 資格試験(E 資格)の受験に向けて、調べた内容をまとめていきます。

勾配降下法

特徴

  • 目的関数が最小となるパラメータを勾配表によって探す。

  • 目的関数が各パラメータによって微分できる必要がある。

  • メリット

    • データが冗⻑な場合の計算コストの軽減
    • 望まない局所極小解に収束するリスクの軽減
    • オンライン学習ができる

計算式

学習率:\varepsilon

\begin{aligned} w^{(t+1)} = w^{(t)} - \varepsilon \nabla E \end{aligned}

確率的勾配降下法(SDG)

  • 無作為に選び出されたデータを用いて行う勾配降下法である。

コード

lr            学習率(learning rate)(小数)
params        学習するパラメータ(行列)
grads         パラメータの勾配(行列)
python
class SGD:

    """確率的勾配降下法(Stochastic Gradient Descent)"""

    def __init__(self, lr=0.01):
        # 学習率
        self.lr = lr

    def update(self, params, grads):
        for key in params.keys():
            params[key] -= self.lr * grads[key]

ミニバッチ勾配降下法

  • 無作為に選び出された複数のデータを用いて行う勾配降下法である。

モメンタム

特徴

  • 誤差をパラメータで微分したものと学習率の積を減算した後、現在の重みに前回の重みを減算した値と慣性の積を加算する

  • メリット

    • 局所的最適解にはならず、大域的最適解となる。
    • 谷間についてから最も低い位置(最適値)にいくまでの時間が早い。

計算式

学習率:\varepsilon
慣性:\mu

\begin{align} V_t &= \mu V_{t-1} - \varepsilon \nabla E \\[8px] w^{(t+1)} &= w^{(t)} + V_t \end{align}

コード

lr            学習率(learning rate)(小数)
params        学習するパラメータ(行列)
grads         パラメータの勾配(行列)
momentum      慣性項の強さを決める係数(0~1)
v             前回の重み
python
class Momentum:
    def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None

    def update(self, params, grads):
        # 初回の初期値設定
        if self.v is None:
            self.v = {}
            for key, val in params.items():
                self.v[key] = np.zeros_like(val)

        for key in params.keys():
            # 式(1)の処理
            self.v[key] = self.momentum*self.v[key] - self.lr*grads[key]
            # 式(2)の処理
            params[key] += self.v[key]

AdaGrad

特徴

  • 誤差をパラメータで微分したものと再定義した学習率の積を減算する。

  • メリット

    • 勾配の緩やかな斜面に対して、最適値に近づける。
  • デメリット

    • 学習率が徐々に小さくなるので、鞍点問題を引き起こす(局所最適解から抜け出せない)事があった。

計算式

任意な値:\theta

\begin{align} h_0 &= \theta \\[8px] h_t &= h_{t-1} + (\nabla E)^2 \\[8px] w^{(t+1)} &= w^{(t)} - \varepsilon \frac{1}{\sqrt{h_t}+\theta} \nabla E \end{align}

コード

lr            学習率(learning rate)(小数)
params        学習するパラメータ(行列)
grads         パラメータの勾配(行列)
h             学習のたびに勾配の2乗ずつ増加するパラメータ毎の値(行列)
python
class AdaGrad:
    def __init__(self, lr=0.01):
        self.lr = lr
        self.h = None

    def update(self, params, grads):
        # 初回の初期値設定
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                # 式(3)の処理
                self.h[key] = np.zeros_like(val)

        for key in params.keys():
            # 式(4)の処理
            self.h[key] += grads[key] * grads[key]
            # 式(5)の処理
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

RMSrop

特徴

  • 誤差をパラメータで微分したものと再定義した学習率の積を減算する。

  • AdaGrad よりも最近の勾配ほど強く影響する。

  • メリット

    • 局所的最適解にはならず、大域的最適解となる。
    • ハイパーパラメータの調整が必要な場合が少ない

計算式

0 ~ 1 の値で昔の勾配情報をどの程度使うか:\alpha
\alphaが小さくなると、昔の勾配情報を無視する

\begin{align} h_t &= \alpha h_{t-1} + (1 -\alpha)(\nabla E)^2 \\[8px] w^{(t+1)} &= w^{(t)} - \varepsilon \frac{1}{\sqrt{h_t}+\theta} \nabla E \end{align}

コード

lr            学習率(learning rate)(小数)
decay_rate    0 ~ 1 の値で昔の勾配情報をどの程度使うか
params        学習するパラメータ(行列)
grads         パラメータの勾配(行列)
h             学習のたびに勾配の2乗ずつ増加するパラメータ毎の値(行列)
pthon
class RMSprop:
    def __init__(self, lr=0.01, decay_rate = 0.99):
        self.lr = lr
        self.decay_rate = decay_rate
        self.h = None

    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros_like(val)

        for key in params.keys():
            # 式(6)の処理
            self.h[key] *= self.decay_rate
            self.h[key] += (1 - self.decay_rate) * grads[key] * grads[key]
            # 式(7)の処理
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

Adam

特徴

  • モメンタムの、過去の勾配の指数関数的減衰平均

  • RMSProp の、過去の勾配の 2 乗の指数関数的減衰平均
    上記をそれぞれ孕んだ最適化アルゴリズムである。

  • メリット

    • モメンタムおよび RMSProp のメリットを孕んだアルゴリズムである。

計算式

\begin{align} \nu_{t} &= \beta_1\nu_{t-1} + (1-\beta_1)G \\ s_{t} &= \beta_2 s_{t-1} + (1-\beta_2)G^2 \\ w_t &= w_{t-1} - \alpha\frac{\nu_{t}}{\sqrt{s_t + \epsilon}} \end{align}

コード

python
class Adam:
    def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
        self.lr = lr
        self.beta1 = beta1
        self.beta2 = beta2
        self.iter = 0
        self.m = None
        self.v = None

    def update(self, params, grads):
        if self.m is None:
            self.m, self.v = {}, {}
            for key, val in params.items():
                self.m[key] = np.zeros_like(val)
                self.v[key] = np.zeros_like(val)

        self.iter += 1
        lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)

        for key in params.keys():
            # 式(8)の処理 (モメンタム)
            self.m[key] = self.beta1*self.m[key] + (1-self.beta1)*grads[key]
            unbias_m += (1 - self.beta1) * (grads[key] - self.m[key])
            # 式(9)の処理 (RMSrop)
            self.v[key] = self.beta2*self.v[key] + (1-self.beta2)*(grads[key]**2)
            unbisa_b += (1 - self.beta2) * (grads[key]*grads[key] - self.v[key])
            # 式(10)の処理
            params[key] -= self.lr * unbias_m / (np.sqrt(unbisa_b) + 1e-7)

参考

【決定版】スーパーわかりやすい最適化アルゴリズム -損失関数から Adam とニュートン法-
[AI 入門] ディープラーニングの仕組み ~その 4:最適化アルゴリズムを比較してみた~

ソースコードはゼロから作る Deep Learningから引用

Discussion