머신러닝

Low level TensorFlow API 선형회귀 모델 파이선 코드 연습

coding art 2019. 1. 22. 18:10
728x90

파이선 코딩을 배우는 초보자도 머신 러닝에 한번 도전해 보자.

머신 러닝을 배우려는 초보자들이 가지게 될 의문점들을 하나하나 찾아내어

실제 풀어보고 결과를 확인해볼 수 있도록  완전히 뒷문으로 들어가 시작하는 머신 러닝!


우선 아래 url 을 방문하여 url 로 구성된 본 서의 목차 파일을 다운로드 받아 살펴보시기 바랍니다.

파이선 코딩 초보자를 위한 톈서플로우∙OpenCV 머신러닝 머리말과 url 목차 파일 다운로드
https://steemit.com/kr/@codingart/pryx1-opencv

noname03.png

_____________________________________________________________________________________________________


처음 텐서 플로우 머신 러닝을 배울 때 시작하게 되는 모델이 바로 Linear Regression 모델이다. Low level 이라함은 배우기 쉽다는 의미가 아니다.여기서 Low level 이라함은  단지 sclkit-learn  라이브러리 레벨에서 편리하게 Perceptron  코드나 Adaline 코드 를 라이브러리로 불러 쓸 수 있음에도 불구하고 소스 코드를 일부러 작성하여 그 내부에서 어떻게 진행되는지 모니터 할 수 있는 수준의 코딩을 뜻한다. 따라서 여기서 소개하는 class TfLinreg(object) 은 실제 텐서플로우 버전 아나콘다 스파이더 편집기에서 불러 쓸 수 있는 라이브러리가 아니며 다니 텐서플로우가 어떻게 연산하는지 알아보기 위한 정도의 코드로 보면 될 것이다. 이러한 코딩을 굳이 해보는 이유는 곧 머지 않아 상당히 높은 수준의 Keras 코딩을 해보기 위한 훈련 정도로 생각하면 될 것이다.


TensorFlow 와 Numpy  라이브러리를 불러들인 후 장난 수준의 데이터를 사용하여 파이선 선형회귀 코드를 실행시켜보자. 대체로 머신 러닝에서는 임의의 수치적인 데이터를 사용하는 것은 터부시 되고 있으며 반드시 MNIST 데이터 또는 Iris flowers 데이터 또는 시카고 공동품 시장의 할아버지 시계 매매가 통계 데이터처럼  근거가 확실한 데이터를 사용하여 입증하는 것이 원칙이나 머신 러닝 초보자를 위한 알고리듬을 소개하고 설명하는 차원에서 임의적인 수치 데이터 예제를 들기도 한다.
학습용 X_train 과 Y_train 데이터를 준비하자. X_train 은 0에서 9까지 실수 데이터를 생성하여 10x1 로 리스트형 데이터의 shape을 설정한다. Y_train 은 임의로 10개의 실수 데이터를 대응시킨다.
X_train = np.arrange(10).reshape((10,1))
Y_train = np.array([1.0, 1.3, 3.1, 2.0, 5.0, 6.3, 6.6, 7.4, 8.0, 9.0])
이 데이터들을 사용하여 Session에서 feed_dict의 입력 데이타 시켜 학습을 시키게 되면 0.0에서 9.0 사이의 임의의 테스트 입력 값에 대해서 학습결과를 사용하여 Y 값을 예측해 볼 수 있게 된다.


다음과 같이 instance를 생성할 수 있도록 lrmodel= TfLinreg (x_dim= X_train.shape[1], learning_rate= 0.01)이란 명칭의 class를 코딩하기로 하자.
intance 대상이 되는 self 변수를 잘 체크해 보자.

 


초기화 루틴이 작성되었으니 TensorFlow에 의해 선형회귀 분석을 위한 Computational Gpaph 설정에 이어 랜덤 시드 설정, 모델 build 및 initalizer까지 준비가 되었다.

이어서 method 인 build(self)에서  X와 y의 placeholder 설정이 필요하며 텐서플로우 변수 웨이트 w 와 바이아스 b를 zeros를 사용하여 설정하자.
w, self.X 와 b를 사용하여 self.z_net을 선형 연산 한다. tf.squeeze 는 shape값 [, 1,]에 해당하는 부분이 필요 없어 삭제하는 역할을 한다고 한다.
제곱에러 계산식 sqr_errors를 설정한다.
sqr_erros를 사용하여 self.mean_cost계산식을 설정한다.
GradientDescentOptimizer를 사용하도록 Optimizer를 설정한다.
self.mean_cost를 사용하여 최소화 할 수 있도록 self.optimizer를 설정한다.

