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).
현재까지의 전체 코드는 다음과 같다.
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b )
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
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})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))