본문 바로가기
AI

ML07-4-MNIST-data (실제 data 분석)

by 월곡동로봇팔 2019. 10. 24.
import tensorflow as tf
import matplotlib.pyplot as plt
import random

tf.set_random_seed(777)  # for reproducibility

# input_data를 좀 더 편하게 input하게 함
from tensorflow.examples.tutorials.mnist import input_data

# Check out https://www.tensorflow.org/get_started/mnist/beginners for
# more information about the mnist dataset
# one_hot을 설정하면 데이터를 읽어올 때 one_hot으로 읽어온다!!!
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# nb_classes는 digit 0-9
nb_classes = 10

input_data의 mnist.py에서 DataSet의 클래스 메소드인 read_data_sets를 불러온다.

이 때 train_dir, one_hot=True를 입력해준다. (validation_size를 조정해서 validation 구간을 늘릴 수도 있다.)

one_hot=True라고 한 것은, 불러오는 label들을 one_hot으로 쉽게 불러 올 수 있기 때문이다.

nb_classes는 label들이 0-9까지 구간이기 때문이다.

 

# MNIST data image of shape 28 * 28 = 784
X = tf.placeholder(tf.float32, [None, 784])
# 0 - 9 digits recognition = 10 classes
Y = tf.placeholder(tf.float32, [None, nb_classes])

W = tf.Variable(tf.random_normal([784, nb_classes]))
b = tf.Variable(tf.random_normal([nb_classes]))

# Hypothesis (using softmax)
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)

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

mnist_data는 28 * 28 = 784 픽셀 즉, 행렬로 이루어져있기 때문에, X를 784로 해둔다.

실제값인 Y는 nb_classes 에 맞춰서 shape을 설정해둔다.

 

hypothesis는 multi-classification이기 때문에 nn.softmax activation 함수를 넣는다.

 

cost 함수는 X의 1번째행과 W의 1번째 열을 곱한 후, bias와 더한 값을 hypothesis_1이라 생각한다면, 

reduce_sum은 그 값을 다 더한 값이고, reduce_mean은 그 값을 평균낸 값이므로, cost는 각각의 cost의 평균인 셈이다.

이 때, axis = 1 인 이유는, 결과값의 shape는 (None, nb_classes) 이기 때문에, axis=1 경우끼리 연산(평균)을 해야한다.

따라서 hypothesis, cost의 shape는 (None, nb_classes)이며 이는 각 데이터마다 label(0-9)이 정해지기 때문이다.

 

# Test model
is_correct = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
# Calculate accuracy
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

# parameters
# epoch는 한번 training을 시킨것을 1 epoch
num_epochs = 15
batch_size = 100
# 루프 도는 횟수는 데이터갯수 / batch size로 하면된다.
# 어차피 for문에서 range는 0부터기 때문에 상관없다.
num_iterations = int(mnist.train.num_examples / batch_size)

 

우리는 저번에 얘기한 mnist.DataSet의 메소드들에 대해서 정리하였다. 그 내용은 밑의 내용과 같다.

 

mnist.( ).images : 이미지 데이터셋
mnist.( ).labels : label 데이터셋
mnist.( ).num_examples : 데이터 갯수
mnist.( ).next_batch : 데이터셋으로부터 필요한 만큼의 데이터를 반환하는 함수

( ) 안에는 train, validation, test인 Dataset이 들어간다. (세 개의 객체도, Dataset이기 때문에 메소드 그대로 사용)

 

batch_size = 는 한 번 불러올 때, 얼만큼 불러올 것인지 정하는 수이다.

num_epochs는 얼마나 training 할 것인지 정하는 수이다.

 

