반응형

+SVM (support vector machine)을 사용하여 간단하게 바이너리 분류하기


간단하게 말하면 가장 마진이 크도록 최적의 구분 라인 긋기. 약간의 판단 오류가 있더라면 데이터의 밀집 분포 정도에 따라 최적의 라인은 다를 수 있다. 판단오류가 하나도 없도록(과적합) 구분 라인을 만들면 오히려 임의의 값 예측시 정확도가 더 떨어질 수 있다. 


X 데이터 : 피쳐2개. 

Y데이터 : 라벨 (0, 1) binary 분류값.

SVM으로 최적 구분 라인 계산.

임의의 값에 대해 Y데이터 예측하기.


from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np

# line split SVM

X = np.array([[1,2],
[5,8],
[1.5,1.8],
[8,8],
[1,0.6],
[9,11]])
y = [0,1,0,1,0,1]
clf = SVC(kernel='linear'1.0# C is error penalty. if C is bigger then more strictly but margin will be narrow...
clf.fit(X,y)
print(clf.predict([[0.58,0.76]]))
print(clf.predict([[10.58,10.76]]))

w = clf.coef_[0]
print(w)
a = -w[0] / w[1]

xx = np.linspace(0,12)
yy = a * xx - clf.intercept_[0] / w[1]

h0 = plt.plot(xx, yy, 'k-'label="non weighted div")

plt.scatter(X[:, 0], X[:, 1], = y)
plt.legend()
plt.show()

[해설]
x데이터의 벡터는 2차원이고 구분 레이블은 y로 0, 1로 두 그룹으로 나눈다.
SVC의 리턴값으노 clf로 피팅을 하게 되면
clf.predict()로 입력값 x에 대한 구분 레이블 y를 예측할 수 있다.

x데이터의 벡터요소(피쳐)를 x0, x1라 하면
새로운 좌표계의 1차원 좌표축을 z라하면
z = f (x0, x1) 
z>=0 이면 레이블1, z<0이면 레이블 0가 될 것이다. (z=0이면 1일까? 맞다.)

clf의 coef_로 w0, w1를 얻고, intercept로 b를 얻는다.
w0, w1는 입력값의 가중치. b 는 bias

z = w0*x0+w1*x1 + b 가 된다.
따라서 위 라인 (z=0으로 놓는다.)을 기준으로 분류한다.

위 라인을 x1(Y축)에 대해 정리하면
기울기는 -w0/w1
y절편은 -b/w1가 된다.
이 라인이 구분선이 된다.





반응형



++ Linear Regression with multi-variables
X의 feature들이 여러 개 x1, x2, ...

import tensorflow as tf
# y = x1*2+x2+x3 training
# W => 2,1,1, b=0
x_train = [[1,2,3],[2,3,4],[3,4,5],[4,5,6], [1,3,5]]
y_train = [[7],[11],[15],[19], [10]]

#placeholder
x = tf.placeholder(tf.float32, shape=[None,3])
y = tf.placeholder(tf.float32, shape=[None,1])
# variables
W = tf.Variable(tf.random_normal(shape=[3,1]), name='W')
b = tf.Variable(tf.random_normal(shape=[1]), name='b')

# model
hypothesis = tf.matmul(x, W) + b
cost = tf.reduce_mean( tf.square(hypothesis-y) )
# train
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# test
# hres= sess.run(hypothesis, feed_dict={x:x_train, y:y_train})
for i in range(3001):
    _, pcost, _W, _b= sess.run([train, cost, W, b], feed_dict={x:x_train, y:y_train})
    if i%500==0:
        print (i, pcost, _W, _b)

# test
print( sess.run(hypothesis, feed_dict={x: [[4, 2, 3]]}))





반응형



1. Linear Regression 

++ single attribute . 

H(x) = x*W + b
cost(W,b) = 1/m * 오차제곱의 합  =   오차제곱의 평균. (편차제곱의 평균은 분산이다.)
   = 1/m * Sigma(  (H(x)-y)^2  )                    # cost함수를 여기에다가 1/2을 곱하여 사용하기도 한다. 그 때의 미분결과는 아래에 2*가 없어진다.
dJ/dW = 2* (1/m) * Sigma(  (H(x)-y) x )
#train
W := W - alpha* dJ/dW

x_train=[1,2,3]
y_train=[1,2,3]

W=tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name="bias')
hypothesis = x_train * W + b

cost = tf.reduce_mean(  tf.square(hypothesis - y_train) )

optimizer = tf.train.GradientDescentOptimizer( learning_rate=0.1 )
train = optimizer.minimize(cost)

sess = tf.Session()
sess.run( tf.global_variables_initializer())
for step in range(2001):
     sess.run(train)
     if step%100==0:
          print(step, sess.run(cost), sess.run(W), sess.run(b) )

+ 예측 
print ( sess.run( hypothesis , {X:[100]} ) )



반응형




-학습데이터 저장 및 복구

: 저장
변수들 선언. (tf.Variables....) 주의! 이름을 지정.
W1 = tf.Variable( tf.truncated_normal(shape=[INPUTSIZE, HIEEDNSIZE]), dtype=tf.float32, name='W1')
저장할 변수들 지정

param_list={ 'W1':W1, 'b1':b1, 'W2':W2, 'b2':b2}
saver = tf.train.Saver( param_list )
...
saver.save(sess, './savedata.ckpt', write_meta_graph=False)     #디렉터리 명시

: 로딩
변수들 선언. (tf.Variables....) 주의! 이름을 지정. (저장시 사용했던 variables 그대로 복사)
saver 초기화도 동일
param_list={ 'W1':W1, 'b1':b1, 'W2':W2, 'b2':b2}
saver = tf.train.Saver( param_list )
...
sess=tf.Session()
saver.restore(sess, './savedata.ckpt')
로딩 완료. W1, b1, ... 변수들 사용 가능.



반응형


+ 자료 처리 및 많이 사용하는 함수들...

-Shape, Rank, Axis
t=tf.constant(  [1,2,3,4])
tf.shape(t).eval()
     tensor의 shape과 타입을 알수 있다.   Rank는 처음에 [의 개수로 볼 수 있음.
     array ( [4],  dtype=int32 )

t=tf.constant(  [[1,2],  [3,4] ])
tf.shape(t).eval()
     array ( [2,2],  dtype=int32 )

     축에도 번호를 매길수 있는데, 가장큰 범위부터 0으로 매김.
     2차원배열의 경우 0은 행방향, 1은 열 방향.

-Matrix 곱

tf.matmul( matrix1, matrix2)          ; Matrix 곱; 내적
matrix1*matrix2     ; 성분곱.
 ( *과 matmul은 다름. 주의!)

;Broadcasting  알아서 형을 변환하여 연산해 줌. (편하지만 주의할 필요가 있음)



-reduce_sum( input_tensor, axis=None)

axis가 없으면 총합. 축은 큰 범위에서부터 인덱스가 0임.

입력이 1차원이면 축은 의미없음. axis=0이 됨.
입력이 2차원이면
axis=0 세로방향으로 합.  (테이블 input이 있으면, 아래에 답을 쓴 것)
axis=1 가로방향으로 합. (테이블 input에서 오른쪽에 답을 단 것)
axis=-1 이면 가장 마지막 축. 2차원에서는 1이됨. 3차원에서는 2가 됨.
axis가 없으면 성분들 총합.


-reduce_mean( tensor, axis )
평균
tf.reduce_mean(x, axis=0)

-argmax  ; 최대값의 인덱스
tf.argmax(x, axis=1)

-reshape ; 텐서 재구성
t=np.array( [[[0,1,2], [3,4,5]],    [[6,7,8],[9,10,11]] ] )
tf.reshape(t, shape=[-1,3])  ; -1은 알아서 다른 성분크기에 맞게 자동조정.
[[0,1,2], [3,4,5], [6,7,8], [9,10,11]]

비슷한 함수. squeeze, expand

-onehot encoding
t=tf.one_hot(  [[0], [1], [2], [0]],  depth=3)
[ [[1, 0, 0]] , [[0,1,0]], [[0,0,1]], [[1,0,0]] ]          #주의 rank가 올라감!!!
원래의 차수로 내리려면
tf.reshape ( t, [-1, 3] )
[ [1,0,0], [0,1,0], [0,0,1], [1,0,0] ]


-타입 캐스팅
tf.cast( [1.8, 2.2], tf.int32)
tf.cast(  [True, False, 1==1, 1==0], tf.int32 )
     [1, 0, 1, 0]

-스택
x=[1,2], y=[3,4], z=[5,6]
np.stack( [x,y,z] )
          =>   [[1,2], [3,4], [5,6]]
np.stack( [x,y,z], axis=1)
          =>  [[1, 3, 5], [2,4,6]]

-ones and zeros like
tf.ones_like(x).eval()          # .eval()은 값과 타입을 출력해준다.
x의 shape과 같은데 값을 모두 1로 채움.
tf.zeros_like(x)

-Zip ; 묶어준다.
for x, y, z in zip( [1,2,3], [4,5,6], [7,8,9] ):
     print (x, y, z)   
1 4 7 
2 5 8
3 6 9
zip을 하지 않고 출력하면?
for x, y, z in ( [1,2,3], [4,5,6], [7,8,9] ):          # 또는 [[1,2,3],[4,5,6],[7,8,9]]
     print (x, y, z)   
1 2 3
4 5 6
7 8 9



반응형



+자료형

1. PlaceHolder
텐서를 저장. (핸들값). 바로 계산되지는 않는다.
input data 저장시. feed dictionary=맵핑시켜주는 역할. (입력값들로 그래프 실행시 입력할 수 있다.)

tf.placeholder(dtype, shape=None, name=None)
     데이터 타입(dtype);     tf.float32, tf....

     p1 = tf.placeholder(tf.float32, shape=(3,3))
     feeding을 해주어야 한다.

# place holder test
ph1 = tf.placeholder(tf.float32)
ph2 = tf.placeholder(tf.float32)
ph3 = tf.placeholder(tf.float32)

value1=3
value2=4
value3=5

feed_dict = {ph1:value1, ph2:value2, ph3:value3}

ph4 = ph1+ph2*ph3

result=s1.run(ph4, feed_dict)
#or  result = s1.run(ph4, {ph1:value1, ph2:value2, ph3:[2.3]})
print(result)



2. Variable (대문자V 주의!)
     weight를 저장시 사용. (그래프 계산시에 내부에서 변경되는 값들. 초기화가 필요.)
v1 = tf.Variable([1,2,3,4], dtype=tf.float32)
v2 = tf.Variable([1,2,3,4], dtype=tf.float32)
v3=v1*v2
print(v3) ; 역시 출력되지 않는다.
sess.run(v3) ; 에러 발생!
원인은 variable은 반드시 초기화가 필요하다. (weight 초기화 같이)
sess.run 전에 반드시 초기화를 돌려주어야한다. (예외, 저장된 vars restore의 경우는 안해도 됨.)
init = tf.global_variables_initializer()
sess.run(init)
또는
     sess.run( tf.global_variables_initializer())

이후부터 sess.run(v3)하면 계산이 된다.

초기화시킨 variables

weights = tf.Variable( tf.random_normal([784,200], stddev=0.35), name="weights")
또는
weights = tf.Variable( tf.truncated_normal( [None, 200] ) )

biases = tf.Variable(tf.zeros([200]), name="biases")

-변수의 값 변경assign()으로 한다.
gradient = tf.reduce_mean( (W*X-Y)*X)
descent = W-0.1*gradient
update = W.assign(descent)
sess.run(update)



3. constant
tf.zeros(shape, dtype=tf.float32, name=None)
tf.zeros_like(tensor, dtype=None, name=None, optimizer=True)
tf.ones(...)
tf.constant(value, dtype=None, shape=None, ..)

c1 = tf.zeros([3,4], tf.int32)


위 값들을 직접 print하면 객체 정보만 나오고 실제 값을 알 수 없음.
세션을 만들고 실행해 줘야 함.


4. Session   세션.
연산 그래프 묶음을 의미.
세션.run() . 세션단위로 실행. (그래프 실행)

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print( sess.run(hello))

세션에 입력되는 텐서는 그래프 말단 노드로 보면 된다. 앞에 있는 것을 따라서 다 실행됨.
run시에 텐서 맵핑 테이블 추가하여  placeholder와 값을 맵핑시킨다.
run의 결과로 받으면 데이터를 로딩 및 출력이 가능하다. Weight, bias 정보를 얻을 수 있다.

result = sess.run(hello)
w = sess.run(w)
b = sess.run(b)
print(result)


tensor_map={x:input_x, y_:output_y}
_,tmp_cost,acc = sess.run( [train, cost, accuracy], tensor_map)
출력이 필요없는 것은 _로 받으면 된다.


다른 출력 방법??? eval() 이용
print ("Accuracy:", accuracy.eval( session=sess, feed_dict={x:inputx, y:outputy}) )

단,  sess = InteractiveSession() 으로 디폴트 세션을 열어주어야 한다.


마지막에 세션 close를 위해서 with as 구문 사용
with tf.Session() as sess:
     sess.run(train)
자동으로 위 블록탈출시 sess.close() 됨.




반응형



+TensorFlow

machine learning 오픈소스 라이브러리. python 기반.
계산 그래프(computational graph) 를 생성하여 텐서가 흐르는 프로그램


+ 로딩
import tensorflow as tf

로딩이 안되면 tensorflow를 설치한다.



+버전 확인
tf.__version__
'1.1.0'


+텐서 (Tensor)
Rank ; 차원
여기서는 모든 자료형이 텐서다. 원래는 정적타입의 n차원 배열 or list ; 랭크값이 차원수. 1차원은 벡터, 2차원은 매트릭스, 3차원부터 텐서다.
rank 0 ; scalar 1
rank 1 ; vector [1,2,3]
rank 2 ; matrix [[1,2],[3,4]]
rank 3 ; 3-tensor [ [[1],[2]], [[3],[4]] ]
rank n ; n-tensor

Shape ; dimension number. 
rank 1 ;  shape [4]
rank 2 ;  shape [4,2]  ; 4x2 행렬
rank 3 ;  shape [3,4,5]    ; 3x4x5 행렬

DataTypes
tf.float32     ; 대부분 함수에서 디폴트 자료형임.
tf.float64
tf.int8, 16, 32, 64
tf.uint8, 16
tf.string
tf.bool
tf.complex64, 128



+ 기본 예제, 작동 확인:   hello world -> hello tensorflow

import tensorflow as tf
hello = tf.constant('Hello tensorflow!')
sess = tf.Session()
print ( sess.run(hello) )
-------------
b'Hello tensorflow!'
위와 같이 출력됨.
b는 bytes를 의미. 


------------------------------------------------------------------
+ 간단한 더하기 계산그래프 테스트

3+4를 계산하는 그래프.

import tensorflow as tf
# build graph(tensor)
node1=tf.constant(3.0, tf.float32)
node2=tf.constant(4.0)
node3 = tf.add(node1, node2)
# 위 값을 print("node1=",node1, "node2=",node2, "node3=",node3)로 출력해 봐야 주소와 타입만 찍힌다. 값을 모름.
# feed data and run graph, update vars and return.
sess = tf.Session()
print ( sess.run( [node1, node2] ) )          # node1, node2를 구하여 출력.
print ( sess.run( [node3] ) )     # node3인 계산 결과를 출력. (윗줄은 데이터 값을 확인하기 위한 디버깅용)
sess.close()



반응형

아래와 같은 함수를 x가 -500~500 까지인 샘플을 가지고, 학습하여 -1000에서 1000까지의 출력결과를 보자.

학습은 기존의 샘플에 맞는 최적화된 모델을 찾을 뿐 그것으로 미래를 예측하는 것은 이 방식으로는 한계가 있다. 주어진 범위 내에서만 가능하다. 학습된 범위 밖의 영역에서는 정확하지 않다. 물론 가까운 정도는 어느정도 맞지 않을까.

학습할 그래프.

위 그래프의 수식은 아무렇게나 만들어본 

y=sin(x/100)*500+ cos(x/27)*300 + x


# -*- 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.00001

learning_rate = 0.001

train_cnt = 4000




# unknown algbra function

def problem(x):

    y = np.sin(x/100)*500 + np.cos(x/27)*300 +x

    return y

# can u imagine? i dont know.

xrange = np.linspace(-500, 500, 1000)

y_correct = problem(xrange)



# draw graph?

if bDrawFigure:

    plt.figure()

    plt.plot(xrange, y_correct)


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


                    # x domain ; -1000~1000

trainx = np.random.rand(train_cnt)*2000-1000   # 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

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

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.ptl')    # continue train


print( "bTrain=", bTrain, " train_cnt=", train_cnt)

# train

oldtime = time.time()

if bTrain:

    for i in range(train_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=", ((train_cnt-i)/100+1)*term)

            oldtime=newtime

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


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

# test

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


test_cnt = 500

testx = np.random.rand(test_cnt)*1000-500  # training set must be shuffle!!!

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

testy_cor = problem(testx)

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

_llast = sess.run( Llast, feed_dict = { X:testx } )

testcost = np.mean( np.square(_llast-testy_cor))

print ( "cost=", testcost )

#for i in range(test_cnt):

#    print("input=", testx[i], " predict=", _llast[i], " correct=", testy_cor[i])

    

#draw compare

if bDrawFigure:

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

    xrange = np.linspace(-500, 500, 1000)

    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()



GPU로 돌려야지 안 그럼 오래걸린다.

어쨋거나 결과는 아래와 같다.



0부근에서 오차가 심하다.

학습을 오래 할수록 좋아지기는 한다.




'AI(DeepLearning)' 카테고리의 다른 글

tensorflow 강좌2. 자료형  (0) 2018.07.16
[tf] tensorflow 강좌1 로딩테스트  (0) 2018.07.16
[tf] unknown math polynomial function modeling  (0) 2017.06.01
[tf] XOR tensorflow로 학습구현  (1) 2017.05.23
[tf] XOR manual solve  (0) 2017.05.23
반응형

알 수 없는 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하게 해야 학습이 더 잘 될 것 같다. 

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


반응형


+ Tensorflow로 XOR  학습을 구현하기


XOR 학습을 수동으로 계산하지 않고, tensorflow의 api를 사용하면 심플해진다.

복잡한 네트웍도 쉽게 구현이 가능하다.


노드의 개수 및 레이어를 2-4-1 로 구성.

입력층에 노드 2개(feature 개수. x1, x2)

은닉층에는 4개 

출력층은 1개의 노드. (Y)

back-propagation을 위한 골치 아픈 작업(미분)들을 할 필요없이 api 하나로 학습 가능! activation function도 원하는대로 쉽게 변경하고, 학습 알고리즘은 쉽게 바꿀 수 있다.


#!/usr/bin/env python3

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

"""

Created on Tue May 23 14:56:53 2017


@author: crazyj

"""



import numpy as np

import tensorflow as tf


# trainint set

X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])

T_train = np.array( [[0], [1], [1], [0]] )



# placeholder

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

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


# variable

W1 = tf.Variable(tf.truncated_normal([2,4]))

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

W2 = tf.Variable(tf.truncated_normal([4,1]))

b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)


