新着情報
Neural Network Classのインスタント化
pythonによるNeuralNetworkをクラスで実装する:
実装するpythonのNeuralNetwork classは入力層(第0層)、隠れ層(第1層)、出力層(第2層)から成る2層構造のNeuralNetworkを考える。
ニューラル・ネットワークをNeuralNetwork classによって実装することにする。NeuralNetworkの実現には
ネットワークの作成、重みの更新、ネットワークへの照会という異なる処理が必要となる。まず、
class NeuralNetwork:
def _ _init_ _( ): コンストラクタ(初期化)・メソッド
ここで、入力層、隠れ層、出力層のneuronの数と学習率をインスタンス変数に代入し、ニューラル・ネットワークの 初期化をする。
def weight_initialize( ): 重みの初期化をするメソッド。
def activation_function( ): シグモイド関数を実装するメソッド。
def train( ):訓練データを読み込み、最適な重みを計算するメソッド。
def evaluate( ): 更新された重みを用いてテストデータを評価するメソッド。
import numpy as np class neuralNetwork: # ニューラルネットワークの初期化 def __init__(self, input_neurons, # 入力層のニューロン数 hidden_neurons, # 隠れ層のニューロン数 output_neurons, # 出力層のニューロン数 learning_rate # 学習率 ): # 入力層、隠れ層、出力層のニューロン数をインスタンス変数に代入 self.inneurons = input_neurons # 入力層のニューロン数 self.hneurons = hidden_neurons # 隠れ層のニューロン数 self.oneurons = output_neurons # 出力層のニューロン数 # 学習率をインスタンス変数に代入 self.lr = learning_rate # weight_initialize()を呼ぶ self.weight_initialize() # 重みの初期化を行う def weight_initialize(self): # 入力層と隠れ層の間のリンクの重みの初期値を設定 self.w_h = np.random.normal(0.0, # 平均は0 pow(self.inneurons, -0.5), # 標準偏差は入力層のニューロン数を元に計算 (self.hneurons, # 隠れ層のニューロン数を行数 self.inneurons + 1) # バイアスを加え、列数とする ) # 隠れ層と出力層の間のリンクの重みの初期値を設定 self.w_o = np.random.normal(0.0, # 平均は0 pow(self.hneurons, -0.5), # 標準偏差は隠れ層のニューロン数を元に計算 (self.oneurons, # 出力層のニューロン数を行数 # 隠れ層のニューロン数に self.hneurons + 1) # バイアスを加え、列数とする ) # シグモイド関数を活性化関数として定義 def activation_function(self, x): return 1 / (1 + np.exp(-x)) # ニューラルネットワークの学習を行うメソッド def train(self, inputs_list, # 入力値の配列 targets_list # 目標出力の配列 ): # 入力値の配列にバイアス項を追加して1列の行列に変換 inputs = np.array( np.append(inputs_list, [1]), # 配列の末尾にバイアスのための値「1」を追加 ndmin=2 # 2次元化 ).T # 転置して1列の行列にする # 目標値の配列を1列の行列に変換する targets = np.array(targets_list, # 目標値の配列 ndmin=2 # 2次元化 ).T # 転置して1列の行列にする # 隠れ層への入力信号を計算 hidden_inputs = np.dot(self.w_h, # 入力層と隠れ層の間の重み inputs # 入力値の行列 ) # 活性化関数を適用して隠れ層から出力する hidden_outputs = self.activation_function(hidden_inputs) # 隠れ層の出力行列の末尾にバイアスの値として1を追加 hidden_outputs = np.append(hidden_outputs, # 隠れ層の出力行列 [[1]], # 2次元形式でバイアス値を追加 axis=0 # 行を指定(列は1) ) # 出力層への入力信号を計算 final_inputs = np.dot(self.w_o, # 隠れ層と出力層の間の重み hidden_outputs # 隠れ層の出力 ) # 活性化関数を適用して出力層から出力する final_outputs = self.activation_function(final_inputs) # 目標値と出力層の出力信号の誤差を求める output_errors = targets - final_outputs # 誤差逆伝播により隠れ層の誤差を求める hidden_errors = np.dot(self.w_o.T, # 隠れ層と出力層の間の重み行列を転置する output_errors # 出力値と目標値との誤差 ) # 隠れ層と出力層の間の重みの更新 self.w_o += self.lr * np.dot( # 出力誤差*出力信号* (1-出力信号) (output_errors * final_outputs * (1.0 - final_outputs)), # 出力信号の行列を転置 np.transpose(hidden_outputs) ) # 隠れ層の出力エラーからバイアスのものを取り除く hidden_errors_nobias = np.delete( hidden_errors, # 隠れ層の出力エラーの行列 self.hneurons, # バイアスを除くニューロン数をインデックスにする axis=0 # 行の削除を指定 ) # 隠れ層の出力からバイアスを取り除く hidden_outputs_nobias = np.delete( hidden_outputs, # 隠れ層の出力の行列 self.hneurons, # バイアスを除くニューロン数をインデックスにする axis=0 # 行の削除を指定 ) # 入力層と隠れ層の間の重みの更新 self.w_h += self.lr * np.dot( # 隠れ層の出力誤差*隠れ層の出力* (1-隠れ層の出力) (hidden_errors_nobias * hidden_outputs_nobias * ( 1.0 - hidden_outputs_nobias)), # 入力層の出力信号の行列を転置 np.transpose(inputs)) # 学習結果を元にテストデータを評価するメソッド def evaluate(self, inputs_list # テスト用データの配列 ): # テスト用データの配列を1列の行列に変換する inputs = np.array( np.append(inputs_list, [1]), # 配列の末尾にバイアスの値「1」を追加 ndmin=2 # 2次元化 ).T # 転置して1列の行列にする # 隠れ層への入力信号を計算 hidden_inputs = np.dot(self.w_h, # 入力層と隠れ層の間の重み inputs # テストデータの行列 ) # 活性化関数を適用して隠れ層から出力する hidden_outputs = self.activation_function(hidden_inputs) # 出力層への入力信号を計算 final_inputs = np.dot( self.w_o, # 隠れ層と出力層の間の重み np.append(hidden_outputs, [1]), # 隠れ層の出力配列の末尾にバイアスの値「1」を追加 ) # 活性化関数を適用して出力層から出力する final_outputs = self.activation_function(final_inputs) # 出力層からの出力を戻り値として返す return final_outputs
neuralNetworkクラスをインスタンス化して、train()メソッドで手書き数字の訓練データの学習を行う。