出力層のsoftmax関数を実装してみる

機械学習は「分類問題」と「回帰問題」の2種類に大きく分けることができる。分類問題は、画像を見てそれが猫なのか犬なのか判別するような、カテゴライズするタイプのもの。回帰問題は、人の姿かたちを分析して体重を推測する、というような対象の情報量を増やすタイプのものだ。

画像①分類問題と回帰問題

学習や推論を行う層(「隠れ層」と呼ばれる)での計算結果を、出力として適切な形に補正する層のことを「出力層」と呼ぶ。出力層は分類問題と回帰問題で異なるが、回帰問題で使われる「恒等関数(identity function)」は入力をそのまま出力するだけなので、説明は省く。ここでは、分類問題の出力層で使われる「ソフトマックス関数(SoftMax function)」について書く。

< ソフトマックス関数 >

画像②数式

画像③ソフトマックス関数

ソフトマックス関数の特徴は、すべての出力の総和が1に調整されることだ。これにより、各出力を確率として考えることができる。例えば入力画像が①犬なのか、②猫なのか、③パンダなのかを判定するニューラルネットワークを設計したとする。ソフトマックス関数を介する前①0.3、②2.9、③4.0という「真である可能性の高さ」を持っていた場合、単に「画像はパンダである」と答えることができる。しかし、ソフトマックス関数を介すると出力は①0.018、②0.245、③0.737というように出て、「画像は73.7%の確率でパンダである。」と言える。

ソフトマックス関数を実装すると以下のようになる。

import numpy as np

def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a

return y

a = np.array([1010, 1000, 990])
s = softmax(a)
print (s) #[ nan nan nan]

実はこの実装は理論上は正確だが、実際に動かすとエラーが起こる。というのも、exp()の計算結果が大きすぎるのだ。入力が100ですでにexp(100)は40桁以上の数になる。入力が1000にもなれば、桁が大きすぎてコンピュータが無限大(inf)と解釈してしまう。この現象を「オーバーフロー(Over flow)」という。オーバーフローを避けるには、計算結果の理論値を変えずに計算途中の数字の絶対値を小さくする工夫が要る。

画像④オーバーフロー対策

ここでは、分母と分子に定数Cを掛けることでexpの中身を補正する。ではCはどのような値なら適切なのか。入力が未知なので、特定の定数ではなく入力に依存する値であるべきなのは明らかだが、一般的にここには入力の最大値を代入する。実装すると以下のようになる。

def softmax(a):
c = np.max(a)
exp_a = np.exp(a – c)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a

return y

a = np.array([1010, 1000, 990])
s = softmax(a)
print (s) #[ 9.99954600e-01 4.53978686e-05 2.06106005e-09]

オーバーフロー対策をすることで、問題なく計算ができた。

Leave a Comment