からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

ソフトマックス関数の逆伝播の導出【ゼロつく1のノート(数学)】

はじめに

 「機械学習・深層学習」初学者のための『ゼロから作るDeep Learning』の攻略ノートです。『ゼロつくシリーズ』学習の補助となるように適宜解説を加えています。本と一緒に読んでください。

 ニューラルネットワーク内部の計算について、数学的背景の解説や計算式の導出を行い、また実際の計算結果やグラフで確認していきます。

 この記事は、付録A「Softmax-with-Lossレイヤの計算グラフ」の内容です。Softmax関数を微分します。

【元の記事】

www.anarchive-beta.com

【他の記事一覧】

www.anarchive-beta.com

【この記事の内容】

ソフトマックス関数の逆伝播の導出

 ソフトマックス関数(Softmax関数)の微分(逆伝播)を導出します。順伝播については「3.5:ソフトマックス関数の実装【ゼロつく1のノート(実装)】 - からっぽのしょこ」を参照してください。

・定義式の確認

 ソフトマックス関数は、入力を$\mathbf{x} = (x_1, x_2, \cdots, x_K)$、出力を$\mathbf{y} = (y_1, y_2, \cdots, y_K)$として、次の式で定義されます。

$$ y_k = \frac{ \exp(x_k) }{ \sum_{k'=1}^K \exp(x_{k'}) } \tag{A.1} $$

 ここで、$K$は分類するクラス数です。この式が順伝播の計算式です。

 逆伝播(微分)は次の式になります。

$$ \frac{\partial y_k}{\partial x_k} = y_k (1 - y_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)} = \exp(x_k^{(0)}) $$

 $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)}$とすると、「総和をとる」は次の式で表せます。

$$ \begin{aligned} x^{(2)} &= \sum_{k=1}^K x_k^{(1)} \\ &= x_1^{(1)} + x_2^{(1)} + \cdots + x_K^{(1)} \end{aligned} $$

 $K$個の要素を足し合わせたので、ベクトルではなくスカラになり、下付き文字$k$がなくなりました。$x^{(2)}$を次のノードに入力します。

 $x^{(2)}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると

$$ x^{(2)} = \sum_{k=1}^K \exp(x_k^{(0)}) $$

です(後で利用します)。

・ステップ3

 3つ目の計算は、「入力で割る」です。「$/$」ノード(除算ノード)に$x^{(2)}$を入力します。

 3つ目のノードの出力を$x^{(3)}$とすると、「入力で割る」は次の式で表せます。

$$ x^{(3)} = \frac{1}{x^{(2)}} $$

 $x^{(3)}$を次のノードに入力します。

 $x^{(3)}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると

$$ x^{(3)} = \frac{1}{\sum_{k=1}^K \exp(x_k^{(0)})} $$

です(後で利用します)。

・ステップ4

 最後の計算は、「分子と分母を掛ける」です。「$\times$」ノード(乗算ノード)に$x_k^{(1)}$と$x^{(3)}$を入力します。

 4つ目のノードの出力を$y_k$とすると、「分子と分母を掛ける」は次の式で表せます。

$$ y_k = x_k^{(1)} x_k^{(3)} $$

 $y_k$ソフトマックス関数(Softmaxレイヤ)の$k$番目の出力です。次のレイヤがあればそのレイヤに$\mathbf{y}$を入力します。

 以上が、ソフトマックス関数で行う計算です。4つのノードをまとめてSoftmaxレイヤとして扱います。

・Softmaxレイヤ

 4つのノードをそれぞれ関数$f_1(x), \cdots, f_4(x)$とすると、Softmaxレイヤの計算は次の合成関数で表現できます。

$$ L = f_4\Bigl( f_1(x_k^{(0)}), f_3(f_2(f_1(x_k^{(0)}))) \Bigr) = \frac{ \exp(x_k) }{ \sum_{k'=1}^K \exp(x_{k'}) } \tag{A.2} $$

 $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つの関数が入れ子になっています。それぞれ分けて書くと

$$ \begin{aligned} x_k^{(1)} &= f_1(x_k^{(0)}) \\ x^{(2)} &= f_2(x_k^{(1)}) \\ x^{(3)} &= f_3(x^{(2)}) \\ y_k &= f_4(x_k^{(1)}, x^{(3)}) \end{aligned} $$

