はじめに
「機械学習・深層学習」初学者のための『ゼロから作るDeep Learning』の攻略ノートです。『ゼロつくシリーズ』学習の補助となるように適宜解説を加えています。本と一緒に読んでください。
ニューラルネットワーク内部の計算について、数学的背景の解説や計算式の導出を行い、また実際の計算結果やグラフで確認していきます。
この記事は、付録A「Softmax-with-Lossレイヤの計算グラフ」の内容です。Softmax関数を微分します。
【元の記事】
【他の記事一覧】
【この記事の内容】
ソフトマックス関数の逆伝播の導出
ソフトマックス関数(Softmax関数)の微分(逆伝播)を導出します。順伝播については「3.5:ソフトマックス関数の実装【ゼロつく1のノート(実装)】 - からっぽのしょこ」を参照してください。
・定義式の確認
ソフトマックス関数は、入力を$\mathbf{x} = (x_1, x_2, \cdots, x_K)$、出力を$\mathbf{y} = (y_1, y_2, \cdots, y_K)$として、次の式で定義されます。
ここで、$K$は分類するクラス数です。この式が順伝播の計算式です。
逆伝播(微分)は次の式になります。
この式を導出します。($i \neq j$の場合(クラスが異なる場合)は$\frac{\partial y_i}{\partial x_j} = - y_i y_j$になりますが、ここでは扱いません。興味がある方は「Softmax関数の微分 - からっぽのしょこ」を参照してください。)
・順伝播の確認
ソフトマックス関数(A.1)の計算は、各入力$x_k$に対して「指数をとる」「総和をとる」「$1$を割る」「分母分子を掛ける」の4つのノード(ステップ)に分解できます(図A-2)。
まずは、この順伝播の計算を確認します。ただし、ステップ番号の振り方が本と異なるので注意してください。
・ステップ1
最初の計算は、「入力の指数をとる」です。「$\exp$」ノード(指数ノード)にソフトマックス関数の入力を入力します。
1つ目のノードの入力を$x_k^{(0)}$、出力を$x_k^{(1)}$とすると、「入力の指数をとる」は次の式で表せます。
$x_k^{(1)}$を次のノードに入力します。
・ステップ2
2つ目の計算は、「総和をとる」です。「$\mathrm{sum}$」ノード(総和ノード)に$\mathbf{x}^{(1)} = (x_1^{(1)}, x_2^{(1)}, \cdots, x_K^{(1)})$を入力します。「$\mathrm{sum}$」ノードについては2巻の1.3.4.4項を参照してください。ここでは「$+$」ノードとほとんど同じです。
2つ目のノードの出力を$x^{(2)}$とすると、「総和をとる」は次の式で表せます。
$K$個の要素を足し合わせたので、ベクトルではなくスカラになり、下付き文字$k$がなくなりました。$x^{(2)}$を次のノードに入力します。
$x^{(2)}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると
です(後で利用します)。
・ステップ3
3つ目の計算は、「入力で割る」です。「$/$」ノード(除算ノード)に$x^{(2)}$を入力します。
3つ目のノードの出力を$x^{(3)}$とすると、「入力で割る」は次の式で表せます。
$x^{(3)}$を次のノードに入力します。
$x^{(3)}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると
です(後で利用します)。
・ステップ4
最後の計算は、「分子と分母を掛ける」です。「$\times$」ノード(乗算ノード)に$x_k^{(1)}$と$x^{(3)}$を入力します。
4つ目のノードの出力を$y_k$とすると、「分子と分母を掛ける」は次の式で表せます。
$y_k$ソフトマックス関数(Softmaxレイヤ)の$k$番目の出力です。次のレイヤがあればそのレイヤに$\mathbf{y}$を入力します。
以上が、ソフトマックス関数で行う計算です。4つのノードをまとめてSoftmaxレイヤとして扱います。
・Softmaxレイヤ
4つのノードをそれぞれ関数$f_1(x), \cdots, f_4(x)$とすると、Softmaxレイヤの計算は次の合成関数で表現できます。
$f_1(x_k^{(0)}) = \exp(x_k)$、$f_3(f_2(f_1(x_k^{(0)}))) = \frac{1}{\sum_{k'=1}^K \exp(x_{k'})}$に対応しており、4つの関数が入れ子になっています。それぞれ分けて書くと
と同じ意味です。$f_4(x)$には2つの変数が入力しています。
ここまでは、順伝播の計算を確認しました。次からは、逆伝播の計算を確認します。
・逆伝播の導出
逆伝播では、「順伝播の入力$x_k^{(0)}$」に関する「順伝播の出力$y_k$」の微分$\frac{\partial y_k}{\partial x_k^{(0)}}$を求めます。
$\frac{\partial y_k}{\partial x_k^{(0)}}$は、「合成関数の微分」と「積の微分」と言えます。よって、「4つの関数(ノード)の微分の積」と「分岐したノードの和」で求められます。合成関数の微分については「5.2:連鎖率【ゼロつく1のノート(数学)】 - からっぽのしょこ」を参照してください。積の微分についてはステップ4で確認します。
「$+$」よりも前の項が分子、後の項が分母に関するノードの微分です。順伝播時に枝分かれしたノードは、逆伝播時に足し合わせる必要があります。この式の「$+$」が、「足し合わせる」に対応します。詳しくは2巻の1.3.4.2項「分岐ノード」を参照してください。
次のように表記しても同じ意味です。
ここでは、上の表記で統一します。
各ノードの微分$\frac{\partial y}{\partial x^{(3)}}, \cdots, \frac{\partial x^{(1)}}{\partial x^{(0)}}$を求めていきます。
・ステップ4
4つ目のノード(「$\times$」ノード)の順伝播は、次の計算でした。
$y_k$を$x_k^{(1)}$と$x^{(3)}$でそれぞれ微分すると、
になります。
$x^{(1)},\ x^{(3)}$にそれぞれ順伝播で求めた式を代入して、「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると
です。
・積の微分について(本の内容から逸脱気味なので省略)(クリックで展開)
2つの関数の積$f(x) g(x)$を微分すると、積の微分$\{f(x) g(x)\}' = f'(x) g(x) + f(x) g'(x)$になります。
$y_k = x_k^{(1)} x_k^{(3)}$を関数$f_n(x)$の表記に置き換えると
です。どちらも$x_k^{(0)}$の関数です。
積の微分の公式に当てはめると、$x_k^{(0)}$に関する$y_k$の微分$\frac{\partial y_k}{\partial x_k^{(0)}}$は
となります。
この式を中間変数$x^{(n)}$の表記に戻すと
です。
さらに、合成関数の微分(連鎖律)より$\frac{\partial x^{(3)}}{\partial x_k^{(0)}} = \frac{\partial x^{(3)}}{\partial x^{(2)}} \frac{\partial x^{(2)}}{\partial x_k^{(1)}} \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}}$なので、$\frac{\partial y_k}{\partial x_k^{(0)}}$は
となります。
この式は、「逆伝播の導出」の連鎖律の式に、「ステップ4」で求めた$\frac{\partial y_k}{\partial x_k^{(1)}} = x^{(3)}$と$\frac{\partial y_k}{\partial x^{(3)}} = x_k^{(1)}$を代入した式になっているのが分かります。
以上で、逆伝播法による「分岐したノードを持つ関数の微分」と、「合成関数の微分と積の微分」との関係を確認できました。
・ステップ3
3つ目のノード(「$/$」ノード)の順伝播は、次の計算でした。
分数はマイナスの指数を使って$\frac{1}{x} = x^{-1}$と表すことができます。よって、「$/$」ノードは、次のように書き換えられます。微分の公式に当てはめやすい形にします。
$x^{(3)}$を$x^{(2)}$で微分すると
となります。$x^{-2} = \frac{1}{x^2}$です。
$\frac{\partial x^{(3)}}{\partial x^{(2)}}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると
です。
・ステップ2
2つ目のノード(「$\mathrm{sum}$」ノード)の順伝播は、次の計算でした。
$x^{(2)}$を$x_k^{(1)}$で微分すると
$x_k^{(1)}$の項だけが1となり、それ以外の項は0になります。
・ステップ1
1つ目のノード(「$\exp$」ノード)の順伝播は、次の計算でした。
$x_k^{(1)}$を$x_k^{(0)}$で微分すると
となります。指数関数$\exp(x)$の微分$\frac{d \exp(x)}{d x}$はそのままの値$\frac{d \exp(x)}{d x} = \exp(x)$です。
以上で、各ノードの微分が求まりました。続いて、Softmaxレイヤの微分を考えます。
・Softmaxレイヤ
各ノードの微分をそれぞれ連鎖律の式に代入します。
ソフトマックス関数の定義式(A.2)より、$y_k$に置き換えます。
$k$番目の入力$x_k^{(0)}$に関する微分$\frac{\partial y_k}{\partial x_k^{(0)}}$が得られました。
前後にレイヤがある場合は、「逆伝播の入力$\frac{\partial L}{\partial y_k}$」と「このレイヤの微分$\frac{\partial y_k}{\partial x_k}$」の積$\frac{\partial L}{\partial x_k} = \frac{\partial L}{\partial y_k} \frac{\partial y_k}{\partial x_k}$を出力します(前のレイヤに入力します)。
参考文献
- 斎藤康毅『ゼロから作るDeep Learning』オライリー・ジャパン,2016年.
おわりに
加筆修正の際に記事を分割しました。
この記事を書いたおかげで、誤差逆伝播法と微分の公式をすり合わせられました。この記事を読んだ人にもその感覚が伝わるのかは微妙です。
【関連する記事】
こちらの記事ではもう少し簡潔に解きました。