前回考えたニューラルネットワークモデルをPythonで実装することによりイメージをつかみます。
イメージ概要
前回考えたニューラルネットワークモデルに少し修正をしたイメージです。

データの準備の実装
データの説明
まずはニューラルネットワークにかけるデータの準備を行います。
基本データは以前の分類に用いた「アヤメの品種データ」を使います。
※データ自体はなんでもよいです。
■説明変数
| 0 | sepal length (cm) | がく片の長さ |
|---|---|---|
| 2 | petal length (cm) | 花弁の長さ |
今回はがく片の長さと花弁の長さを使ってみます。
■目的変数
3クラスに分類するという点だけ抑えておけばよいです。
| 0 | setosa(ヒオウギアヤメ) |
|---|---|
| 1 | versicolor(ブルーフラッグ) |
| 2 | virginica(バージニカ) |
データの保存
scikit-learnからデータを抜いてきてファイルに保存するところまで。
# データ準備
import numpy as npy
import matplotlib.pyplot as plt
%matplotlib inline
# アヤメ品種データの読み込み
from sklearn.datasets import load_iris
iris_data = load_iris()
# 説明変数
X_array = iris_data.data
# カラムデータを取得
X0=X_array[:,0]
X1=X_array[:,3]
# 目的変数
t_array = iris_data.target
T=t_array
N=len(X0)
petal_data=npy.zeros((N,2))
T3 = npy.zeros((N,3), dtype=npy.uint8)
#データの設定
for i in range(N):
petal_data[i]=[X0[i], X1[i]]
# 0[1,0,0] 1[0,1,0] 2[0,0,1]
if T[i] == 0:
T3[i]=[1,0,0]
elif T[i] == 1:
T3[i]=[0,1,0]
else:
T3[i]=[0,0,1]
X_range0=[min(X0)*0.9,max(X0)*1.1]
X_range1=[min(X1)*0.9,max(X1)*1.1]
# データをclassdata3.npzファイルに保存する
npy.savez('neural_rawdata.npz',X=petal_data,T3=T3,X_range0=X_range0,X_range1=X_range1,X_n=N)
訓練データとテストデータに分割
今回はデータを訓練データと検証のためのテストデータに分けてみます。
データセットは150個のデータが50個ごとにクラス1、2、3の順にならんでいるので各クラスから25個をそれぞれ訓練データとテストデータに分割しました。
・実装
# 生データファイルから取り出す
sample_data = npy.load('neural_rawdata.npz')
# 入力値の設定
X=sample_data['X']
# がく片の長さの表示範囲設定
X_range0=sample_data['X_range0']
# 花弁の長さの表示範囲設定
X_range1=sample_data['X_range1']
# クラス(答え)の設定
T3=sample_data['T3']
# データの並び替え
X1 = X[:50,:]
X2 = X[50:100,:]
X3 = X[100:150,:]
npy.random.shuffle(X1)
npy.random.shuffle(X2)
npy.random.shuffle(X3)
X_test=npy.r_[X1[:25,:], X2[:25,:], X3[:25,:]]
X_train=npy.r_[X1[25:50,:],X2[25:50,:],X3[25:50,:]]
T_test=npy.r_[T3[:25,:], T3[50:75,:], T3[100:125,:]]
T_train=npy.r_[T3[25:50,:],T3[75:100,:],T3[125:150,:]]
npy.savez('neural_data.npz',X_train=X_train, T_train=T_train,X_test=X_test,T_test=T_test,X_range0=X_range0,X_range1=X_range1)
データのプロット
分割した訓練データとテストデータをグラフ上にプロットします。
・実装例
import matplotlib.pyplot as plt
%matplotlib inline
# データの表示
def Show_data(x,t):
wk,n=t.shape
c=[[0,0,0],[.5,.5,.5],[1,1,1]]
for i in range(n):
plt.plot(x[t[:,i]==1,0],x[t[:,i]==1,1],linestyle='none',marker='o',markeredgecolor='black',color=c[i],alpha=0.8)
plt.grid(True)
plt.figure(1,figsize=(8,3.7))
plt.subplot(1,2,1)
Show_data(X_train,T_train)
plt.xlim(X_range0)
plt.ylim(X_range1)
plt.title('Training Data')
plt.subplot(1,2,2)
Show_data(X_test,T_test)
plt.xlim(X_range0)
plt.ylim(X_range1)
plt.title('Test Data')
plt.show()・出力結果

訓練データとテストデータがそれぞれ違うデータで表示されていればとりあえずOK。
ニューラルネットワークの実装
シグモイド関数の実装
ニューラルネットワーク内で使用されるシグモイド関数を先に実装しておきます。
・シグモイド関数

・実装例
# シグモイド関数
def Sigmoid(x):
y=1/(1+npy.exp(-x))
return y
ニューラルネットワークの実装
# ニューラルネットワーク(wv重み、M中間層ノード数、K出力層ノード数、x入力層の入力値)
def FNN(wv, M, K, x):
# Nデータ数 Dデータの入力次元
N, D = x.shape
# w 入力層⇒中間層の重み
w = wv[:M * (D+1)]
w = w.reshape(M,(D+1))
# v 中間層⇒出力層の重み
v = wv[M*(D+1):]
v = v.reshape((K,M+1))
# b 中間層の入力総和
b = npy.zeros((N,M+1))
# z 中間層の出力値
z = npy.zeros((N,M+1))
# a 出力層の入力総和
a = npy.zeros((N,K))
# y 出力層の出力値
y = npy.zeros((N,K))
# データごとに中間層、出力層の計算を行う
for n in range(N):
# 中間層の計算(シグモイド関数)
for m in range(M):
b[n,m] = npy.dot(w[m,:],npy.r_[x[n,:],1])
z[n,m] = Sigmoid(b[n,m])
# ダミーニューロン
z[n,M]=1
u=0
# 出力層の計算(ソフトマックス関数)
for k in range(K):
a[n,k] = npy.dot(v[k,:],z[n,:])
u = u + npy.exp(a[n,k])
for k in range(K):
y[n,k] = npy.exp(a[n,k])/u
return y,a,z,b
# テスト実行
WV = npy.ones(15)
M = 2
K = 3
FNN(WV,M,K,X_train[:2,:])WV(中間層と出力層の重み)と中間層のノード数(M)、出力層のノード数(K)、入力値(X)をニューラルネットワークに渡して戻り値として各層の出力値と入力総和を返します。
中間層での計算は先ほど実装したシグモイド関数を適用します。
出力層の計算にはソフトマックス関数を適用するので、ニューラルネットワーク内で合計値(u)を求めて各値を割ることで出力値とします。

・テスト実行
テスト実行なので、重みは全て1としています。
入力値については訓練データの頭2つのデータを適用しています。
・出力結果
(array([[0.33333333, 0.33333333, 0.33333333],
[0.33333333, 0.33333333, 0.33333333]]),
array([[2.9955243 , 2.9955243 , 2.9955243 ],
[2.99396317, 2.99396317, 2.99396317]]),
array([[0.99776215, 0.99776215, 1. ],
[0.99698158, 0.99698158, 1. ]]),
array([[6.1, 6.1, 0. ],
[5.8, 5.8, 0. ]]))
注目すべきは最終的な出力結果となる「y」ですが、テスト実行で重みパラメータが全て1なので確率が全ての「0.33」となっています。
なので、現時点では有効に活用できておらず、重みの設定の重要性が分かります。
重みの設定ができていないとニューラルネットワークがあっても活用することはできないので、次回は最適な重みを設定することを検討します。
・今回のソース
python_dev/Neural_net1_prod.ipynb at master · wantanblog/python_dev · GitHub