인공지능 AI

[인공지능/AI]텐서플로를 이용한 MNIST 딥러닝학습

2020/06/06 - [인공지능 AI] - [딥러닝/인공지능]MNIST(필기체 손글씨)

이전 게시글에서 MNIST를 다루었는데요, 족히 19시간 이상은 걸렸습니다..

이렇게 긴 학습 시간이 걸린다면 상당히 비효율적이겠죠

하지만 텐서플로를 이용하여 학습시간을 훨씬 단축시켜줄 수 있습니다!

딥러닝 기본아키텍처와 텐서플로기반 아키텍처의 차이

딥러닝 기본적인 아키텍처는 1. 입력데이터 X와 T를 입력층으로 보내주고 2. 피드 포워드 수행하여 시그모이드 함수 값으로 출력층의 출력 값 y를 계산하고 3. 출력층 출력 값 y와 정답 T를 비교해서 4. 손실함수가 최소가 될 때까지 가중치와 바이어스를 업데이트하는 구조였습니다.

 

하지만 텐서플로 기반의 딥러닝 아키텍처는 은닉층에서 활성화 함수로 시그모이드 함수가 아닌 relu와 softmax 함수를 사용합니다. 

relu는 이전 글에서도 다루었고, softmax는 출력 값의 확률 분포를 나타내는 함수입니다.

relu는 sigmoid(0과 1 사이의 값으로 전달)과 다르게 입력값 그대로 출력(0이하면 0으로)하기 때문에 

학습 속도가 훨씬 빠릅니다.

 

MNIST 검증

이제 텐서플로를 사용한 딥러닝 아키텍처로 MNIST를 검증해보겠습니다.

위의 이미지처럼 은닉층 선형회귀 값으로 sigmoid 대신 relu를 사용하고, 출력층 선형회귀 값으로는 대신 softmax함수를 사용하는 부분이 달라집니다. (속도 향상) 

 

 

이미지 데이터 불러오기

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np

#read_data_sets()통해 데이터를 객체형태로 받아온다. 그리고 원핫인코딩형태로 받아옴
mnist=input_data.read_data_sets("MNIST_data/", one_hot=True)

#mnist데이터셋은 train, test, validation 3개의 데이터셋으로 구성되어 있으며,
#num_examples 값을 통해 데이터의 개수 확인 가능하다

print('\n', mnist.train.num_examples, mnist.test.num_examples, mnist.validation.num_examples)

#데이터는 794(28*28)개 픽셀가지는 이미지랑 다르게
#10(0~9)개의 클래스 가지는 원핫인코딩된 레이블(정답)을 가진다
print("\ntrain image shape=", np.shape(mnist.train.images))
print("train label shape=", np.shape(mnist.train.labels))
print("test image shape=", np.shape(mnist.test.images))
print("test label shape=", np.shape(mnist.test.labels))

결과 

이미지 데이터를 추출완료했으면 학습(딥러닝)을 시작합니다.

#입력은닉출력노드, 학습율, 반복횟수, 배치개수 등 설정하기
learning_rate=0.1
epochs=100 #반복횟수
batch_size=100 #한번에 입력으로 주어지는 MNIST 개수

input_nodes=784
hidden_nodes=100
output_nodes=10

#입출력위한 플레이스홀더 정의
X = tf.placeholder(tf.float32, [None, input_nodes])
T = tf.placeholder(tf.float32, [None, output_nodes])

W2 = tf.Variable(tf.random_normal([input_nodes, hidden_nodes])) #은닉층 가중치노드
b2= tf.Variable(tf.random_normal([hidden_nodes])) #은닉층 바이어스노드

W3 = tf.Variable(tf.random_normal([hidden_nodes, output_nodes])) #출력층 가중치노드
b3 = tf.Variable(tf.random_normal([output_nodes])) #출력층 바이어스노드

Z2 = tf.matmul(X,W2) + b2 #은닉층 선형회귀 값 Z2
A2 = tf.nn.relu(Z2) #은닉층 출력값 A2, sigmoid 대신 relu 사용!!

Z3 = tf.matmul(A2,W3) + b3 #출력층 선형회귀 값 Z3, 즉 softmax에 들어가는 입력값
y = A3 = tf.nn.softmax(Z3)

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=Z3, labels=T))
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(loss)

predicted_val=tf.equal(tf.argmax(A3,1), tf.argmax(T,1)) #행단위로 비교
accuracy=tf.reduce_mean(tf.cast(predicted_val, dtype=tf.float32)) #True/False 0/1로 변환

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer()) #변수노드초기화
    for i in range(epochs): #100번 반복수행
        total_batch = int(mnist.train.num_examples/batch_size)
        for step in range(total_batch):
            batch_x_data, batch_t_data = mnist.train.next_batch(batch_size)
            loss_val, _ = sess.run([loss, train], feed_dict={X: batch_x_data, T: batch_t_data})

            if step % 100 == 0:
                print("step = ", step, ", loss_val = ", loss_val)

    #Accuracy
    test_x_data = mnist.test.images #10000*784
    test_t_data = mnist.test.labels #10000*10

    accuracy_val = sess.run(accuracy, feed_dict={X: test_x_data, T: test_t_data})

    print("\nAccuracy = ", accuracy_val)

{....생략.....}

마지막 정확도까지 출력을 완료했습니다.

기본 딥러닝 아키텍처로 학습했을 때는 반나절 이상이 소요되었는데

텐서플로를 기반으로 한 딥러닝 아키텍처로 학습해보니 1분 정도의 시간이 소요되었습니다.

 

엄청난 학습속도 향상을 이룬 것이죠

 

 

 

 

 

 

 

 

(참고사항. tensorflow 1.5 버전으로 구현한 코드입니다. 최신 2.0 버전에서는 호환되지 않는 부분들이 존재합니다.)