備忘録_3層のニューラルネットワーク

備忘録_3層のニューラルネットワーク

各層における信号伝達の実装

入力層から第1層目への信号の伝達

①はバイアスニューロンである。

上記の記号の意味は下記のとおりである。

${}^{}_{}a^{(1)}_{1}$を数式で表現

     \[ ${}^{}_{}a^{(1)}_{1}={}^{}_{}w^{(1)}_{11}{}^{}_{}x^{}_{1}+{}^{}_{}w^{(1)}_{12}{}^{}_{}x^{}_{2}+{}^{}_{}b^{(1)}_{1}$ \]

行列の積を用いて表現

     \[ ${}^{}_{}A^{(1)}_{}={}^{}_{}XW^{(1)}_{}+{}^{}_{}B^{(1)}_{}$ \]

${}^{}_{}A^{(1)}_{}$$X$$W^{(1)}_{}$${}^{}_{}B^{(1)}_{}$は下記のとおり

     \[ ${}^{}_{}A^{(1)}_{}=\begin{pmatrix} a^{(1)}_{1} & a^{(1)}_{2} & a^{(1)}_{3} \end{pmatrix}$\\ $X=\begin{pmatrix} x^{}_{1} & x^{}_{2} \end{pmatrix}$\\ ${}^{}_{}B^{(1)}_{}=\begin{pmatrix} b^{(1)}_{1} & b^{(1)}_{2} & b^{(1)}_{3} \end{pmatrix}$\\ ${}^{}_{}W^{(1)}_{}=\begin{pmatrix} w^{(1)}_{11} & w^{(1)}_{21} & w^{(1)}_{31} \\ w^{(1)}_{12} & w^{(1)}_{22} & w^{(1)}_{32} \end{pmatrix}$\\ \]

Numpyの多次元配列を使用して行列の積を計算

import numpy as np
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])
print(W1.shape)
(2, 3)
print(X.shape)
(2,)
print(B1.shape)
(3,)
A1= np.dot(X,W1)+B1

※ここでは、入力信号、重み、バイアスは適当な値に設定している

第1層目の活性化関数によるプロセス

隠れ層での重み付き和(重み付き信号とバイアスの総和)を$a$で表し、活性化関数で変換された信号を$z$で表す。活性化関数は$h()$で表し、ここではシグモイド関数を使うこととする。

A1をシグモイド関数でPythonで実装すると

def sigmoid(x):
    return 1 / (1 + np.exp(-x))
Z1 = sigmoid(A1)
print(A1)
[0.3 0.7 1.1]
print(Z1)
[0.57444252 0.66818777 0.75026011]

第1層から第2層目までの実装

実装内容は第1層の出力(Z1)が第2層への入力になっている点を除けば入力層から第1層目と同じである。

W2 = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2 = np.array([0.1,0.2])
print(Z1.shape)
(3,)
print(W2.shape)
(3, 2)
print(B2.shape)
(2,)
A2 = np.dot(Z1,W2) + B2
Z2 = sigmoid(A2)

※ここでは重み、バイアスは適当な値に設定している

第2層から出力層への信号の伝達

出力層の活性化関数として「恒等関数」を利用する。恒等関数は、入力をそのまま出力する関数である。

第2層から出力層のPythonでの実装

def identity_function(x): #恒等関数
    return x

W3 = np.array([[0.1,0.3],[0.2,0.4]])
B3 = np.array([0.1,0.2])
A3 = np.dot(Z1,W2) + B3
Y = identity_function(A3)
print(Y)
[0.51615984 1.21402696]

※ここでは重み、バイアスは適当な値に設定している

まとめ

まとめて(綺麗に)実装

import numpy as np
def identity_function(x): 
    return x
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
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 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
network = init_network()
x = np.array([1.0,0.5])
y = forward(network,x)
print(y)
[0.31682708 0.69627909]
  • ニューラルネットワークの実装の慣例として、重みだけは大文字で表記し、それ以外は小文字で表記する
  • init_network()関数は重みとバイアスの初期化し、networkに格納する
  • ディクショナリ型のnetworkにはそれぞれの層で必要なパラメータ(重みとバイアス)を格納する
  • forword()関数は入力信号が出力へと変換するプロセスである