chainerを使ってsin関数を近似してみようとした

Deep Learningのフレームワークの１つである[chainer](http://chainer.org/)を使って勉強がてらsin関数を近似しようとしてみたけどダメだった。chainerのexampleにあるmnistをちょこちょこ書き換えただけのコード。データセットが悪いのか、学習プロセスでバグがあるのかわからない。指摘していただけるとすごくうれしい。

まずはデータセットの作成から

```lang:make_dataset.py
def make_dateset():
	x_train = np.arange(0,3.14*50.0,0.05)
	y_train = np.sin(x_train).astype(np.float32)
	x_test  = np.arange(3.14*50.0,3.14 * 60.0,0.05)
	y_test = np.sin(x_test).astype(np.float32)
	return x_train.astype(np.float32),y_train.astype(np.float32),x_test.astype(np.float32),y_test.astype(np.float32)

```

x_trainにはnp.arrayで０から3.14*50までの0.05刻みで数字が入っている
ex) [0.0,0.05,0.10,......,157.0]

y_trainにはsin関数にx_trainを代入した値が入っている。
ex) [0.0,0.47942553860420301,0.09983341......,]

x_test,y_testも同じような感じ。範囲が違うだけ

```lang:sin_test.py
import numpy as np
import six
import chainer
from chainer import computational_graph as c
from chainer import cuda
import chainer.functions as F
from chainer import optimizers
import matplotlib.pyplot as plt
import csv

def make_dateset():
	x_train = np.arange(0,3.14*50.0,0.05)
	y_train = np.sin(x_train).astype(np.float32)
	x_test  = np.arange(3.14*50.0,3.14 * 60.0,0.05)
	y_test = np.sin(x_test).astype(np.float32)
	return x_train.astype(np.float32),y_train.astype(np.float32),x_test.astype(np.float32),y_test.astype(np.float32)


	
def forward(x_data,y_data,train = True):
	x,t = chainer.Variable(x_data),chainer.Variable(y_data)
	h1 = F.dropout(F.relu(model.l1(x)),  train=train)
	h2 = F.dropout(F.relu(model.l2(h1)),  train=train)
        h3 = F.dropout(F.relu(model.l3(h1)),  train=train)
	y = model.l4(h3)
	return F.mean_squared_error(y,t),y


if __name__ == "__main__":
	
	x_train,y_train,x_test,y_test = make_dateset()
	x_train,y_train = x_train.reshape(len(x_train),1),y_train.reshape(len(y_train),1)
	x_test,y_test = x_test.reshape(len(x_test),1),y_test.reshape(len(y_test),1)
	y_t,y_p,ll = [],[],[]
	
	xp = np

	batchsize = 10
	N = len(x_train)
	N_test = len(x_test)
	n_epoch = 100
	n_units = 20
	pred_y = []

	model = chainer.FunctionSet(l1=F.Linear(1, n_units),
								l2=F.Linear(n_units, n_units),
								l3=F.Linear(n_units, u_units)),
                                                                l4=F.Linear(n_units, 1))
	optimizer = optimizers.Adam()
	optimizer.setup(model.collect_parameters())



	x_t,y_t,y_p = [],[],[]

	for epoch in six.moves.range(1, n_epoch + 1):
		print('epoch', epoch)

		perm = np.random.permutation(N)
		sum_loss = 0

		for i in six.moves.range(0, N, batchsize):
			x_batch = xp.asarray(x_train[perm[i:i + batchsize]])
			y_batch = xp.asarray(y_train[perm[i:i + batchsize]])

			optimizer.zero_grads()
			loss,y = forward(x_batch, y_batch)
			loss.backward()
			optimizer.update()
			sum_loss += float(cuda.to_cpu(loss.data)) * len(y_batch)
		print "train mean loss = ",sum_loss/N 
		
		sum_loss = 0
		for i in six.moves.range(0, N_test, batchsize):
			x_batch = xp.asarray(x_test[i:i + batchsize])
			y_batch = xp.asarray(y_test[i:i + batchsize])
			loss, y = forward(x_batch, y_batch, train=False)
                        #デバック用
			#y_t.append(y_batch[0])
			#y_p.append(y.data[0])
			#x_t.append(x_batch[0])
			sum_loss += float(cuda.to_cpu(loss.data)) * len(y_batch)
		print "test mean loss is ",sum_loss/N_test
    #デバック用
	#f = open('sin_pre.csv','ab')
	#csvWriter = csv.writer(f)
	#csvWriter.writerow(y_p)
	#f.close()

	#f = open('sin_ans.csv','ab')
	#csvWriter = csv.writer(f)
	#csvWriter.writerow(y_t)
	#f.close()

```
最初のx_train,y_train,x_test,y_testはN*1行列に変換している。(chainerのVariableに渡せるようにするため)
あとはmnistのサンプルとほとんど同じ。違う所は回帰問題なのでForward()関数でmean_squared_error(平均二乗誤差関数)を使ってlossを求めている。あとはネットワーク構成が1-20-20-1になっている。

```lang:実行結果(epoch10まで)
('epoch', 1)
train mean loss =  2553.66754833
test mean loss is  127.272548827
('epoch', 2)
train mean loss =  401.413729346
test mean loss is  5.86524515122
('epoch', 3)
train mean loss =  138.270190761
test mean loss is  4.34996299998
('epoch', 4)
train mean loss =  68.4881465446
test mean loss is  0.659433874475
('epoch', 5)
train mean loss =  38.2469408746
test mean loss is  0.640729590383
('epoch', 6)
train mean loss =  24.6955423482
test mean loss is  0.529370371471
('epoch', 7)
train mean loss =  16.3685227446
test mean loss is  0.505678843091
('epoch', 8)
train mean loss =  11.0349840385
test mean loss is  0.542997811425
('epoch', 9)
train mean loss =  7.98288726631
test mean loss is  0.509733980175
('epoch', 10)
train mean loss =  5.89249175341
test mean loss is  0.502585373718
```
一応学習はしているっぽいがepochが20を超えたあたりからtest mean lossが0.5付近をうろうろしていていっこうに下がる気配がない。局所解に陥ってしまったのか、パラメーターが更新されていないのか、単純にコードにミスがあるのかがわからない。



>参考
[chainer](http://chainer.org/)