※以下の企画です
前回に続いてゼロつくやっていきます。
今回は3章-ニューラルネットワーク-の続きです。
前回は活性化関数のことをメインで学び、今回は実際に三層のNNを組んでいくという内容になりそうです。
それでは頑張っていきます〜
3章 ニューラルネットワーク
3層NN
ニューラルネットワークの計算は、各ノードへの入力値に重みを掛けて総和を取るだけ。
コードに落とし込むと、「各ノードへの重み×入力値の計算」を「ノード数×層」分繰り返すことになる。
ちょっと冗長なコードになりそうな印象だが、numpy
ライブラリを用いれば割とキレイに書くことができる(僕も本書を読んで知った)。
def init_network():
network = {}
network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
network['b1'] = np.array([0.1, 0.2, 0.3])
network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
network['b2'] = np.array([0.1, 0.2])
network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
network['b3'] = np.array([0.1, 0.2])
return network
def identity_Function(x):
return x
def forward(network, x):
w1,w2,w3 = network['W1'], network['W2'], network['W3']
b1,b2,b3 = network['b1'], network['b2'], network['b3']
a1 = np.dot(x, w1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, w2) + b2
z2 = sigmoid(a2)
a3 = np.dot(z2, w3) + b3
y = identity_Function(a3)
return y
コードはみたまんまの内容だが、a1 = np.dot(x, w1) + b1
という部分が割とミソで、行列同士の席やベクトルの内積をサクッと計算してくれる関数。
これで繰り返し文をエッサホイサと記述する必要がなくなる。ありがたい。
また、identity_Function
という関数が最後に用いられている。
関数の中身を見ると、入力をそのまま出力に設定しているだけの謎関数に見えるが、これは後で出力層をイジイジするときに使うらしいのおいておく(これは恒等関数と言うらしい)
実行結果をみてみる。
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y)
[0.31682708 0.69627909]
めっちゃ簡単!
出力層の設計
分類、回帰問題
出力層に用いていた恒等関数は回帰問題のときに用いて、分類問題のときにソフトマックス関数というものを用いるらしい。
ソフトマックス関数
まずは式から。
y_{k} = \frac{\exp(a_{k})}{\sum_{i=1}^{n}\exp(a_{i})}
出力層への入力が$n$個あって、$k$番目の出力$y_{k}$を求めるという計算。
また、指数感の計算は桁数がとんでもない数になるので、コンピュータでそのまま扱おうとするとエラーになるらしい。
なので、入力値の最大値を分母分子から引くという処理を行う。
これは、ある定数を分母分子に加えたとて、計算結果は変わらないという特徴を活用している。証明式は本書内にあるので興味のある人は是非とも読んでみてほしい!(怠惰)
※入力の最大値を使うのは、なんかそういう流れがあるからってだけらしい
ということで、それらも踏まえてソフトマックス関数をコードに落とし込んでみる。
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
ソフトマックス関数の特徴としては、出力の総和が1になるという点。
これで何が言いたいかというと、これは「各出力の発生確率に置き換えられる」ということ。
だからソフトマックス関数は分類問題に用いられるということみたい。
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
ここまでやっといて「え?」となったのが、ニューラルネットワークで分類問題を推論するときは、ソフトマックス関数を省略するらしい。草
というのも、指数関数を用いても入力された値のそもそもの大小関係は変わらず、単調増加するだけなので、重たい計算しなくても最大値を取るだけで大丈夫だってことらしい。
まぁたしかに。
まとめ
今回は出力層に用いる関数について学んだ。
ソフトマックスとか恒等関数とか、忘れかけていたものを改めて理解できて良かった。
次回はいよいよMNISTデータを用いてのテストになる。
こんな牛歩進捗で、月内に終わる気がしない。
では、次回も頑張ります〜〜