본문 바로가기

Theory/DeepLearning

[Tensor Flow] 간단한 예제로 텐서플로우 시작해보기

요즘 인공지능이라는 단어는 참 많은 분야에 너무 많이 사용되는 것 같습니다. 특히나 그 중에 딥러닝이라는 단어는 더더욱 그렇죠. 저는 딥러닝의 학술적 의미 같은 어려운 이야기를 하려는 것은 아니구요. 딥러닝을 정말 쉽게 학습할 수 있는 여러 라이브러리 중에서 아무래도 가장 유명하다고 할 수 있는 Tensor Flow를 학습해 보려합니다. 뭐 그냥 쉽게 쉽게 진행해 보려구요....^^ 그래서 정말 오랜만에 연재를 시작하려고 합니다. 언제나 그렇듯 저 자신의 지식을 정리하려는 의도랍니다.^^ (그러므로 부족한 부분은 댓글로 부탁드립니다.)

이 분야는 절대 혼자 힘으로 할 수 있다고 생각할 수 없죠^^. 이번 연재는 김성훈 교수님의 유명한 딥러닝과 텐서플로우 공개 강좌[바로가기], 그 외에 엣지있게 설명한 텐서플로우[바로가기], 딥러닝 첫걸음[바로가기]을 정말 단순히 따라가는 수준입니다.

먼저 텐서플로우를 설치해야죠~~ Jupyter[바로가기]를 기본으로 하겠습니다. Jupyter는 Anaconda를 이용해서 설치되었다고 보구요... 터미널에서

pip install tensorflow == 1.3

라고 입력해서 버전 1.3으로 하겠습니다. 뭐 최신 버전(1.4)으로 하셔도 되는데요. 그냥 제가 1.3으로 공부해서 그렇습니다.^^

먼저.. 뭐 이런걸 예제로 하냐고 하시겠지만.. 위 표와 같이 AND 연산을 학습하려고 합니다. 뭐 ??? 훈련용 데이터 셋과 검증용, 테스트용??  뭐?? 데이터가 4set?? ㅎㅎ 그게 아니라 텐서플로우를 한 번 사용해보는 거니까요..

그러면.. 뭘 학습?? 뭘 정한다는 걸까요... 바로 위의 W라는 가중치와 b라는 바이어스를 찾겠다는 겁니다. x1, x2로 입력이 두 개라서 가중치도 w1, w2 두개인데, 이를 행렬로 표현하면 2*1의 크기를 가지는 행렬이 됩니다. 그리고 bias도 있다고 보구요.. 위 수식에서 Wb를 찾으면 됩니다.^^

import tensorflow as tf
import numpy as np

tf.set_random_seed(777)
print(tf.__version__)

일단 방금 설치한 tensorflow를 import 하시고... 시작하죠^^

# AND
x_data = np.array([[0, 0],
                  [0, 1],
                  [1, 0],
                  [1, 1]], dtype=np.float32)
y_data = np.array([[0],
                  [0],
                  [0],
                  [1]], dtype=np.float32)

그리고 위의 표를 numpy array로 선언해 둡니다.

X = tf.placeholder(tf.float32, [None, 2], name='x-input')
Y = tf.placeholder(tf.float32, [None, 1], name='y-input')

그리고 위 처럼 입력(X)과 출력(Y)을 선언합니다. 여기서 placeholder라는 아이가 있네요. 텐서 객체처럼 행동하지만, 생성될 때 값을 가지지 않고, 자리(place)를 유지(hold)하는 개념입니다. User defined variable이라고 하는 것이 괜찮을까하고 생각도 해봅니다.

