ゼロから作るDeep Learning(6日目)

こんにちは、筋肉めがねです。

 

住んでいる街の中央駅にある、とあるカフェでこの記事を書いています。カフェを囲むのは壁ではなく、3面大きなガラスであり、カフェの外のずーっと向こうまで見渡せます。日本にはあまり無い気がしますが、ドイツにはターミナル駅が結構あるんですよね。ここの駅も例に漏れずターミナル駅で、電車が駅に入ってくるところ、駅から出ていくところを真正面から見ることができます。どこからともなく聞こえてくる音色は、誰かが駅の構内に置いてあるピアノを弾いているんですね。なんとも贅沢な金曜日の夕方でございます。

 

f:id:KinnikuMegane:20181013043600j:plain

 

それでは、本日も「ゼロから作るDeep Learning」を進めていきましょう。

本日も3章でございます。

 

前回の記事では、多次元配列を使って、3層のニューラルネットワークを実装しましたね。そして、出力層に使う活性化関数は、分類問題、回帰問題など解きたい問題によって異なる関数を使用する、という事を書きました。

 

では、分類問題、回帰問題とは何なのか。 

分類問題とは、ざっくり言うとデータをそれぞれカテゴリごとに分類するもの。例えば、帳簿に記帳された経費が変動費なのか固定費なのか、とカテゴリに分ける、ということ。そして、回帰問題とは、これもざっくり言うと数値予測です。例えば、ある会社の過去10年間の営業利益をインプットにして、翌月の営業利益を予測する、というものです。

 

それで、先の記事で、分類問題と回帰問題では、出力層に使用する活性化関数が異なる、という事を書きました。

 

では、分類問題に使う活性化関数は、というと、これはソフトマックス関数、というものであり、回帰問題には恒等関数、というものを使います。恒等関数は、入力をそのまま出力します。入ってきたものに何も手を加えず出力する、それが恒等関数です。恒等関数については、あまり特筆すべきことはなさそうです。

 

という事で、ソフトマックス関数について、以下、ソフトマックス関数を実装したコードをoutputを載せましょう。

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

a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)
[ 0.01821127  0.24519181  0.73659691]
np.sum(y)
1.0

このコードで大事なことは二つです。

 

一つはオーバーフロー対策と呼ばれるもの。以下の2行のコードで何をしているか、というと複数のインプットデータの最大値を各要素からdeductしています。これで、exponentialの計算結果がコンピューターの計算許容範囲を超える事を防ぐことができます。

c = np.max(a)
exp_a = np.exp(a - c)

 

そして、もう一つは、ソフトマックス関数の出力結果である各要素の総和は1となる、という事。つまり、各要素を確率としてとらえる事ができるわけですね。分類問題と捉えるならば、outputとなる各要素の中で、どの要素が一番確率が高いのか、という事がわかります。(上の例では、0.7365 = 73.65%ですね。)

 

ここで、ソフトマックス関数がexponentialを使っているという事、そしてコンピューターでexponentialの計算をさせる事は負荷が高い、という事から、出力層では、ソフトマックス関数(活性化関数)を使う必要がない、という事を書いておきましょう。

前の記事で示した通り、ニューラルネットワークでは各層に活性化関数を用いています。それで、分類問題で知りたいことは、結局、各要素が出力される確率を見て、それで判断すれば良いわけですよね。

それで、下の図を使って説明すると、出力層のインプットであるa1, a2に対して、exponentialを適用しても、アウトプットであるy1とy2の大小関係は、実はa1とa2の大小関係と変わらないんですよね。例えば、1と5という二つのインプットがあった時に、大きほうは5ですね。そして、両方の値のexponential値、exp(1)とexp(5)と比較しても、大きいほうはexp(5)となるわけです。分類問題では、結局、最終的なアウトプットである各要素の大小関係(各要素の確率)が知りたいわけだから、出力層で活性化関数(ソフトマックス関数)を使う必要がない、という事なんです。それだけ、コンピューターが楽をできるわけです。

ただ、これは分類(機械学習では推論と呼ぶ)を行うフェーズでのみ言えることであって、学習するフェーズでは、出力層に活性化関数を使用するんですよね。

これについては4章で書いていきます。

f:id:KinnikuMegane:20181012041728p:plain

次の記事では、実際に手書き文字を分類するニューラルネットワークを作っていきましょう。 

 

それでは、本日は以上でございます。