반응형


보간법. interpolate 


몇 개의 샘플 포인트들로 추정하여 인접한 점들 사이를 다항식 함수로 완만한 곡선으로 이어준 것을 스플라인 곡선이라고 한다.

보간법은 이러한 미싱 포인트(추정)들을 계산/추정하는 방법이다.

간단하게는 linear 방식(1차)이 있고, 2차, 3차, 4차 곡선등으로 확장하면서 보다 다양하게 추정할 수 있다.



위 그림은 파란색 점의 샘플 좌표들만을 가지고, 스플라인 곡선을 만들어 그린 추정 그래프이다.

python에서 scipy 라이브러리의 interpolate를 사용하여 구현하였다.

아래 코드에서 splrep에 별다른 옵션이 없으면 3차 스플라인 곡선으로 추정하게 된다. (k=1(선형보간), k=2, k=3(default), k=4 이런식으로 옵션을 준다. )

[python code]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu May 25 2017
@author: crazyj
"""

# interpolation test

import numpy as np
import scipy.interpolate as ip
from scipy.interpolate import splrep, splev
import matplotlib.pyplot as plt

# 0~10까지 15개로 나누어 점을 찍음.
x0 = np.linspace(0, 10, 15)
print('x0=', x0)
# cosine 값을 계산
y0 = np.cos(x0)

# x, y (샘플)값을 주고 추정하는 스플라인 곡선을 만든다.
spl = splrep(x0, y0)
# 0~10까지 50구간에 대한 모든 점들을 위 스플라인 곡선으로 추정한 y값을 구한다.
x1 = np.linspace(0, 10, 50)
y1 = splev(x1, spl)

# 그린다.
plt.figure(figsize=(16, 5))
plt.subplot(121)
plt.plot(x0, y0, 'o')
plt.plot(x1, y1, 'r')
plt.grid()

# 이번에는 sine 곡선으로 추정해 본다.
plt.subplot(122)
y2=np.sin(x0)
spl2=splrep(x0, y2)
y3=splev(x1, spl2)
plt.plot(x0, y2, 'o')
plt.plot(x1, y3, 'b')
plt.grid()
plt.show()



'Python' 카테고리의 다른 글

Python 강좌4 정규식 regular expression  (0) 2018.03.19
Python 강좌3 자료형. 수/문자열  (1) 2018.03.16
Python 강좌2 if/for/while/function  (0) 2018.03.15
Python 강좌1. 산술연산, range  (0) 2018.03.14
Linear regression  (0) 2018.03.13
반응형


+ 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 분류를 한다.





반응형


XOR  학습

단층 퍼셉트론으로는 비선형이 학습이 안된다.

따라서 멀티 퍼셉트론을 사용. 입력 레이어를 제외하고 Two-Layer 구성.

Sigmoid를 사용. 0/1 binary구별로 함.



#!/usr/bin/env python3

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

"""

Created on Tue May 23 14:10:10 2017


@author: crazyj

"""


import numpy as np

import os


# xor simple network.

#   X(2) - 2 - Y(1)

# sigmoid activation function use.

# manual gradient

#

# if fail?, try again!

#   local minima problem exists... 

#   make deep and wide network.

#



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

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


np.random.seed(int(os.times()[4]))


W1 = np.random.randn(2,2)

b1 = np.zeros([2])

W2 = np.random.randn(2,1)

b2 = np.zeros([1])



def Sigmoid(X):

    return 1/(1+np.exp(-X))


def Predict(X,  W1, b1, W2, b2):

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    Y = A2

    return Y


def Cost(X, W1, b1, W2, b2, T):

    epsil = 1e-5

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    Y = A2

    return np.mean(-T*np.log(Y+epsil)-(1-T)*np.log(1-Y+epsil))



def Gradient(learning_rate, X, W1, b1, W2, b2, T):

    Z1 = np.dot(X, W1)+b1

    A1 = Sigmoid(Z1)

    Z2 = np.dot(A1, W2)+b2

    A2 = Sigmoid(Z2)

    deltaY = A2-T

    deltaA1 = np.dot(deltaY, W2.T) * (A1*(1-A1))

    m = len(X)

    

    gradW2 = np.dot(A1.T, deltaY)

    gradW1 = np.dot(X.T, deltaA1)

    W2 = W2-(learning_rate/m)*gradW2

    b2 = b2-(learning_rate/m)*np.sum(deltaY)

    W1 = W1-(learning_rate/m)*gradW1

    b1 = b1-(learning_rate/m)*np.sum(deltaA1)

    return (W1, b1, W2, b2)



for i in range(3000):

    J= Cost(X,W1,b1,W2,b2,T)

    W1,b1,W2,b2 = Gradient(1.0, X, W1, b1, W2, b2, T)

    print ("Cost=",J)


Y = Predict(X, W1, b1, W2, b2)

print("predict=", Y)




결과


Cost= 0.351125685078

predict= [[ 0.50057071]

 [ 0.49643107]

 [ 0.99648031]

 [ 0.00640712]]



실패?

다시 실행을 반복하다 보니 성공할때도 있다??? local minima 문제가 있음.

이를 해결하기 위해서는 여러번 시도해서 코스트가 낮아질 때까지 처음부터 반복(initialize 가 중요).하던가 network을 deep & wide하게 설계한다.


Cost= 0.00403719259697

predict= [[ 0.00475473]

 [ 0.99634993]

 [ 0.99634975]

 [ 0.00409427]]

이건 성공 결과.


+ Recent posts