新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。もう新人じゃないかも…

学習記録:ゼロから作るDeepLearning

3章:ニューラルネットワーク(続き)

多次元配列の計算

まずはNumPyによる多次元配列の計算について学ぶ。
2次元配列=行列の内積を計算してみる。内積の計算にはdot関数を使う。

>>> A = np.array([[1,2],[3,4]])
>>> B = np.array([[5,6],[7,8]])
>>> np.dot(A,B)
array([[19, 22],
       [43, 50]])

なお,当然内積の計算ができるように,行列Aの1次元目と行列Bの0次元目の次元数は一致している必要がある。
では,続いてNumPy行列を使ってニューラルネットワークの実装を行う。
今回はバイアスと活性化関数は省略し,重みだけあるものとする。

>>> X = np.array([1,2])
>>> W = np.array([[1,3,5],[2,4,6]])
>>> Y = np.dot(X,W)
>>> print(Y)
[ 5 11 17]

この例では,入力x1とx2があり,出力はy1,y2,y3がある。
x1からy1〜3への重みがw1で,x2からy1〜3への重みがw2で表されている。

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

それでは実践的なニューラルネットワークの実装を行う。
ここで実装するのは3層のニューラルネットワークで,入力層は2つ,続いて3つ -> 2つの隠れ層があり,出力層は2つのニューロンから構成される。

入力層を1 x 2の行列X,重みを2 x 3の行列W,バイアスを1 x 3の行列Bとして表すと,
第1層(1つ目の隠れ層)の1 x 3行列Aは次のように表される。

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])

A1 = np.dot(X, W1) + B1
print(A1)
% python 3layer_nn.py
[ 0.3  0.7  1.1]

続いては第1層の活性化関数を見ていく。
隠れ層での重み付き和aに対し,h()で表される活性化関数により,出力zが得られる。
ここでは活性化関数としてシグモイド関数を使うことにし,出力zはそのまま次の第2層への入力になるので,
第1層目から2層目への実装は次のようになる。

import matplotlib.pylab as plt

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

Z1 = sigmoid(A1)
W2 = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2 = np.array([0.1,0.2])

A2 = np.dot(Z1, W2) + B2
print(A2)
% python 3layer_nn.py
[ 0.3  0.7  1.1]
[ 0.51615984  1.21402696]

ここまでは先程の実装とほぼ同じで,このA2が第2層(2つ目の隠れ層)への入力になる。
ここでの第2層での活性化関数も同様にシグモイド関数を使うと,Z2はsigmoid(A2)となり,これが最後の出力層への入力となるところも同じである。

出力層の実装もここまでとほぼおなじだが,最後の活性化関数だけが異なる。

def identity_function(x):
    return x

Z2 = sigmoid(A2)
W3 = np.array([[0.1,0.3],[0.2,0.4]])
B3 = np.array([0.1,0.2])

A3 = np.dot(Z2, W3) + B3
Y = identity_function(A3)

print("Y: ")
print(Y)
% python 3layer_nn.py
[ 0.3  0.7  1.1]
[ 0.51615984  1.21402696]
Y: 
[ 0.31682708  0.69627909]

出力層の活性化関数として,identity_function()を使用している。
上の例では,入力をそのまま出力する恒等関数を使っている。出力層の活性化関数はσ()で表し,中間層のh()とは異なることを示す。
なお,σ()は解く問題の性質に応じて決める。回帰問題では恒等関数,2クラス分類問題ではシグモイド関数…といった決め方になる。