LoginSignup
3
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-10-07

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

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

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で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も同じような感じ。範囲が違うだけ

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になっている。

実行結果(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

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2