반응형

알 수 없는 n차 다항 함수에 근사하는 샘플데이터를 학습시켜보자.

단순한 linear regression으로는 다차항 함수의 학습이 되지 않는다.

feature 값을 x^2, x^3, .. 이런식으로 변환하여 feture들을 늘려서 학습시킨다면 가능할수도 있지만, 몇 차로 해야될지도 알 수 없고 전처리를 해야되서 예측이 어렵다.

이것을 해결하기 위해서는 deep and wide한 네트웍을 구성하여 학습을 시킨다.

단, 주의해야될 점은 바로 activation function이다. 항등함수로만 하면 아무리 네트웍을 구성해도 학습이 되지 않는다.

네트웍을 affine  계층으로만 하게되면 weighted sum을 다시 weighted sum을 하게 되므로 다중 레이어를 둔 의미가 상실되게 된다. 즉, xw+b를 다시 (xw+b)w+b가 되서 아무리 반복해도 x*w+b꼴로 표현이 가능하다. 즉, 단층레이어와 동일할 뿐이다.

activation function은 다양한 정보 표현이 가능하도록 비선형 함수들을 사용해야 한다. sigmoid, tanh, relu 등.

그리고 마지막 계층 또한 중요하다. 1/0을 판단하는 binary classification이라면 sigmoid로 하고, multinomial classfication이라면 softmax를 사용하며, 실수범위의 예측이라면???  출력값의 범위가 표현될 수 있는 function을 만든다.  학습이 잘 되냐 실패하냐거 거의 여기에 달린 것 같다.

ex) sigmoid or tanh or identity 의 값에 * 도메인크기 + bias , 

(identity는 항등함수를 말함. 즉, weighted sum 인풋이 그대로 출력되는 함수) 

몇 번 테스트해보니 sigmoid나 tanh가 적당하다. 


단, 이렇게 학습하여 예측하는 것에는 한계가 있다.

학습한 데이터의 도메인에 해당되는 범위내에서는 예측가능하나, 학습되지 않은 구간에서는 맞지 않게 된다.


# -*- coding: utf-8 -*-


'''

Created on Sat May 13 10:54:59 2017


@author: Junhee

'''


#

# complex algbra predict learning? is it possible???

# continous valued target bounded range (-1000,1000)

# not using polynomial modified input!. because I don't know

# what polynomial degree is correct. 

#



import numpy as np

import tensorflow as tf

import matplotlib.pyplot as plt

import time



bDrawFigure = True

# train yes or no

bTrain = 1

#learning_rate = 0.1

#learning_rate = 0.0001

learning_rate = 0.00001

#learning_rate = 0.1

trainset_cnt = 200

epoch_cnt = 4000

#epoch_cnt = 40000





# unknown algbra function

def problem(x):

#    y = x**2

    y = x**2-30*x

    return y

# can u imagine? i dont know.

xrange = np.linspace(0, 100, 200)

y_correct = problem(xrange)


# draw graph?

if bDrawFigure:

    plt.figure()

    plt.plot(xrange, y_correct)


output_space = 40000     # tanh ; -1~1 X output_space ; output range! ; -2000~2000


                    # x domain ; -1000~1000

trainx = np.random.rand(trainset_cnt)*100-0   # training set must be shuffle!!!

trainx = trainx.reshape([-1,1])

trainy_cor = problem(trainx)

trainy_cor = trainy_cor.reshape([-1,1])



X = tf.placeholder(tf.float32, shape=[None,1])

Y = tf.placeholder(tf.float32, shape=[None,1])


# make network NN

W1 = tf.Variable(tf.random_normal([1,512]))

b1 = tf.Variable(tf.zeros([512]))

L1 = tf.nn.sigmoid(tf.matmul(X, W1)+b1)

#L1 = tf.nn.tanh(tf.matmul(X, W1)+b1) 


W2 = tf.Variable(tf.random_normal([512,1024]))

b2 = tf.Variable(tf.zeros([1024]))

L2 = tf.nn.sigmoid( tf.matmul(L1, W2)+b2) 


W3 = tf.Variable(tf.random_normal([1024,1024]))

b3 = tf.Variable(tf.zeros([1024]))

L3 = tf.nn.sigmoid( tf.matmul(L2, W3)+b3) 


W4 = tf.Variable(tf.random_normal([1024,1024]))

