Deep Learningのフレームワークの1つであるchainerを使って勉強がてらsin関数を近似しようとしてみたけどダメだった。chainerのexampleにあるmnistをちょこちょこ書き換えただけのコード。データセットが悪いのか、学習プロセスでバグがあるのかわからない。指摘していただけるとすごくうれしい。
まずはデータセットの作成から
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で0から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も同じような感じ。範囲が違うだけ
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になっている。
('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