# model

A1 = tf.matmul(X, W1)+b1

Z1 = tf.sigmoid(A1)

A2 = tf.matmul(Z1, W2)+b2

Z2 = tf.sigmoid(A2)


learn_rate = 0.1

Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))

train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)


predict = Z2


sess = tf.Session()

sess.run(tf.global_variables_initializer())

for i in range(5000):

    _train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})

    print( "cost=", _Cost)

    

_predict = sess.run([predict], feed_dict={X:X_train})

print("predict=", _predict)

print("result=", np.array(np.array(_predict)>=0.5, np.int))




결과

cost= 0.021748

cost= 0.0217359

cost= 0.0217239

predict= [array([[ 0.10571096],

       [ 0.86153752],

       [ 0.84178925],

       [ 0.17739831]], dtype=float32)]

result= [[[0]

  [1]

  [1]

  [0]]]


+ 코드 설명

# trainint set

X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])

T_train = np.array( [[0], [1], [1], [0]] )

훈련 데이터는 당연히 xor의 입력 조합에 따른 결과를 훈련시킨다. (0,0) -> 0 , (0,1) -> 1 , (1,0) -> 1 , (1,1)->1


# placeholder

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

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

플레이스 홀더는 텐서플로우내에서 돌아갈 입출력 변수들이라고 보면 된다. 노드에서 변수가 되는 것을 X 입력층은 (?,2) 매트릭스 크기(로우는 임의의 개수, 컬럼은 2개(x1,x2)), 출력층 T는 (n,1) 매트릭스 형태로 선언한다.