W = tf.Variable(tf.random_normal([2, 1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')

hypothesis = tf.sigmoid(tf.matmul(X, W) + b)

그리고 우리가 찾아야하는 가중치(W)와 바이어스(b)를 찾아야하니 변수(Variable)로 선언해 둡니다. 여기서 크기는 위에서 이야기한데로 잡아주면 됩니다. 그리고 가설(hypothesis)이라고 하는데 loss function이라고 생각해도 됩니다. 위에서 이야기한데로 XW+b로 잡구요... 활성화 함수 Activation Function이라는 것으로 Sigmoid 함수를 사용했습니다.

위 그림에 표시된 부분까지가 XW+b라면, 그 다음 출력 y로 넘어가는 단계에서 비선형성을 부여하기 위해 Activation Function을 사용해야 합니다.

그 활성화 함수에 사용하는 것 중 하나가 Sigmoid입니다. 위 그림처럼 생겼습니다. 최대 1, 최소 0의 값을 가지는 함수입니다. 이 내용에 대한 더 깊으면서 쉬운 이야기는 Ratsgo's blog[바로가기]를 한 번 들러보시는 걸 추천드립니다.

뭐 여하튼.. 이렇게 hypothesis까지 정의했으니~~~

# cost/loss function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)

이렇게 cost 함수를 cross-entropy로 잡고, cost를 최소화하는 optimizer로 Gradient Descent를 사용합니다. 이 부분은 텐서플로우를 학습에서는 살짝꿍 패스하겠습니다. 단 cost함수와 Gradient Descent에 대해서는 홍콩과기대 김성훈 교수님의 유투브 강좌[바로가기]를 하나 소개해 드립니다.

# Accuracy computation
# True if hypothesis>0.5 else False
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float32))

이제 예측 결과를 계산하는 부분과 정확도(accuracy)를 계산하는 부분입니다. sigmoid 함수의 결과가 0과 1사이의 값이니 0.5를 넘으면 1로 보는거죠. 그리고 참값(Y)과 비교해서 평균을 잡아서 그걸 accuracy로 보는 겁니다.

# Launch graph
with tf.Session() as sess:
    # Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())

    for step in range(10001):
        sess.run(train, feed_dict={X: x_data, Y: y_data})
        
        if step % 100 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}), sess.run(W))

    # Accuracy report
    h, c, a = sess.run([hypothesis, predicted, accuracy], feed_dict={X: x_data, Y: y_data})
    print("\nHypothesis: ", h, "\nCorrect: ", c, "\nAccuracy: ", a)

이제... 그래프(graph)를 시작하는 거죠... 텐서의 flow를 이야기하는 라이브러리라 그런지 아무튼 학습하기 위해 진행하는 과정을 graph라고 합더군요. with 구문 없어도 되지만 여하튼 Session을 시작해야 합니다. Session 객체는 Tensor Graph를 감독하는 역할이라고 생각하시면 됩니다. 그리고 tf.global_variables_initializer()를 통해 반드시 초기화해야합니다. 그리고 10000번 반복하는 for문에서 sess.run으로 훈련(train)을 실행합니다. 마지막에 훈련이 끝나고 나면 accuracy를 확인하는 거죠^^

방금의 과정은

  • 학습 데이터와 출력 데이터를 읽음
  • 입출력값과 학습할 뉴럴 네트워크의 가중치와 바이어스를 정의함
  • 학습할 네트워크를 정의하고 가설(hypothesis 모델)을 정의함
  • cost함수와 훈련(train)에 사용할 optimizer를 결정함
  • 예측값과 accuracy를 정의함
  • 학습 시작 Session.run
  • Accuracy 확인

으로 진행되었습니다. 그리고 난 결과는 

와 같이 나타납니다. 뭐 정확도는 1로 잘 나왔구요^^. 애초 학습하려 한 AND0, 0, 0, 1을 잘 학습한 것 같습니다. 뭐 별거 없는 예제이지만, 텐서플로우라는 라이브러리를 어떻게 사용하는지 튜토리얼처럼 한 번 시작해 보았습니다. 다음에는 조금 더 재미있는 걸로 다뤄보겠습니당^^

반응형