b4 = tf.Variable(tf.zeros([1024]))

L4 = tf.nn.sigmoid( tf.matmul(L3, W4)+b4) 


W5 = tf.Variable(tf.random_normal([1024,1]))

b5 = tf.Variable(tf.zeros([1]))

#Llast = tf.nn.tanh( tf.matmul(L4, W5)+b5) *output_space


#good

Llast = (tf.nn.sigmoid( tf.matmul(L4, W5)+b5)) *output_space - 500


#Llast = (tf.matmul(L4, W5)+b5) *output_space


# bad... 

#Llast = (tf.matmul(L4, W5)+b5)


cost = tf.reduce_mean( tf.square(Llast-Y) )


train = tf.train.AdamOptimizer(learning_rate).minimize(cost)


sess = tf.Session()

sess.run( tf.global_variables_initializer())


param_list = {'W1':W1,'b1':b1,

              'W2':W2,'b2':b2,

              'W3':W3,'b3':b3,

              'W4':W4,'b4':b4,              

              'W5':W5,'b5':b5,

              }

saver = tf.train.Saver(param_list)

#saver.restore(sess, './unknown_predict_poly.ptl')    # continue train


print( "bTrain=", bTrain, " trainset_cnt=", trainset_cnt, " epoch=cnt", epoch_cnt)

# train

oldtime = time.time()

if bTrain:

    for i in range(epoch_cnt) :

        _, _cost = sess.run( [train, cost], feed_dict={X:trainx, Y:trainy_cor})

        if i%100==(100-1):

            newtime = time.time()

            term = newtime-oldtime

            print( "train=",i," cost=",_cost, " remaintime=", ((epoch_cnt-i)/100+1)*term)

            oldtime=newtime

    saver.save(sess, './unknown_predict_poly.ptl')


##########################################################

# test

saver.restore(sess, './unknown_predict_poly.ptl')

    

#draw compare

if bDrawFigure:

#    xrange = np.linspace(-1000, 1000, 2000)

    xrange = np.linspace(1, 200, 200)

    xrange = xrange.reshape(-1, 1)

    _llast2 = sess.run( Llast, feed_dict = { X:xrange } )

    xrange = xrange.reshape(-1)

    testyrange = _llast2.reshape(-1)

    plt.plot(xrange, testyrange, c='r')    

    

plt.show()



출력결과

bTrain= 1  trainset_cnt= 200  epoch=cnt 4000

train= 99  cost= 4.10605e+07  remaintime= 408.33133206844326

train= 199  cost= 6.47534e+06  remaintime= 374.9750850892067

train= 299  cost= 3.22122e+06  remaintime= 390.8726796555519

...

train= 3399  cost= 12447.5  remaintime= 73.77905233621597

train= 3499  cost= 12130.0  remaintime= 62.91447646141052

train= 3599  cost= 11828.8  remaintime= 51.30402812004089

train= 3699  cost= 11539.5  remaintime= 43.085111978054044

train= 3799  cost= 11257.4  remaintime= 33.96168860197067

train= 3899  cost= 10978.7  remaintime= 21.201974751949308

train= 3999  cost= 10699.7  remaintime= 11.279016330242158

INFO:tensorflow:Restoring parameters from ./unknown_predict_poly.ptl

초반에 cost가 어마어마하다. 학습이 잘 된다면 위와 같이 점점 줄어들 것이다.


임의의 다차항 함수의 샘플을 생성하여 학습한다.

y=x^2-30x 라는 함수를 배워본다. 단, 전체 실수범위에 대해서 학습은 불가능하다.

샘플의 범위는 유한하기 때문. x의 범위를 0~100까지를 학습해 본다.

학습데이터의 모습은 아래와 같다.

이를 학습하여 200까지 예측해 보면, 100~200 범위는 배우지 않았기 때문에 오차가 커진다.

그러나 학습한 범위인 0~100까지는 거의 정확하다!

최종 학습 결과.

위 그림에서 0~100 구간은 파란선과 빨간선의 거의 일치한다.


추신)

샘플에 noise를 가해주고 학습하는게 좋을 것 같다.

학습시에는 batch로 샘플데이터를 random select하게 해야 학습이 더 잘 될 것 같다. 

다른 복잡한 곡선도 테스트해 보자.


+ Recent posts