안녕하세요.  생각의 웹입니다.


홍콩과기대 김성훈 교수님의 텐서플로우 강의 중 Softmax classifier를 이용해 classification 하는 강의를 듣고 실습한 과정을 정리합니다.


https://www.youtube.com/watch?v=FiPpqSqR_1c

여기서 문제는 어떤 학생의 수업 시간과 공부 시간을 입력 값으로 해서 학점을 예측해 보는 것입니다. 데이터셋은 6개의 행으로 나눠져 있는데 x1과 x2를 각각, 학생의 수업 참여 시간과 공부 시간으로 볼 경우, A, B, C 중 하나의 학점을 얻게 되는 것을 0, 1로 기록하고 있습니다.  데이터의 내용은 첨부된 파일을 참고하시기 바랍니다.


그럼 본격적으로 코딩에 들어가보도록 하겠습니다. 처음은 텐서플로우를 사용하기 위해서 tensorflow 모듈과 csv 파일 처리 및 가공 편의성을 위해 numpy 모듈을 불러들입니다.


입력:

import tensorflow as tf

import numpy as np



이제 데이터 파일을 읽어들여 입력 값과 출력 값으로 분리하는데 이때 데이터를 처리하기 쉽도록 전치 행렬(transposed matrix)로 바꿉니다.  


입력:

xy = np.loadtxt('train.csv', unpack=True, dtype='float32')

x_data = np.transpose(xy[0:3])

y_data = np.transpose(xy[3:])

print x_data

print y_data 


결과:


[[ 1.  2.  1.]
 [ 1.  3.  2.]
 [ 1.  3.  4.]
 [ 1.  5.  5.]
 [ 1.  7.  5.]
 [ 1.  2.  5.]
 [ 1.  6.  6.]
 [ 1.  7.  7.]]
[[ 0.  0.  1.]
 [ 0.  0.  1.]
 [ 0.  0.  1.]
 [ 0.  1.  0.]
 [ 0.  1.  0.]
 [ 0.  1.  0.]
 [ 1.  0.  0.]
 [ 1.  0.  0.]]


  

데이터를 불러들이는 것을 마쳤으니 데이터를 가공할 영역을 만듭니다. 텐서플로우는 placeholder라는 생성함수를 통해 데이터의 type과 갯수등을 지정할 수 있습니다.


입력:

X = tf.placeholder("float", [None, 3])

Y = tf.placeholder("float", [None, 3])

이제 본격적으로 모델을 만들고 gradient descent 방식으로 최적 해를 찾아가는 것을 구현합니다. 여기서 가설은 Y = WX 인데 찾고자하는 값이 변수인 W이기 때문에 Variable 생성함수로 선언합니다. 행렬 곱 함수인 matmul() 에서 순서가 바뀐 부분을 주의해서 볼 필요가 있습니다. 텐서플로우 구현 상의 trick인데 강의를 보면 그 이유에 대해 간략히 설명하고 있습니다. cost 함수는 예측 치와 실제 값의 차이를 최소화 하도록 차이가 커지면 무한대로, 작아지면 0에 수렴하도록 만들어 gradient descent 방식으로 최적 해를 찾는 데 활용됩니다.  


입력:

W = tf.Variable(tf.zeros([3, 3]))

hypothesis = tf.nn.softmax(tf.matmul(X, W))

learning_rate = 0.001

cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(hypothesis), reduction_indices=1)) 
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

텐서플로우는 코드를 선언한다고 해서 수행되는 것이 아니라 Session 인스턴스에 전달해야 수행됩니다. 또한 먼저 모든 값을 초기화 해주어야 합니다. 아래 코드는 초기화 수행 후 2000번의 반복을 통해 최적 해를 찾아가는 과정을 구현했는데 매 200번마다 진행상황을 출력하게 됩니다. 출력은 이 과정을 통해 cost 함수 값이 감소하는 것을 보여줍니다. 

마지막으로 코드는 11시간의 수업시간과 7시간의 공부 시간을 투입했을 때 어떤 학점을 맞게될지에 대해 예측하고 있습니다. 이를 통해 약 46%의 확률로 A 학점을, 35% 확률로 B 학점을, 18% 확률로 C 학점을 맡게 됨을 알 수 있습니다.


입력:

init = tf.initialize_all_variables()


with tf.Session() as sess:

    sess.run(init)

    

    for step in xrange(2001):

        sess.run(optimizer, feed_dict={X:x_data, Y:y_data})

        if step % 200 == 0:

            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

   

# prediction

    a = sess.run(hypothesis, feed_dict={X:[[1, 11, 7]]})

    print a, sess.run(tf.arg_max(a, 1)) 

출력:

0 1.09774 [[ -8.33333252e-05   4.16666626e-05   4.16666480e-05]
 [  1.66666694e-04   2.91666773e-04  -4.58333408e-04]
 [  1.66666636e-04   4.16666706e-04  -5.83333429e-04]]
200 1.05962 [[-0.02051384 -0.00103983  0.02155367]
 [ 0.01406439  0.01097753 -0.0250419 ]
 [ 0.01431208  0.03574874 -0.05006079]]
400 1.04985 [[-0.04282598 -0.00625899  0.04908497]
 [ 0.01747187  0.00156368 -0.01903554]
 [ 0.01831204  0.04954104 -0.06785305]]
600 1.0407 [[-0.06517859 -0.01176361  0.07694223]
 [ 0.01943521 -0.00848972 -0.01094547]
 [ 0.0211558   0.06118308 -0.0823388 ]]
800 1.03194 [[-0.08734013 -0.01729389  0.10463406]
 [ 0.0211172  -0.01796171 -0.00315547]
 [ 0.02396628  0.07198346 -0.09594975]]
1000 1.02354 [[-0.10928574 -0.02282182  0.13210759]
 [ 0.02266255 -0.02678035  0.00411784]
 [ 0.02685851  0.08210357 -0.10896213]]
1200 1.01547 [[-0.13101467 -0.02834093  0.15935563]
 [ 0.02409704 -0.03497621  0.01087924]
 [ 0.02983199  0.091598   -0.12143002]]
1400 1.0077 [[-0.15252906 -0.03384716  0.1863762 ]
 [ 0.02543302 -0.04258838  0.01715543]
 [ 0.03287464  0.10050804 -0.13338274]]
1600 1.00021 [[-0.1738314  -0.03933693  0.21316831]
 [ 0.02668083 -0.04965464  0.02297391]
 [ 0.03597423  0.10887134 -0.14484566]]
1800 0.992979 [[-0.19492455 -0.04480689  0.23973146]
 [ 0.02784995 -0.05621057  0.02836075]
 [ 0.0391195   0.11672312 -0.15584266]]
2000 0.985988 [[-0.21581143 -0.05025397  0.26606542]
 [ 0.02894918 -0.06228961  0.03334056]
 [ 0.04230016  0.12409624 -0.16639641]]
[[ 0.46272627  0.35483009  0.18244369]] [0]
지금까지 발견한 텐서플로우의 코딩 패턴은 다음과 같습니다.


  • 데이터가 달라지더라도 데이터를 담는 그릇(placeholder)를 통해 대응
  • 데이터의 형식을 생성함수로 지정
  • cost 함수, 모델 변경 시, 손 쉽게 대응할 수 있는 구조
  • Session에 전달해서 수행해야 실행이 이뤄짐.


Happy Coding!

+ Recent posts