# variable

W1 = tf.Variable(tf.truncated_normal([2,4]))

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

W2 = tf.Variable(tf.truncated_normal([4,1]))

b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)

텐서 플로우 변수들을 정의한다. 이것은 그래프에 구성될 노드들의 변수의 형태를 정의한다.

네트웍을 2-4-1로 구성할 것이므로 여기에 따른 weight를 담을 변수와 bias 변수의 형태는 다음과 같다.

2개 노드는 placeholder로 X이고, 2-4연결되는 W(웨이트)는 2행(입력노드개수) 4열(출력노드개수) 매트릭스이다. bias는 4개(출력노드개수)이다.

4-1로 연결되는 파트의 W는 4x1 이렇게 b는 1개 이렇게 구성한다. 초기값들은 랜덤하게 채워준다. bias는 0으로 초기화해준다.


# model

A1 = tf.matmul(X, W1)+b1

Z1 = tf.sigmoid(A1)

A2 = tf.matmul(Z1, W2)+b2

Z2 = tf.sigmoid(A2)

이제 빠진 히든 노드들과 출력층 노드들을 구성한다.

2-4-1네트웍에서 2개는 X, 4개는 A1으로 정하고,

A1 = X x W1 + b1 으로 정의한다.

Z1=은 A1에 활성화함수 sigmoid를 적용한다.


