SoftMax関数


出力層の総和を1にするように調整できれば、出力層を確率としてとらえることができるようになる。
入力層に画像を放り込み、出力層でラベルに属する確率を出せば、画像にラベルをつける分類器になる。

入力が\(n\)ノードあるとして、全てのノードを入力を受けて出力する。
出力側のノードが\(m\)ノードあるとして、和が\(1\)になるようにどう操作するか。
分母は入力側の全ノードの和、分子は対応する1ノードだけ。そうやって1にする。

指数関数に入力を食わせて和を取る。指数関数は単調増加関数だから、
入力の大小と出力の大小は一致する。定義上は以下の通り。
\begin{eqnarray}
y_k &=& \frac{e^{a_k}}{\sum_{i=1}^n e^{a_i}}
\end{eqnarray}


import numpy as np

def softmax1(x):
    return np.exp(x) / np.sum(np.exp(x))

a = np.array([1010,1000,990])
r1 = softmax1(a)
r1

# array([nan, nan, nan])

ただ、この通りにするとオーバーフローを起こすので、
式変形してオーバーフローを回避する。\(C\)は入力ノードの最大値。
\begin{eqnarray}
y_k &=& \frac{e^{a_k}}{\sum_{i=1}^n e^{a_i}} \\
&=& \frac{C e^{a_k}}{C\sum_{i=1}^n e^{a_i}} \\
&=& \frac{e^{a_k+\log{C}}}{\sum_{i=1}^{n} e^{a_i + \log{C}}} \\
&=& \frac{e^{a_k+C’}}{\sum_{i=1}^{n} e^{a_i + C’}}
\end{eqnarray}


import numpy as np

def softmax2(x):
    c = np.max(x)
    return np.exp(x-c) / np.sum(np.exp(x-c))

a = np.array([1010,1000,990])
r2 = softmax2(a)
r2

# array([9.99954600e-01, 4.53978686e-05, 2.06106005e-09])

SoftMax後の和は1

前述の通り、SoftMax後の和は1。


z = np.sum(r2)
z
# 1.0