중간에 넣어둔 출력문은 6개의 Node에 해당하는 X,y,w,b,z_net 과 sqr_errors 의 명칭과 shape를 모니터링 한다.



lrmodel= TfLinreg (x_dim= X_train.shape[1], learning_rate= 0.01)
를 실행 출력하여 앞서 언급했던 Node들의 설정을 체크해보자.



학습을 위해서는 학습용 데이터 X_train 과 y_train, num_epochs=10를 사용하는 별도의 함수 train_linreg를 생성하자. 이 함수는 TfLinreg과는 별도이므로 method가 아닌 함수이다. 이 부분은 많은 텐서플로우 예제에서 직접 Sesiion을 설정하여 실행했던 부분인데 앞부분의 Graph 단계에서부터 class 화하는 바람에 이 부분도 마찬가지로 함수화가 가능한 듯하다. 말이 Low level이지 파이선 코딩 중급 이상의 기교기 요구되는 코딩인 듯하다.


실행 후 cost 함수 감소 트렌드와 테스트 데이터를 사용한 예측 값을 아나콘다에서 첨부된 코드를 실행하여 작도해 보자.



#ch13_low_level_01.py
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# ### Developing a simple model with low-level TensorFlow API

X_train = np.arange(10).reshape((10, 1))
y_train = np.array([1.0, 1.3, 3.1,
                    2.0, 5.0, 6.3,
                    6.6, 7.4, 8.0,
                    9.0])

class TfLinreg(object):
   
    def __init__(self, x_dim, learning_rate=0.01,
                 random_seed=None):
        self.x_dim = x_dim
        self.learning_rate = learning_rate
        self.g = tf.Graph()
        ## build the model
        with self.g.as_default():
            ## set graph-level random-seed
            tf.set_random_seed(random_seed)
           
            self.build()
            ## create initializer
            self.init_op = tf.global_variables_initializer()
       
    def build(self):
        ## define placeholders for inputs
        self.X = tf.placeholder(dtype=tf.float32,shape=(None, self.x_dim), name='x_input')
        self.y = tf.placeholder(dtype=tf.float32, shape=(None), name='y_input')
        print(self.X)
        print(self.y)
        ## define weight matrix and bias vector
        w = tf.Variable(tf.zeros(shape=(1)), name='weight')
        b = tf.Variable(tf.zeros(shape=(1)), name="bias")
        print(w)
        print(b)

        self.z_net = tf.squeeze(w*self.X + b, name='z_net')
        print(self.z_net)
       
        sqr_errors = tf.square(self.y - self.z_net, name='sqr_errors')
        print(sqr_errors)
        self.mean_cost = tf.reduce_mean(sqr_errors, name='mean_cost')
       
        optimizer = tf.train.GradientDescentOptimizer(
                    learning_rate=self.learning_rate, name='GradientDescent')
        self.optimizer = optimizer.minimize(self.mean_cost)


lrmodel = TfLinreg(x_dim=X_train.shape[1], learning_rate=0.01)


def train_linreg(sess, model, X_train, y_train, num_epochs=10):
    ## initialiaze all variables: W & b
    sess.run(model.init_op)
   
    training_costs = []
    for i in range(num_epochs):
        _, cost = sess.run([model.optimizer, model.mean_cost],
                           feed_dict={model.X:X_train,
                                      model.y:y_train})
        training_costs.append(cost)
       
    return training_costs


sess = tf.Session(graph=lrmodel.g)
training_costs = train_linreg(sess, lrmodel, X_train, y_train)

plt.plot(range(1,len(training_costs) + 1), training_costs)
plt.tight_layout()
plt.xlabel('Epoch')
plt.ylabel('Training Cost')
plt.show()


def predict_linreg(sess, model, X_test):
    y_pred = sess.run(model.z_net,
                      feed_dict={model.X:X_test})
    return y_pred


plt.scatter(X_train, y_train,
            marker='s', s=50,
            label='Training Data')
plt.plot(range(X_train.shape[0]),
         predict_linreg(sess, lrmodel, X_train),
         color='gray', marker='o',
         markersize=6, linewidth=3,
         label='LinReg Model')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.tight_layout()
plt.show()