<目次>
多層パーセプトロンをPythonで実装した例をご紹介
(1-1) 実装のフロー
(1-2) サンプルプログラム
多層パーセプトロンをPythonで実装した例をご紹介
(1-1) 実装のフロー
●STEP0:モデル基本情報
\r\n●STEP1:モデルの定義
●STEP2:誤差関数の定義
●STEP3:最適化手法の定義(例:勾配降下法)
●STEP4:セッションの初期化
●STEP5:学習
>目次にもどる\r\n
(1-2) サンプルプログラム
import numpy as np
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from sklearn.utils import shuffle
import matplotlib.pyplot as plt
# 入力層xの次元
M = 2
# 隠れ層の次元
J = 2
# 出力層yの次元(クラス数)
K = 1
# 入力データセットの総
nc = 4
# 入力データセットの総数
N = nc * K
def multi_layer_perceptron(X_arg,t_arg):
############################################
# STEP1:モデルの定義
############################################
# 入力の電気信号Xの初期化
X = tf.constant(X_arg, dtype = tf.float64, shape=[N,M])
xn = tf.Variable(tf.zeros([M,1],tf.float64),dtype = tf.float64, shape=[M,1])
# 重みWの定義
W = tf.Variable(tf.zeros([J,M],tf.float64), dtype = tf.float64, shape=[J,M])
# バイアスbの定義 (※データはn個でも1つのbを更新)
b = tf.Variable(tf.zeros([J,1],tf.float64), dtype = tf.float64, shape=[J,1])
# 隠れ層の出力(シグモイド関数):h = σ(Wx + b)の定義 (※データはn個でも1つのyを更新)
h = tf.Variable(tf.zeros([J,1],tf.float64), dtype = tf.float64, shape=[J,1])
# 重みVの定義
V = tf.Variable(tf.zeros([K,J],tf.float64), dtype = tf.float64, shape=[K,J])
# バイアスcの定義 (※データはn個でも1つのbを更新)
c = tf.Variable(tf.zeros([K,1],tf.float64), dtype = tf.float64, shape=[K,1])
# 出力層の出力(ソフトマックス関数):y = softmax(Vh + c)の定義 (※データはn個でも1つのyを更新)
y = tf.Variable(tf.zeros([K,1],tf.float64), dtype = tf.float64, shape=[K,1])
# 出力層の正解値tの定義
t = tf.Variable(t_arg, dtype = tf.float64, shape=[N,K])
# 重みWの勾配(∂E(W,V,b,c)/∂W)の定義
dW = tf.Variable(tf.zeros([J,M],tf.float64), dtype = tf.float64, shape=[J,M])
# バイアスbの勾配(∂E(W,V,b,c)/∂b)の定義
db = tf.Variable(tf.zeros([J,1],tf.float64), dtype = tf.float64, shape=[J,1])
# 重みVの勾配(∂E(W,V,b,c)/∂V)の定義
dV = tf.Variable(tf.zeros([K,J],tf.float64), dtype = tf.float64, shape=[K,J])
# バイアスcの勾配(∂E(W,V,b,c)/∂c)の定義
dc = tf.Variable(tf.zeros([K,1],tf.float64), dtype = tf.float64, shape=[K,1])
# 学習率ηの定義
eta = 0.1
# Epoc数の定義
epocs = 1000
############################################
# STEP4:セッションの初期化
############################################
# ⇒今回は不要
# (TensorFlow v2以降はSessionを使用しないため)
############################################
# STEP5:学習
############################################
for epoc in range(epocs):
# バッチのデータ数だけ繰り返し
for n in range(N):
# データをシャッフル
#X_,t_ = shuffle(X.numpy(),t.numpy())
X_,t_ = X.numpy(),t.numpy()
# 取り出したX_[n]を転置してxnに格納(Mx1)
xn.assign(tf.transpose([X_[n]]))
############################################
# STEP2:誤差関数の定義
############################################
# ⇒今回は不要
# (確率的勾配降下法の最終式を使うため、誤差関数Eは計算不要)
############################################
# STEP3:最適化手法の定義(例:勾配降下法)
############################################
# 隠れ層の出力(シグモイド関数):h = σ(wx + b)の計算
# h[J,1] = sigmoid( W[J×M] × X[M×1] + b[J×1] )
# reshapeで[J]に変換してsigmoidしたのち、再度[J,1]に戻して行列計算できる形に戻す。
h.assign( tf.reshape( tf.nn.sigmoid(tf.reshape(tf.matmul(W,xn)+b,[J])),[J,1]).numpy() )
# 出力層(シグモイド関数):y = σ(Wx + b)の計算
# y[K,1] = sigmoid( V[K×J] × h[J×1] + c[K×1] )
# reshapeで[K]に変換してsigmoidしたのち、再度[K,1]に戻して行列計算できる形に戻す。
y.assign( tf.reshape( tf.nn.sigmoid(tf.reshape(tf.matmul(V,h)+c,[K])),[K,1]).numpy() )
# ※出力yが多クラスの場合はsoftmaxを使う
# y[K,1] = softmax( V[K×J] × h[J×1] + c[K×1] )
# reshapeに関しては、softmax関数の引数が[K]の形式でないと適切に動かない為に使用している。
# reshapeで[K]に変換してsoftmaxしたのち、再度[K,1]に戻して行列計算できる形に戻す。
#y.assign( tf.reshape( tf.nn.softmax(tf.reshape(tf.matmul(V,h)+c,[K])),[K,1]).numpy() )
# 重みvの勾配(∂E(W,V,b,c)/∂V)の計算
# δK*h[K,J] = dV[K,J] += ( tn[K×1](転置) - y[K×1] ) × hn[1×J](転置)
dV.assign(tf.matmul((tf.transpose([t_[n]])-y),tf.transpose(h)).numpy())
# バイアスcの勾配(δK[K,1] = ∂E(W,V,b,c)/∂c)の計算
dc.assign( tf.transpose([t_[n]])-y )
# dwj[1,M] += { σ'(pj) × Σ[k=1...K]vkj*δk } * xn
# dwj[1,M] += { σ(pj)*(1 - σ(pj)) × Σ[k=1...K](vkj*δk) } × xn
# dwj[1,M] += { σ(wj*xn+b)[1×1]*( 1[1×1] - σ(wj*xn+b)[1×1]) × Σ[k=1...K](vkj[1×1] * δk[1×1]) } × xn[1×M]
# dW[J,M] += { σ(Wj*xn+b)[J×1]*( I[J×1] - σ(W*xn+b)[J×1]) × (V[J×K](転置) × δK[K×1]) } × xn[1×M]
# dW[J,M] += { sigmoid(W*xn+b)[J×1]*(I[J×1]-sigmoid(W*xn+b)[J×1]) × {matmul(V[J×K](転置),δK[K×1])} } × xn[1×M](転置) (※k=1...K)
# σ(pj)*(1 - σ(pj)) = sigmoid(W*xn+b)[J×1]*(I[J×1]-sigmoid(W*xn+b)[J×1]) ⇒[J×1]
I = tf.Variable(tf.ones([J,1],tf.float64), dtype = tf.float64, shape=[J,1])
dfp = tf.math.multiply( h,(I - h) )
# V[J×K](転置) × δK[K×1] ⇒[J×1]
dEdq_vkj = tf.matmul(tf.transpose(V),dc)
# 重みwの勾配(∂E(W,V,b,c)/∂W)の計算
dW.assign( tf.matmul( tf.math.multiply(dfp,dEdq_vkj),tf.transpose(xn)) )
# バイアスbの勾配(∂E(W,V,b,c)/∂b)の計算
db.assign( tf.math.multiply(dfp,dEdq_vkj) )
# コンソール出力
decimals = 4
print("Epoc= ", epoc+1,
"No. = ", n,
"\r\n\t x1,x2 \t\t=", np.array_repr(np.round(X[n].numpy(),decimals)),
"\r\n\t t \t\t=", np.array_repr(np.round(t[n].numpy(),decimals)),
"\r\n\t w1,w2 \t\t=", np.array_repr(np.round(W.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t b \t\t=", np.array_repr(np.round(b.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t h1,h2 \t\t=", np.array_repr(np.round(h.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t v1,v2 \t\t=", np.array_repr(np.round(V.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t c \t\t=", np.array_repr(np.round(c.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t y \t\t=", np.array_repr(np.round(y.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t dv1,dv2 \t=", np.array_repr(np.round(dV.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t dc \t\t=", np.array_repr(np.round(dc.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t dw1,dw2 \t=", np.array_repr(np.round(dW.numpy(),decimals)).replace('\n', '').replace(' ', ''),
"\r\n\t db \t\t=", np.array_repr(np.round(db.numpy(),decimals)).replace('\n', '').replace(' ', ''),
)
# 重みVの再計算
V.assign_add( tf.math.scalar_mul(eta,dV) )
# バイアスbの再計算
c.assign_add( tf.math.scalar_mul(eta,dc) )
# 重みWの再計算
W.assign_add( tf.math.scalar_mul(eta,dW) )
# バイアスbの再計算
b.assign_add( tf.math.scalar_mul(eta,db) )
def main():
# 初期値を設定し学習実行
# テスト用データセット
X = [[0,0],[0,1],[1,0],[1,1]]
t = [[0],[1],[1],[0]]
multi_layer_perceptron(X,t)
if __name__ == "__main__":
main()

(例)出力結果
Epoc= 1000 No. = 1
x1,x2 = array([0., 1.])
t = array([1.])
w1,w2 = array([[-0.254,-0.476],[-0.254,-0.476]])
b = array([[-0.4944],[-0.4944]])
h1,h2 = array([[0.2748],[0.2748]])
v1,v2 = array([[-0.0975,-0.0975]])
c = array([[-0.0029]])
y = array([[0.4859]])
dv1,dv2 = array([[0.1413,0.1413]])
dc = array([[0.5141]])
dw1,dw2 = array([[0.,-0.01],[0.,-0.01]])
db = array([[-0.01],[-0.01]])
Epoc= 1000 No. = 2
x1,x2 = array([1., 0.])
t = array([1.])
w1,w2 = array([[-0.254,-0.477],[-0.254,-0.477]])
b = array([[-0.4954],[-0.4954]])
h1,h2 = array([[0.321],[0.321]])
v1,v2 = array([[-0.0834,-0.0834]])
c = array([[0.0485]])
y = array([[0.4987]])
dv1,dv2 = array([[0.1609,0.1609]])
dc = array([[0.5013]])
dw1,dw2 = array([[-0.0091,0.],[-0.0091,0.]])
db = array([[-0.0091],[-0.0091]])
Epoc= 1000 No. = 3
x1,x2 = array([1., 1.])
t = array([0.])
w1,w2 = array([[-0.2549,-0.477],[-0.2549,-0.477]])
b = array([[-0.4963],[-0.4963]])
h1,h2 = array([[0.2265],[0.2265]])
v1,v2 = array([[-0.0673,-0.0673]])
c = array([[0.0986]])
y = array([[0.517]])
dv1,dv2 = array([[-0.1171,-0.1171]])
dc = array([[-0.517]])
dw1,dw2 = array([[0.0061,0.0061],[0.0061,0.0061]])
db = array([[0.0061],[0.0061]])