머신러닝

3-1 MNIST 인식률 계산을 위한 Covariance Softmax 알고리듬

coding art 2019. 8. 24. 11:41
728x90

MNIST 수시숫자 인식률 향상을 위해서 Covariance항을 고려한 Softmax 공식을 사용하도록 한다. MNIST 입력데이타가 1X784 이므로 직접 activation 단계에서 hypothesis784X10 으로 최종 처리하여 Softmax 에 입력하자.

 

GradientDescentOptimizer를 사용하기로 하며 파라메터 설정은 다음과 같다.

learning rate = 0.1

alpha = 0.0 2.0 , increment = 0.02

 

3.1 에서의 결과를 참조하면 α0.120.2 사이에서 인식률 값이 95.596.0 사이 값을 보여 준다.




한편 동일한 Covariant 알고리듬을 사용하되 hidden layer를 하나 추가한 뉴럴 네트워크를 구성해 보자. 앞서 고려했던 알고리듬은 1X785 입력 데이터에서 785X10 매트릭스를 사용하여 막바로 1X10 hypothesis를 계산하여 Softmax를 적용하였으나 뉴럴 네트워크에서는 중간에 hiden layer를 하나 추가한다. 785X124 1차 처리하고 이어서 hidden layer에서 124X10 으로 처리 후 Softmax를 적용하기로 한다. 물론 124 라는 hidden layer 의 컬럼 수는 11784 사이의 적절한 값을 임의로 취할 수 있을 것이다. 하지만 그 값이 변동되더라도 인식률 계산에 그다지 큰 영향을 미치지는 않는다.

      

아래의 표는 SImple Network 와 뉴럴 네트워크의 계산 사례이다.



작도 결과를 보면 α≧0.1 이상 영역에서 96% 안팎의 인식률 값을 보여주며 뉴럴네트워크가 다소 높은 결과를 보여준다.


이와 같이 Covariance 항을 고려한 Softmax에서 Gradient Descent Optimizer를 사용하여 Lagrange’s multiplier α의 최적값을 0.2로 결정하였다. α값이 0.2를 넘어서면 고정된 상수 값의 learning rate = 0.1 로는 cost 계산이 불안정해진다. 따라서 컴퓨팅 과정에서 learning rate 값 자동 변경이 가능한 Optimizer 로서 AdamOptimizer를 사용하면 보다 넓은 법위의 α 값 영역에서 인식률 값을 조사할 수 있을 것이다.

#mnist_nn_covariance_gd_01.py

import tensorflow as tf
import random
import time
#import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

start_time = time.time()
tf.set_random_seed(777)  #reproducibility

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

#parameters
learning_rate = 0.1
training_epochs = 1
batch_size = 100
dof1 = 124
dof2 = 10
alpha = 0.0

X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])

for n in range(0, 12):
    W0 = tf.Variable(tf.random_normal([784, dof1], stddev=0.01))
    b0 = tf.Variable(tf.random_normal([dof1], stddev=0.01))
    W1 = tf.Variable(tf.random_normal([784, dof1], stddev=0.01))
    b1 = tf.Variable(tf.random_normal([dof1], stddev=0.01))
    W2 = tf.Variable(tf.random_normal([784, dof1], stddev=0.01))
    b2 = tf.Variable(tf.random_normal([dof1], stddev=0.01))
    L1 = (tf.matmul(X, W0) + b0 + alpha * (tf.matmul(X, W2) + b2)*(tf.matmul(X, W1) + b1))
    W3 = tf.Variable(tf.random_normal([dof1, dof2], stddev=0.01))
    b3 = tf.Variable(tf.random_normal([dof2], stddev=0.01))
    hypothesis = (tf.matmul(L1, W3) + b3 )
    #define cost/loss & optimizer
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=hypothesis, labels=Y))
    #optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)
   
    #initialize
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    for epoch in range(training_epochs):
        avg_cost = 0
        total_batch = 20000
        #total_batch = int(mnist.train.num_examples / batch_size)
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            feed_dict = {X: batch_xs, Y: batch_ys}
            c, _ = sess.run([cost, optimizer], feed_dict=feed_dict)
            avg_cost += c / total_batch
           
        print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))
        print('Learning Finished!')
       
        #Test model and check accuracy
        correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        print('Accuracy:', sess.run(accuracy, feed_dict={ X: mnist.test.images, Y: mnist.test.labels}))
       
        #Get one and predict
        r = random.randint(0, mnist.test.num_examples - 1)
        print('case=:', n,'alpha=:', alpha, ' lr=:', learning_rate)
        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]}))
       
        alpha = alpha + 0.02

end_time = time.time()
print( "Completed in ", end_time - start_time , " seconds")