と同じ意味です。$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で確認します。

$$ \frac{\partial y_k}{\partial x_k^{(0)}} = \frac{\partial y_k}{\partial x_k^{(1)}} \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} + \frac{\partial y_k}{\partial x^{(3)}} \frac{\partial x^{(3)}}{\partial x^{(2)}} \frac{\partial x^{(2)}}{\partial x_k^{(1)}} \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} $$

 「$+$」よりも前の項が分子、後の項が分母に関するノードの微分です。順伝播時に枝分かれしたノードは、逆伝播時に足し合わせる必要があります。この式の「$+$」が、「足し合わせる」に対応します。詳しくは2巻の1.3.4.2項「分岐ノード」を参照してください。
 次のように表記しても同じ意味です。

$$ \frac{\partial y_k}{\partial x_k^{(0)}} = \frac{\partial f_4(x^{(3)})}{\partial x_k^{(1)}} \frac{\partial f_1(x_k^{(0)})}{\partial x_k^{(0)}} + \frac{\partial f_4(x^{(3)})}{\partial x^{(3)}} \frac{\partial f_3(x^{(2)})}{\partial x^{(2)}} \frac{\partial f_2(x_k^{(1)})}{\partial x_k^{(1)}} \frac{\partial f_1(x_k^{(0)})}{\partial x_k^{(0)}} $$

 ここでは、上の表記で統一します。

 各ノードの微分$\frac{\partial y}{\partial x^{(3)}}, \cdots, \frac{\partial x^{(1)}}{\partial x^{(0)}}$を求めていきます。

・ステップ4

 4つ目のノード(「$\times$」ノード)の順伝播は、次の計算でした。

$$ y_k = x_k^{(1)} x_k^{(3)} $$

 $y_k$を$x_k^{(1)}$と$x^{(3)}$でそれぞれ微分すると、

$$ \begin{aligned} \frac{\partial y_k}{\partial x_k^{(1)}} &= x^{(3)} \\ \frac{\partial y_k}{\partial x^{(3)}} &= x_k^{(1)} \end{aligned} $$

になります。

 $x^{(1)},\ x^{(3)}$にそれぞれ順伝播で求めた式を代入して、「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると

$$ \begin{aligned} \frac{\partial y_k}{\partial x_k^{(1)}} &= \frac{1}{\sum_{k=1}^K \exp(x_k^{(0)})} \\ \frac{\partial y_k}{\partial x_k^{(3)}} &= \exp(x_k^{(0)}) \end{aligned} $$

です。

・積の微分について(本の内容から逸脱気味なので省略)(クリックで展開)

 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)$の表記に置き換えると

$$ y_k = f_1(x_k^{(0)}) f_3(x^{(2)}) $$

です。どちらも$x_k^{(0)}$の関数です。
 積の微分の公式に当てはめると、$x_k^{(0)}$に関する$y_k$の微分$\frac{\partial y_k}{\partial x_k^{(0)}}$は

$$ \frac{\partial y_k}{\partial x_k^{(0)}} = \frac{\partial f_1(x_k^{(0)})}{\partial x_k^{(0)}} f_3(x^{(2)}) + f_1(x_k^{(0)}) \frac{\partial f_3(x^{(2)})}{\partial x_k^{(0)}} $$

となります。
 この式を中間変数$x^{(n)}$の表記に戻すと

$$ \frac{\partial y_k}{\partial x_k^{(0)}} = \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} x^{(3)} + x_k^{(1)} \frac{\partial x^{(3)}}{\partial x_k^{(0)}} $$

です。
 さらに、合成関数の微分(連鎖律)より$\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)}}$は