A2=Z1 x W2 + b2로 정의한다. 앞 노드의 출력 결과에 weighted sum이다.

Z2 = A2에 sigmoid를 적용한 것으로 최종 output이다.


learn_rate = 0.1

Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))

train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)

predict = Z2

이제 학습방식을 정한다.
cost function은 오차 제곱법을 쓰고, 학습방식은 gradient descent를 사용하여 훈련 그래프를 만든다.
예측값은 최종 노드 출력인 Z2가 된다.


sess = tf.Session()

sess.run(tf.global_variables_initializer())

for i in range(5000):

    _train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})

    print( "cost=", _Cost)

텐서플로우로 학습을 돌린다. 세션을 만들고, 초기화하여 5000번 학습한다. 그래프의 꼭지인 train을 집어 넣고, feed_dict로 플레이스 홀더 X, T에 훈련 데이터를 넣는다.  학습1회마다 cost값을 출력해 본다. 


_predict = sess.run([predict], feed_dict={X:X_train})
학습 완료후, 학습이 잘 되었는지  입력값 X_train을 넣고 출력값을 생성한다.

print("result=", np.array(np.array(_predict)>=0.5, np.int))

최종 결과로 시그모이드 함수에서 0.5이상이면 1로 미만이면 0으로 출력하여 binary 분류를 한다.





+ Recent posts