Enjoy Engineer Life

C#,Unity,C++,UE4などの技術ブログや雑記を徒然なるままに書いていきます。

【読書メモ】Deep Learningを学ぶ〜ニューラルネットワークの実装〜Part 11

最初に

本記事は以下の本から得た知見を自分用のメモも兼ねてまとめた記事となります。ただし本の内容をそのまま書き写ししているわけではなく、ある程度自身で調べたものや感想が混じっています。ご了承ください。

f:id:rossamu:20190103000547p:plain ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

また、本記事は株式会社よむネコのプロジェクトの業務内のお時間を頂いて蓄積した知見となります。
以下会社URLです。

http://www.yomune.co/ f:id:rossamu:20191023153505p:plain



今回は、前回学んだNumPy行列を用いてニューラルネットワークの実装を行なっていきます。


単純なニューラルネットワークの実装

最初なので、バイアスと活性化関数を省略し、重みだけが存在する以下のような図のニューラルネットワークを実装します。

f:id:rossamu:20191024195400p:plain

   x = np.array([1, 2])
    
    # w = array([[x1の信号の重み], [x2の信号の重み]])
    w = np.array([[1, 3, 5], [2, 4, 6]])
    
    y = np.dot(x, w)
    print(y)
    # 出力
    #[ 5 11 17]



3層ニューラルネットワークの実装

以下の図に示す3層ニューラルネットワークの、入力から出力へ向けた処理(これをフォワード処理という)を実装していきます。

f:id:rossamu:20191024195426p:plain



ここから、「入力層→第1層目の1番目のニューロンへ向かう信号」にだけ注目します。記号を用いた図が以下のものです。

(記号についての記事はこちら:【読書メモ】Deep Learningを学ぶ〜ニューラルネットワークで使用する記号〜Part 10.5

f:id:rossamu:20191024195446p:plain


(ちなみにバイアスニューロンは一つだけなため、右下のインデックスは一つだけです)



a^ {(1)} _ 1を式で表すと以下のようになります。


a^{(1)}_1 = w^{(1)}_{11}x_1 + w^{(1)}_{12} + b^{(1)}_1


先ほどの図の中の第1層目に出てくる、 a^ {(1)} _ 1,  a^ {(1)} _ 2,  a^ {(1)} _ 3は、行列の内積を用いてまとめて一つの式で表すことができます。

a^ {(1)} _ 2, a^ {(1)} _ 3は、行列の内積を用いてまとめて一つの式で表すことができます。

・( a^ {(1)} _ 1, a^ {(1)} _ 2.....a^ {(1)} _ n) を A^ {(1)} とします。

・(x _ 1, x _ 2.....x _ n) を X とします。

・(b^ {(1)} _ 1, b^ {(1)} _ 2.....b^ {(1)} _ n)を B^ {(1)} とします。

 \begin{pmatrix}w^ {(1)} _ {11} & w^ {(1)} _ {21} ... & ..w^ {(1)} _ {n1}\\w^ {(1)} _ {12} & w^ {(1)} _ {22} ...& .. w^ {(1)} _ {3n} \\\end{pmatrix}


W^ {(1)} とします。



A^{(1)} = XW^{(1)} + B^{(1)}



これにまずは第1層のa^ {(1)} _ 1を求めるために仮値を入れ、NumPyを使用して実装した場合は以下のようになります。

   X = np.array([1.0, 0.5])
    W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    B1 = np.array([0.1, 0.2, 0.3])
    A1 = np.dot(X, W1) + B1
    
    print(A1)
    # 出力
    # [0.3 0.7 1.1]


次は活性化関数h()を用いて、a^ {(1)} _ 1を変換(変換後の値はz^ {(1)} _ 1とする)します。

f:id:rossamu:20191024195507p:plain


ここでのh()シグモイド関数を使用してみます。

   def sigmoid_func(x):
        return 1 / (1 + np.exp(-x))

    Z1 = sigmoid_func(A1)
    print(Z1)
    # 出力
    # [0.57444252 0.66818777 0.75026011]

a^ {(2)} _ 1を求める際には先ほど導き出したZ1を使用して、同様の処理を行うことで出力値が得られます。

ただ、出力層に向けた活性化関数だけは、入力をそのまま出力するものになります。

f:id:rossamu:20191024195528p:plain

   def identity_func(x):
        return x


このidentity_func(x)のような関数を「恒等関数」と言います。



最後に

これでニューラルネットワークの実装に必要な基礎知識を少し得ることができました。今回はフォワード処理についてでしたが次はバックワード処理となります。少しずつでも頑張っていきます。