갈루아의 반서재

MNIST For ML Beginners (3) -Training & Evaluating Our Model



모델을 훈련시키기 위해, 먼저 모델에게 좋다는 것이 무엇을 의미하는 것인지부터 정의해야한다. 사실 머신러닝에서는 전통적으로 모델에게 나쁜 것 - 통상 cost 혹은 loss 라고 부른다 - 을 정의하곤 하는데, 이는 우리가 만든 모델이 우리가 의도하는 결과에서 얼마나 떨어져있는가를 나타내는 것이다. 에러의 오차를 줄일수록, 모델은 훌륭해진다.

모델이 가진 loss 를 정의하는 좋은 지표중의 하나는 "cross-entropy" 라고 불리는 것이다. Cross-entropy는 우리의 예측이 얼마나 비효율적인지를 측정해주는 도구로서, 관심이 있으신 분들은 다음 링크를 통해 자세한 내용을 찾아볼 수 있다.

Visual Information Theory http://colah.github.io/posts/2015-09-Visual-Information/


cross-entropy를 구현하기 위해 정답을 입력할 placeholder 를 추가한다.

1
y_ = tf.placeholder(tf.float32, [None, 10])
cs

cross-entropy function을 구현해보자.






1
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
cs


tf.log : y의 각각의 요소에 대해 로그 연산을 한다.

y_ * tf.log(y) tf.log(y)와 y_ 의 대응하는 각각의 요소끼리 곱을 실행한다.

tf.reduce_sum  : y의 2번째 차원의 요소를 더한다

tf.reduce_mean

: 예제 전체의 평균값 계산


그리고 최적화 알고리즘을 적용한다. 

1
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
cs

위의 코드에서 gradient descent algorithm (learning rate = 0.5)을 통해 텐서플로우로 하여금 cross_entropy

를 최소화하도록 했다. Gradient descent 는 cost를 줄이는 방향으로 각각의 variable을 이동시키는 간단한 프로시져다. 하지만 이외에도 텐서플로우는 다양한 최적화 알고리즘(many other optimization algorithms) 을 제공한다. 여기서 텐서플로우는 여러분의 그래프에 역전달backpropagation 과 경사하강gradient descent을 구현하는 새로운 오퍼레이션을 추가하고 있는 것이다.

이제 우리가 만들 모델이 트레이닝을 시작하도록 셋업해야한다. 마지막으로 해줘야할 것은, 우리가 앞서 만든 모든 variables을 초기화하는 작업이다.

1
init = tf.initialize_all_variables()
cs


1
2
sess = tf.Session()
sess.run(init)
cs


이제 트레이닝을 시작하자. 총 1,000번을 실행한다.

전편의 스크립트에서 이어서 작성하지 않은 경우 아래의 두 라인이 누락되어 하단에서 보는 NameError가 발생할 수도 있으니 주의한다.

1
2
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
cs

1
2
3
4
5
6
7
8
9
10
11
12
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
 
-------------------------------------------------------------------------
NameError                               Traceback (most recent call last)
<ipython-input-11-2d078bd5aac2> in <module>()
      1 for i in range(1000):
----> 2   batch_xs, batch_ys = mnist.train.next_batch(100)
      3   sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
 
NameError: name 'mnist' is not defined
cs

https://github.com/tensorflow/tensorflow/issues/3043

그럼 이제 앞서 만든 모델을 평가해보자.

특정 축에 존재하는 텐서 중 가장 높은 엔트리의 인덱스를 반환해주는 tf.argmax 를 통해 예측 결과의 정확성을 가늠할 수 있다. 예를 들면,tf.argmax(y,1)는 모델이 생각하는 가장 인풋에 적합한 레이블이며, tf.argmax(y_,1)는 정답에 해당하는 레이블이다. 그리고 tf.equal을 우리의 예상이 맞는지 확인하기 위해 사용할 수 있다.


1
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
cs


True / False 로 이루어진 리스트를 반환하게 된다. 어떤 부분이 맞는지 결정하기 위해, boolean 값을 부동소수점숫자로 표현한 후 그 평균을 구하게 된다. 예를 들면 이런 식이다.

[True, False, True, True] → [1,0,1,1]0.75

1
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
cs


테스트 데이터의 정확도를 출력한다.

1
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
cs

약 92%의 정확도를 기록했음을 출력해준다. 결코 좋은 결과가 아니다. 하지만 지금은 튜토리얼의 목적상 간단한 모델을 사용했기 때문에 결과가 좋지 않을 뿐이다. 약간의 변화로도 약 97%에 해당하는 결과를 얻을 수 있다. 심지어 99.7% 를 넘는 정확성을 기록한 모델도 있다(자세한 내용은 다음 링크 참조 list of results).



현재까지의 전체 코드는 다음과 같다.

mnist_for_beginner
In [1]:
import tensorflow as tf
In [2]:
x = tf.placeholder(tf.float32, [None, 784])
In [3]:
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
In [4]:
y = tf.nn.softmax(tf.matmul(x, W) + b )
In [5]:
y_ = tf.placeholder(tf.float32, [None, 10])
In [6]:
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
In [7]:
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
In [8]:
init = tf.initialize_all_variables()
In [9]:
sess = tf.Session()
In [10]:
sess.run(init)
In [13]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Extracting MNIST_data/train-images-idx3-ubyte.gz
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
In [14]:
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
In [15]:
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
In [16]:
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
In [19]:
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
0.9147
In [ ]: