【読書メモ】Deep Learningを学ぶ〜分類問題で使用されるソフトマックス関数について〜Part 13
最初に
本記事は以下の本から得た知見を自分用のメモも兼ねてまとめた記事となります。ただし本の内容をそのまま書き写ししているわけではなく、ある程度自身で調べたものや感想が混じっています。ご了承ください。
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
また、本記事は株式会社よむネコのプロジェクトの業務内のお時間を頂いて蓄積した知見となります。
以下会社URLです。
今回は、主に分類問題で使用されるソフトマックス関数について学んでいきたいと思います。
ソフトマックス関数の式
このソフトマックス関数とは、複数ある出力の数値を合計した時に1.0
としてくれる関数です。つまり犬の写真を入力データとした時に、犬である確率が0.7
、猫である確率が0.3
と言ったように、確率として解釈できる値へ変換してくれます。
式の特徴としては以下のような点が挙げられます。
- 0 < < 1
これを踏まえた上で、ソフトマックス関数の式を表すと以下のようになります。
ここで、Σという数列の和自体に慣れていない人向けに式の解説しておきます。
まずはを表す指数関数です(eはネイピア数を表します)。
入力信号はとします。出力がです。
この式内の分母にあるは、が出力層の数で、は1番目の入力信号の値から順に足していくという意味です。この場合は1番目の出力からn番目までの入力信号の値()の総和となります。
のとは、番目の出力をさします。例えば、3個の出力の中から2番目の出力値を得たい場合には以下のようになります(ここで出力値の総和をとします)。
ソフトマックス関数の実装
先ほどの式をそのままPythonで実装すると以下のようになります。
def softmax_func(a): exp_a = np.exp(a) sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y a = np.array([0.3, 2.9, 4.0]) softmax_func(a) array([0.01821127, 0.24519181, 0.73659691])
ただしこのままでは、入力値が大きいと指数関数の計算をした時にオーバーフロー(値が大きすぎて表示できなくなった状態)が発生する危険性があります。
対策としては端的にいうと、入力値の中の最大値を全ての入力値から引くのが一般的な手法とされています(を用いた式も本には書いてありましたが省きます)。この要素を先ほどの実装に加えると以下のようになります。
def softmax_func_v2(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([0.3, 2.9, 4.0]) softmax_func_v2(a) array([0.01821127, 0.24519181, 0.73659691]) y = softmax_func_v2(a) np.sum(y) 1.0
ソフトマックス関数と分類問題
先ほど、ソフトマックス関数を用いることで、確率として解釈できる値へ変換してくれる、と言いました。分類問題では、一般的には、出力値の中で一番大きい値になる入力信号を発したクラスを認識結果とします。つまり犬である確率が0.7
、猫である確率が0.3
となった場合は、認識結果は「犬」になります。
また、ソフトマックス関数を適用したとしても出力の一番大きいニューロンの場所は変わりません。そのため、分類問題を扱う際には、一般的に出力層の活性化関数であるソフトマックス関数を省略しています(指数関数の計算はそれなりにPCに負荷がかかるため)。では今回学んだソフトマックス関数がどこで重要になるかというと、ニューラルネットワークが問題を扱う際の「学習」フェーズとなります。
分類問題の出力層
出力層の数は扱う問題によって適宜決定する必要があります。分類問題では、先ほどの例で「犬」と「猫」を分ける場合、出力層は2つとなります。ここに「兎」や「魚」を加える場合は出力層は合計4つです。
最後に
今回はソフトマックス関数について学んでいきました。一見難しそうに見えますが、少し時間をかけて紐解いてみるとある程度理解することができました。次は実際に手書き数字の認識という実践問題に取り組んでいきます。