$$ \frac{\partial y_k}{\partial x_k^{(0)}} = \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} x^{(3)} + x_k^{(1)} \frac{\partial x^{(3)}}{\partial x^{(2)}} \frac{\partial x^{(2)}}{\partial x_k^{(1)}} \frac{\partial x_k^{(1)}}{\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つ目のノード(「$/$」ノード)の順伝播は、次の計算でした。

$$ x^{(3)} = \frac{1}{x^{(2)}} $$

 分数はマイナスの指数を使って$\frac{1}{x} = x^{-1}$と表すことができます。よって、「$/$」ノードは、次のように書き換えられます。微分の公式に当てはめやすい形にします。

$$ x^{(3)} = (x^{(2)})^{-1} $$

 $x^{(3)}$を$x^{(2)}$で微分すると

$$ \begin{aligned} \frac{\partial x^{(3)}}{\partial x^{(2)}} &= - 1 * (x^{(2)})^{-1-1} \\ &= - (x^{(2)})^{-2} \\ &= - \frac{1}{(x^{(2)})^{2}} \end{aligned} $$

となります。$x^{-2} = \frac{1}{x^2}$です。

 $\frac{\partial x^{(3)}}{\partial x^{(2)}}$を「ソフトマックス関数の入力$x_k^{(0)}$」を使って表現すると

$$ \frac{\partial x^{(3)}}{\partial x^{(2)}} = - \frac{ 1 }{ \Bigl( \sum_{k=1}^K \exp(x_k^{(0)}) \Bigr)^{2} } $$

です。

・ステップ2

 2つ目のノード(「$\mathrm{sum}$」ノード)の順伝播は、次の計算でした。

$$ \begin{aligned} x^{(2)} &= \sum_{k=1}^K x_k^{(1)} \\ &= x_1^{(1)} + \cdots + x_k^{(1)} + \cdots + x_K^{(1)} \end{aligned} $$

 $x^{(2)}$を$x_k^{(1)}$で微分すると

$$ \begin{aligned} \frac{\partial x^{(2)}}{\partial x_k^{(1)}} &= 0 + \cdots + 1 + \cdots + 0 \\ &= 1 \end{aligned} $$

 $x_k^{(1)}$の項だけが1となり、それ以外の項は0になります。

・ステップ1

 1つ目のノード(「$\exp$」ノード)の順伝播は、次の計算でした。

$$ x_k^{(1)} = \exp(x_k^{(0)}) $$

 $x_k^{(1)}$を$x_k^{(0)}$で微分すると

$$ \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} = \exp(x_k^{(0)}) $$

となります。指数関数$\exp(x)$の微分$\frac{d \exp(x)}{d x}$はそのままの値$\frac{d \exp(x)}{d x} = \exp(x)$です。

 以上で、各ノードの微分が求まりました。続いて、Softmaxレイヤの微分を考えます。

・Softmaxレイヤ

 各ノードの微分をそれぞれ連鎖律の式に代入します。

$$ \begin{aligned} \frac{\partial y_k}{\partial x_k^{(0)}} &= \frac{\partial y_k}{\partial x_k^{(1)}} \frac{\partial x_k^{(1)}}{\partial x_k^{(0)}} + \frac{\partial y_k}{\partial x^{(3)}} \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{1}{\sum_{k=1}^K \exp(x_k^{(0)})} \exp(x_k^{(0)}) + \exp(x_k^{(0)}) \left( - \frac{ 1 }{ \Bigl(\sum_{k=1}^K \exp(x_k^{(0)})\Bigr)^2 } \right) 1 \exp(x_k^{(0)}) \\ &= \frac{\exp(x_k^{(0)})}{\sum_{k=1}^K \exp(x_k^{(0)})} - \left( \frac{ \exp(x_k^{(0)}) }{ \sum_{k=1}^K \exp(x_k^{(0)}) } \right)^{2} \end{aligned} $$

 ソフトマックス関数の定義式(A.2)より、$y_k$に置き換えます。

$$ \begin{aligned} \frac{\partial y_k}{\partial x_k^{(0)}} &= y_k - y_k^{2} \\ &= y_k (1 - y_k) \end{aligned} $$

 $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年.

おわりに

 加筆修正の際に記事を分割しました。

 この記事を書いたおかげで、誤差逆伝播法と微分の公式をすり合わせられました。この記事を読んだ人にもその感覚が伝わるのかは微妙です。

【関連する記事】

www.anarchive-beta.com

www.anarchive-beta.com

www.anarchive-beta.com

 こちらの記事ではもう少し簡潔に解きました。

www.anarchive-beta.com