※以下の企画です
前回に続いてゼロつくやっていきます。
今回は3章-ニューラルネットワーク-です。
基本は図を使わないという横着をしていきますので、誰かのなにかのための記事になる気はしないので期待しないでください。
ひたすらに自分のためのアウトプットになります。
おねがいします!
3章 ニューラルネットワーク
ニューラルネットワークとは
前回まで学んでいたパーセプトロンだと、重み$w_{n}$を自分の手でいい感じに設定する必要があった。
ニューラルネットワークというものを用いると、複数階層のパーセプトロン達をつなげて、しかも適切な重みを計算によって導きだせるような仕組みを構築できる。というかそういう仕組みのことをニューラルネットワークと言う。
上記の"複数階層"とは、入力層、中間層、出力層という層に分けることができて、中間層を増やしまくって何階層にもしたものをディープニューラルネットワーク(DNN) という。
活性化関数
入力信号の総和を出力信号に変換するための関数。
それってただのSUM関数じゃね?って感じだが、「出力信号に変換」という部分がミソになっている。
今後の説明簡略化のために、入力信号の総和を求める式を以下のようにしておく。
y = h(b+w_{1}x_{1}+w_{2}x_{2}...+w_{n}x_{n}) \\
y = \left\{
\begin{array}{ll}
0 & (x \leqq 0) \\
1 & (x > 0)
\end{array}
\right.
h(x) = \left\{
\begin{array}{ll}
0 & (x \leqq 0) \\
1 & (x > 0)
\end{array}
\right.
$h(x)$は、入力値$x$の総和を、0を閾値にして1と0に変換する関数。
日本語むずかしい。
シグモイド関数
入力信号を以下の式に従って変換する関数。
h(x) = \frac{1}{1+exp(-x)}
$exp$はネイピア数というやつで、いわゆる$e$だ(なんの説明にもなっていない)。
こいつがいることによって、シグモイド関数は指数関数的な数値変動が想定される。
ということで、実際にプロットまでしてみて動作確認をする。
from os.path import normpath
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.array([-1.0, 1.0, 2.0])
sigmoid(x)
array([0.26894142, 0.73105858, 0.88079708])
上記がシグモイド関数の実装と出力テストの結果。
入力に対して極めて連続的な出力値になっている。
import matplotlib.pylab as plt
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1, 1.1) #yの描画範囲
plt.show()
とりあえず描画してみたところ、S次カーブを描く曲線になった。
入力に対して緩やかに応答している感じ。
一定の閾値を超えたらバシッと1か0かに変換するパーセプトロンのときの関数(ステップ関数という)とは異なっていることがわかる。
ニューラルネットワークだと、こういう滑らかな活性化関数を用いないといけないらしい。
1か0かにしかならない場合だと、何層にも重ねる意味がなくなるかららしい。まぁ、たしかに。
ReLu関数
シグモイド関数と同じくらい有名で代表的な活性化関数がReLu(Rectified Linear Unit)関数というやつ。
これは以下の通りめちゃくちゃ簡単な仕組み。
h(x) = \left\{
\begin{array}{ll}
0 & (x \leqq 0) \\
x & (x > 0)
\end{array}
\right.
0を超えたら入力値がそのまま現れるという関数。
def relu(x):
return np.maximum(0,x)
コードも非常にシンプルで、0と入力値を比較して大きい方を取るだけ。
※これは書籍の方から写経したのだが、もし自分がヒント無しにゼロからコーディングするとしたら、if文
とか使って無駄なコードだらけになりそう。悲しい
まとめ
一旦今回は活性化関数まで進めた。
次回は三層のNNを実装してみるところから始めるが、no.dot
とかそういう文法的な内容は端折っていく上に図を極力使わない(工数エグくてアウトプットが続かなくなるので…)方向で行く( ◠‿◠ )