誤差逆伝搬法の計算 (1)

1入力、1出力ニューラルネットワークを用いた誤差逆伝搬法算出について

本チュートリアルでは誤差逆伝搬法の算出について紹介します。どこの変数を用いて算出しているかをより直感的に理解いただくために、まずはシンプルな例をもとに紹介します。

誤差逆伝搬法は重みを更新する際に使用する計算方法です。この計算により、ニューラルネットワークは目標とする非線形関数を学習することが可能です。本チュートリアルでは入力層にて1ユニット、隠れ層にて2ユニット、出力層にて1ユニットで構成された3層のニューラルネットワークと回帰問題を例に紹介します。

理論

まずは目標値を1つの値と想定してください。まずは出力層付近に注目します。

z は入力の総和、 f(z) は活性化関数、 r は目標値です。

通常、重みは以下の式で更新されます。

w_{t+1} \leftarrow w_t + \gamma \frac{\partial E}{\partial w}

t は学習のステップ、 w は重み、 \gamma は学習率、 E は損失関数です。右辺の第2項を計算すると以下のようになります。

\frac {\partial E}{\partial w}=\frac {\partial E}{\partial y}\frac {\partial y}{\partial z}\frac {\partial z}{\partial w}

回帰問題の場合、 E (r-y)^2/2 で算出できますが、運のいいことにこの式に対して y で微分すると、 -(r-y) になります。また、 z w_1 で微分するとき、残りの変数は w_1 と関係ないため、定数として扱えます。 \partial y / \partial z は関数 f に対する入力 z の微分値、つまり接線の傾きを表します。

例えば、 z=0 、活性化関数がシグモイド関数である場合、微分は以下のような赤線の傾きを表します。

結局以下のように表すことができます。

\frac {\partial E}{\partial w}=\frac {\partial E}{\partial y}\frac {\partial y}{\partial z}\frac {\partial z}{\partial w}=-(r-y) \frac {\partial y}{\partial z} x_1

数式だと上記のように表現できるが、どこの値を使っているかを図で確認した方がわかりやすいです。

上記の式だと赤点の変数を参照すれば、重みを更新することができます。 w_2 の重みについても同様です。つまり、 w_1 の前後にある1)出力関数の勾配と2)入力変数 x_1 の関によって w_1 の更新具合が変わります。

w_a w_b についてはどうでしょうか。 w_a を算出すると、計算上以下のようになります。

\frac {\partial E}{\partial w_a}=\frac {\partial E}{\partial y}\frac {\partial y}{\partial z}\frac {\partial z}{\partial x_1}\frac {\partial x_1}{\partial x_{1,in}}\frac {\partial x_{1,in}}{\partial w_a}=-(r-y) \frac {\partial y}{\partial z}w_1\frac {\partial x_1}{\partial x_{1,in}}u

x_{1,in} x_1 を出力ユニットの入力信号です。 u は入力です。 上記の算出は入力層にあるユニットが線形の活性化関数を用いている前提としています。以下の図では、どの値を計算時に使用しているかを示しています。

上記の図から w_a の更新量は出力層から遡った各微分値の総和と入力信号を用いて算出していることがわかります。

それでは目標変数が時系列データのように、1変数に対して複数の値を持っているデータセットの場合はどのように算出するのでしょうか。このような場合は通常ミニバッチという学習手法で学習させます。ミニバッチでは、まずデータセットの中からD個の値を取り、各値に対して損失関数を適用し、それらの総和を求め、平均化するという流れで重みの更新量を計算します。出力層の重みを算出すると以下のようになります。

\frac {\partial E}{\partial w}=\frac{1}{D}\sum_{i}^{D}\frac {\partial E_i}{\partial w}

i i 番目の損失関数を示します。 w は一般化された重みを表します。

以上のように誤差逆伝搬法を算出する際には前後の値を用いて重みを更新します。ReNomでは以下の部分が重みを更新します。

プログラミング

In [1]:
    with model.train():
        l = rm.mean_squared_error(model(in1), out1)
    grad = l.grad()
    grad.update(Sgd(lr=0.001))

‘model’はニューラルネットワーク関数を表します。’in1’、’out1’は入出力学習信号を表します。 ‘with model.train’ではトレーニングループを実行し、損失関数を算出します。 ‘l’は結果を積み重ねます。 ‘.grad()’メソッドはグラデーションを計算し、updateは ’model’の重みを更新します。

チェイン・ルール

ちなみに上記の流れでは直接微分するのではなく、変数ごとに微分をしました。この方法は通称、チェイン・ルール(連鎖律)と言います。高校では関数を含む関数を微分する場合、「大きい関数を微分してから中を微分する」という方法で微分を教わったかもしれませんが、実はそれもチェイン・ルールです。

まとめ

上記では3層のニューラルネットワークと回帰問題をもとに誤差逆伝搬法について紹介しました。また、図を使いながら、どこの値をもとに誤差逆伝搬法をしているかについて紹介しました。

どこの値を用いて算出しているかを直感的な理解をするために上記では1入力、1出力を例に紹介しました。多ノードをもつ層同士だと少し計算の工夫が必要ですが、チェイン・ルールを用いることに変わりはないです。