実装関連事項

各種プログラミング言語の基本的な書き方やソフトウェア等の使用方法について.

Chainerのインストール

CUDA がインストールされているディレクトリを $HOME/local/cuda として,$HOME/local/cuda/include に cudnn.h,$HOME/local/cuda/lib64 に libcudnn.so* を置いている場合において,Chainer は以下のコマンドでインストールする.

$ CUDA_PATH=$HOME/local/cuda pip3 install chainer --no-cache-dir

最も基本的なChainerの実装

考えられ得る中でも極めてシンプルな例,以下のたったふたつのデータを学習させる.全データは,(1, 2, 3) という入力に対して (2, 5, 7) という教師ベクトルからなるひとつ目のデータ (インスタンス) と (2, 4, 5) という入力に対して (1, 1, 3) という教師ベクトルを持つふたつ目のデータからなる.

インプットターゲット
(1, 2, 3)(2, 5, 7)
(2, 4, 5)(1, 1, 3)

これらを以下のようなプログラムにおいて学習する.(1, 2, 3) が入力されたら (2, 5, 7) を,(2, 4, 5) が入力されたら (1, 1, 3) を出力するような予測器を作る.すなわち,これは回帰のためのプログラムとなる.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import chainer.functions as F
from chainer import Variable, FunctionSet, optimizers, serializers
np.random.seed(0)

def main():
	# Preparation of training data
	x=Variable(np.array([[1,2,3],[2,5,7]],dtype=np.float32))
	t=Variable(np.array([[2,4,5],[1,1,3]],dtype=np.float32))
	
	# Designing the structure of neural network
	model=F.Linear(3,3) # The structure of this neural network is of 2 layers and each layer has 3 units.
	optimizer=optimizers.SGD() # SGD stands for stochastic gradient descent. This is for finding directions, to which the weight value is moved.
	optimizer.setup(model)
	
	# Learning loop, the number of epoch is 3000
	for i in range(3000):
		optimizer.zero_grads() # Fills all gradient arrays by zeros.
		y=model(x) # This line calculates an output vector, which should correspond to the input vector.
		
		# These lines are for printing the progress of the calculation.
		print("Epoch: ",i+1,sep="")
		for j in range(2):
			print("Data ",j+1,": Input=",x.data[j],", Target=",t.data[j],", Output=",y.data[j],sep="")
		
		# This line calculates the difference between the output vector and target vector.
		loss=F.mean_squared_error(y,t)
		
		# This line is for learning based on the difference (loss function).
		loss.backward()
		optimizer.update()

if __name__ == '__main__':
	main()

最初の部分は Chainer の呼び出しに必要な記述.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import chainer.functions as F
from chainer import Variable, FunctionSet, optimizers, serializers
np.random.seed(0)

以下の9-11行ではデータの準備を行う.

	# Preparation of training data
	x=Variable(np.array([[1,2,3],[2,5,7]],dtype=np.float32))
	t=Variable(np.array([[2,4,5],[1,1,3]],dtype=np.float32))

以下の13-16行はニューラルネットワークの設計をするための記述.

	# Designing the structure of neural network
	model=F.Linear(3,3) # The structure of this neural network is of 2 layers and each layer has 3 units.
	optimizer=optimizers.SGD() # SGD stands for stochastic gradient descent. This is for finding directions, to which the weight value is moved.
	optimizer.setup(model)

以下の18-34行のラーニングループにおいて,20行目は勾配の初期化.Cheiner は勾配を計算した際にその値を上書きでなく,蓄積するような仕様らしく,そのため,新たな勾配を求めるときには zero_grads() で勾配行列の全要素を0で初期化しなければならない.21行目は入力ベクトルに対する出力ベクトルの計算.29行目は出力ベクトルとそれに対応する教師ベクトルの比較 (損失関数の計算)..32行目は損失関数を微分して,重み行列の各値を動かす方向 (今より大きくするのか小さくするのか) を決定するための計算 (勾配降下法の計算) のための記述.33行目は得られた向きに従って重み行列を更新するための記述.これらは何度も繰り返され,損失関数が変化しなくなったと判断されたら計算が終了する.

	# Learning loop, the number of epoch is 3000
	for i in range(3000):
		optimizer.zero_grads() # Fills all gradient arrays by zeros.
		y=model(x) # This line calculates an output vector, which corresponds to the input vector.
		
		# These lines are for printing the progress of the calculation.
		print("Epoch: ",i+1,sep="")
		for j in range(2):
			print("Data ",j+1,": Input=",x.data[j],", Target=",t.data[j],", Output=",y.data[j],sep="")
		
		# This line calculates the difference between the output vector and target vector.
		loss=F.mean_squared_error(y,t)
		
		# This line is for learning based on the difference (loss function).
		loss.backward()
		optimizer.update()

このプログラムを実行した結果は以下のようになる.最初は,教師ベクトル (Target) と出力ベクトル (Output) の値は全く似ていないが,パラメーター更新 (epoch) を経るに従い,かなり近い値になることが確認できる.

Epoch: 1
Data 1: Input=[ 1.  2.  3.], Target=[ 2.  4.  5.], Output=[ 3.1757617   1.75755572  0.19498125]
Data 2: Input=[ 2.  5.  7.], Target=[ 1.  1.  3.], Output=[ 7.14762878  4.02911472  0.24298292]
Epoch: 2
Data 1: Input=[ 1.  2.  3.], Target=[ 2.  4.  5.], Output=[ 2.42024255  1.52637851  0.74769413]
Data 2: Input=[ 2.  5.  7.], Target=[ 1.  1.  3.], Output=[ 5.39550066  3.48559237  1.51356626]
Epoch: 3
Data 1: Input=[ 1.  2.  3.], Target=[ 2.  4.  5.], Output=[ 1.90107358  1.36835885  1.12877202]
Data 2: Input=[ 2.  5.  7.], Target=[ 1.  1.  3.], Output=[ 4.19039106  3.11139679  2.38692188]
.
.
.
Epoch: 2999
Data 1: Input=[ 1.  2.  3.], Target=[ 2.  4.  5.], Output=[ 1.94350708  3.86448908  4.8621006 ]
Data 2: Input=[ 2.  5.  7.], Target=[ 1.  1.  3.], Output=[ 1.02440882  1.05855131  3.05958247]
Epoch: 3000
Data 1: Input=[ 1.  2.  3.], Target=[ 2.  4.  5.], Output=[ 1.94356549  3.86462879  4.8622427 ]
Data 2: Input=[ 2.  5.  7.], Target=[ 1.  1.  3.], Output=[ 1.02438366  1.05849075  3.05952072]
Hatena Google+