Pythonで機械学習 3層ニューラルネットワーク Part(5)

colaboratory

はじめに

こんにちわ、swim-loverです。 Pythonで機械学習の一つである手書き数字認識を実装しています。Pythonを始めたばかりですが、「使いながら覚える」をコンセプトに勉強しています。 第4回は、 numpyで行列演算を行い、簡単なニューラルネットを作ってみました。 今回は、さらに内容を進めて、3層ニューラルネットを作ってみたいと思います。

参考書籍について

今回、機械学習の参考書籍として、”斎藤康毅著 ゼロから作るDeep Learning オライリージャパン 2016年9月”を使用しました。 

3層ニューラルネットワークについて

3層ニューラルネットワークの図になります。層の数を数えるときは、入力層は、カウントしないようです。

行列演算

行列演算を行うため、各箇所に記号をつけます。この図ではバイアス要素である”1”を追加しています。のちのち役に立つとして進みます。

記号の数字のつけ方は、参考書籍のつけ方とは逆に変えてみました。W11の場合、前の1を前層の番号、後ろの1を次層の番号にしました。矢印の向きと合っている方が個人的には好みです。

Python実行環境は、google colaboratotyを使用します。

import numpy as np
x = np.array([1,2])#1行2列
print("x={}".format(x))

#1st layer
w11=1;w12=2;w13=3;w14=4;w15=5;w16=6
w1 = np.array([[w11,w12,w13],[w14,w15,w16]])#2行3列
print("w1={}".format(w1))
b11=1;b12=2;b13=3;
b1 = np.array([b11,b12,b13])#2行3列
print("b1={}".format(b1))
#calc 1st layer
a1 = np.dot(x,w1)+b1
print("a1={}".format(a1))

出力行列a1を得るには、xとw1の積を行います。dot(x,w1)にて行います。さらにb1を加算します。行列式は次のような演算を想定しています。

行列a1が得られたら、a1を入力として活性化関数h(x)を処理します。活性化関数とは神経細胞の発火を数式で表現したものといえるかもしれません。ニューラルネットワークでは、シグモイド関数(sigmoid function)が良く用いられるようです。 隠れ層1での活性化処理を拡大した図と 式を載せてみます。

シグモイド関数をpythonで記述すると以下のようになります。ここで初めて関数を作ってみました。

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

ついでにグラフを書いてみたいと思います。Plotはmatplotlibをimportします。

import matplotlib.pyplot as plt
x=np.arange(-5,5,0.1)
y=sigmoid(x)
plt.plot(x,y)
plt.show()

シグモイド関数を処理します。これで第一層の処理ができました。

#input sigmoid 
z1=sigmoid(a1)
print("z1={}".format(z1))

ここまでの処理結果です。

x=[1 2]
w1=[[1 2 3]
 [4 5 6]]
b1=[1 2 3]
a1=[10 14 18]
z1=[0.9999546  0.99999917 0.99999998]

次に第2層の処理です。入力がxからz1に代わっているだけで、第1層の処理と何も変わりません。ただし、第2層は出力が二つなので、重み係数w2が3行2列、バイアスb2が1行2列になっています。

#2nd layer
w21=1;w22=2;w23=3;w24=4;w25=5;w26=6;
w2 = np.array([[w21,w22],[w23,w24],[w25,w26]])#3行2列
b21=1;b22=2;
b2 = np.array([b21,b22])#1行2列
#calc 2nd layer
a2 = np.dot(z1,w2)+b2
print("a2={}".format(a2))
z2=sigmoid(a2)
print("z2={}".format(z2))

続けて第3層も実装します。第3層の出力はニューラルネットそのものの出力yになります。この場合の活性化関数はシグモイド関数ではなく、入力をそのまま出力するようです。書籍では、恒等関数を定義していますが、ここでは、y=a3としておきます。

#3rd layer
w31=1;w32=2;w33=3;w34=4;
w3 = np.array([[w31,w32],[w33,w34]])#2行2列
b31=1;b32=2;
b3 = np.array([b31,b32])#1行2列
#calc 3nd layer
a3 = np.dot(z2,w3)+b3
y=a3
print("a3={}".format(a3))

出力yの結果になります。

x=[1 2]
w1=[[1 2 3]
 [4 5 6]]
b1=[1 2 3]
a1=[10 14 18]
z1=[0.9999546  0.99999917 0.99999998]
a2=[ 9.99995203 13.99990579]
z2=[0.9999546  0.99999917]
y=[4.99995211 7.99990587]

まとめ

3層ニューラルネットワークをpythonで実装してみましたが、処理全体を関数化して、スッキリさせた方が、後々のコード再利用の観点からすると望ましいです。これは次回以降に改良したいとおもいます。今回、Pythonでの

・関数の作成方法 C言語にくらべると驚くほど非常に簡単に書けます。関数プロトタイプ宣言のような面倒な記述も不要でした。

・グラフの書き方  google colaboratotyで実行しているので、グラフもブラウザで表示されました。

も学ぶことができました。 

コメント

タイトルとURLをコピーしました