with tf.Session() as sess:
    # Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())
    # Training cycle
    for epoch in range(num_epochs):
        avg_cost = 0
        # batch를 쓰는 이유는 784개를 모두 올리기에는 너무 용량이 커서 batch를 씀.
        # avg_cost를 쓰는 이유는 1개의 image를 나눠서 올리기 때문에!
        for i in range(num_iterations):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            _, cost_val = sess.run([train, cost], feed_dict={X: batch_xs, Y: batch_ys})
            avg_cost += cost_val / num_iterations

        print("Epoch: {:04d}, Cost: {:.9f}".format(epoch + 1, avg_cost))

    print("Learning finished")

    # Test the model using test sets
    print(
        "Accuracy: ",
        # sess.run 할수도 있고, tf.eval도 할 수 있다.(하나만 실행하고싶을때)
        accuracy.eval(
            session=sess, feed_dict={X: mnist.test.images, Y: mnist.test.labels}
        ),
    )

여기서 avg_cost를 쓰는 이유는 1개의 image를 나눠서 올리기 때문에, 한 image의 cost 한 값으로 모이려면 avg_cost를 각각 연산을 할 때, 1 batch당 cost_val를 num_iterations로 나눠준다. 이를 avg_cost에 더해준다.

 

따라서 for 문 위에서 epoch 값에 따라서, 우리는 epoch와 cost 값을 적어준다.

 

Accuracy는 tf.reduce_mean(tf.cast(is_correct, tf.float32)) 이기 때문에, eval을 사용한다.

이는 sess.run과 같은 맥락이지만, eval의 경우는 하나의 값만 간단히 보고싶을 때 쓴다.

정확도는 mnist.test.images, labels 를 feed_dict를 통해 알아낸다.

 

    # r은 test data 10000개 중에 하나를 고르는 것이다.
    # Get one and predict
    r = random.randint(0, mnist.test.num_examples - 1)
    # 우리가 mnist 불러올 때, one_hot으로 불러왔으니, mnist.test.label도 당연히 one_hot
    # label은 0,0,0,0,1,0,0,0,0,0 이형태로 10000개로 이어져있다.
    print("Label: ", sess.run(tf.argmax(mnist.test.labels[r : r + 1], 1)))
    print(
        "Prediction: ",
        sess.run(tf.argmax(hypothesis, 1), feed_dict={X: mnist.test.images[r : r + 1]}),
    )

    plt.imshow(
        mnist.test.images[r : r + 1].reshape(28, 28),
        cmap="Greys",
        interpolation="nearest",
    )
    plt.show()

 

 

위에 코드에서 r은 test data의 image, label.shape을 보면 (10000, 784) (10000, 10) :

r은 이 중에서 10000개 중에 data 하나를 고르는 것이다.

우리가 mnist 불러올 때, one_hot으로 불러왔으니, mnist.test.label도 당연히 one_hot

 

"Label" 은 0,0,0,0,1,0,0,0,0,0 이형태로 10000개로 이어져있다.

따라서 mnist.test.labels[r : r+1] 형태로 해야지 r 에 해당하는 자리에 label을 뽑아올 것이다.

이를 argmax를 한다면 label은 0,0,0,0,1,0,0,0,0,0 형태기 때문에 숫자를 예측 가능하다.

 

"Prediction" 은 X로 mnist.test.images[r:r+1] 을 넣는다. 이 때의 hypothesis가 무엇을 가르키는지가 prediction이다.

 

밑의 코드는 plt로 그래프를 그리는 것이다.

 

 

MNIST는!!

1. input_data.read_sets로읽어,주어진 Dataset을 Training , Validation, Test 구간으로 나눈다.

2. num_epoch, batch_size, num_iterations 정한다. 원한다면 validation_size도 정해줄 수있다.

3. Session 위에서 training할 때 batch_size 대로 하고, batch로 구간을 나누기 때문에 

   avg_cost를 두어서 한 data의 cost를 합해서 한 epoch당 cost를 return 해야한다.

4. 원한다면 Validation을 넣어서 cost를 줄인다.

5. r을 난수로 표현하고, 이를 0-mnist의 테스트의 갯수사이의 값을 넣어준다.

   (테스트 10000개 중에 아무 숫자나 넣는 것이다.) 그 후 label은 r을 index에 넣어 알아낸다.

6. Prediction은 mnist.test.images[r:r+1], label을 넣은후 hypothesis를 argmax해서 예측한다.

댓글