본문 바로가기

Deep Learning

TensorFlow - MNIST ReLU, Xavier 초기화, Dropout 적용하여 정확도 높이기

@markdown

# MNIST ReLU, Xavier 초기화, Dropout 적용하여 정확도 높이기

<br/>

## ReLU 함수 사용

____

- 기존의 Sigmoid 보단 ReLU를 사용하여 인식률을 높인다.

- shape=[512, 512]와 ReLU로 5-Layer를 설계해 Deep하고 Wide한 Neural Network을 구성한다.

<pre><code class="python" style="font-size:15px">import tensorflow as tf

import random

import matplotlib.pyplot as plt

from tensorflow.examples.tutorials.mnist import input_data


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

learning_rate = 0.001

training_epochs = 15

batch_size = 100

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

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


# ReLU 사용한 NN 구성

W1 = tf.Variable(tf.random_normal([784, 256]))

b1 = tf.Variable(tf.random_normal([256]))

L1 = tf.nn.relu(tf.matmul(X, W1) + b1)


W2 = tf.Variable(tf.random_normal([256, 256]))

b2 = tf.Variable(tf.random_normal([256]))

L2 = tf.nn.relu(tf.matmul(L1, W2) + b2)


W3 = tf.Variable(tf.random_normal([256, 10]))

b3 = tf.Variable(tf.random_normal([10]))

hypothesis = tf.matmul(L2, W3) + b3


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)

sess = tf.Session()

sess.run(tf.global_variables_initializer())


for epoch in range(training_epochs):

    avg_cost = 0

    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("---------------------------------------------------------------------")

print('Learning Finished!')

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}))


for epoch in range(5):

    r = random.randint(0, mnist.test.num_examples - 1)

    # print("Test Random Label: ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))

    print("\nTest Image -> ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))

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

    plt.show()

    print("Prediction: ", sess.run(tf.argmax(hypothesis, 1), feed_dict={X: mnist.test.images[r:r + 1]}))

</code></pre>

<pre><code class="python" style="font-size:15px">실행결과

지난번 Sigmoid+NN으로 구성했던 결과보다 5%나 정확도가 증가한 것을 확인할 수 있다.

하지만 초기 cost가 높은 값으로 학습이 시작된다.

Epoch: 0001 cost = 168.560498304

...

Epoch: 0015 cost = 0.686247512

---------------------------------------------------------------------

Learning Finished!

Accuracy: 0.942

</code></pre>

<br/>


## Xavier 초기화 방법

____

- 변수를 xavier initialization 방법을 사용하여 초기값을 초기화해 정확도를 올릴 수 있다.

- 초기값이 적절하게 초기화되어 첫 Cost부터 낮은 값을 얻을 수 있어 효율적이다.

- tf.Variable과 tf.get_variable의 차이는 변수를 생성하냐, 기존의 변수를 공유하냐의 차이이다.

<pre><code class="python" style="font-size:15px"># weights & bias for nn layers

W1 = tf.get_variable("W1", shape=[784, 256], initializer=tf.contrib.layers.xavier_initializer())

b1 = tf.Variable(tf.random_normal([256]))

L1 = tf.nn.relu(tf.matmul(X, W1) + b1)


W2 = tf.get_variable("W2", shape=[256, 256], initializer=tf.contrib.layers.xavier_initializer())

b2 = tf.Variable(tf.random_normal([256]))

L2 = tf.nn.relu(tf.matmul(L1, W2) + b2)


W3 = tf.get_variable("W3", shape=[256, 10], initializer=tf.contrib.layers.xavier_initializer())

b3 = tf.Variable(tf.random_normal([10]))

hypothesis = tf.matmul(L2, W3) + b3

</code></pre>


<pre><code class="python" style="font-size:15px">실행결과

ReLU로 구성한 Network보다 3% 가량 정확도가 올라간 것을 확인할 수 있다.

또한, 초기 Cost값이 상당히 낮은 값에서 점차 줄어드는 것을 확인할 수 있다.

Epoch: 0001 cost = 0.327931981

...

Epoch: 0015 cost = 0.007789033

---------------------------------------------------------------------

Learning Finished!

Accuracy: 0.9755

</code></pre>

<br/>

## Dropout 사용

____

- Network가 깊어지면 Overfitting 현상이 나타날 수 있어, Dropout을 사용한다.

- Dropout은 Network이 Overfitting 되지 않도록 Network(뉴런 연결)을 랜덤으로 끊는 방식으로 overfitting을 방지한다.

- Dropout을 사용해 학습 시킬 경우, 0.5~0.7로 keep_prob 값을 설정하여 Network를 얼마나 유지(50%~70%)할지 설정해준다.

 

<pre><code class="python" style="font-size:15px">import tensorflow as tf

import random

import matplotlib.pyplot as plt

from tensorflow.examples.tutorials.mnist import input_data


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

learning_rate = 0.001

training_epochs = 15

batch_size = 100


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

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


# Network의 학습, 테스팅에 얼마나 유지, 학습에 사용할지 설정값을 placeholder 변수로 초기화한다.

# Train과 Testing 두 곳에서 각각 다른 값을 사용해야하기 때문에

keep_prob = tf.placeholder(tf.float32)


W1 = tf.get_variable("W1", shape=[784, 512], initializer=tf.contrib.layers.xavier_initializer())

b1 = tf.Variable(tf.random_normal([512]))

L1 = tf.nn.relu(tf.matmul(X, W1) + b1)

L1 = tf.nn.dropout(L1, keep_prob=keep_prob)


W2 = tf.get_variable("W2", shape=[512, 512], initializer=tf.contrib.layers.xavier_initializer())

b2 = tf.Variable(tf.random_normal([512]))

L2 = tf.nn.relu(tf.matmul(L1, W2) + b2)

L2 = tf.nn.dropout(L2, keep_prob=keep_prob)


W3 = tf.get_variable("W3", shape=[512, 512], initializer=tf.contrib.layers.xavier_initializer())

b3 = tf.Variable(tf.random_normal([512]))

L3 = tf.nn.relu(tf.matmul(L2, W3) + b3)

L3 = tf.nn.dropout(L3, keep_prob=keep_prob)


W4 = tf.get_variable("W4", shape=[512, 512], initializer=tf.contrib.layers.xavier_initializer())

b4 = tf.Variable(tf.random_normal([512]))

L4 = tf.nn.relu(tf.matmul(L3, W4) + b4)

L4 = tf.nn.dropout(L4, keep_prob=keep_prob)


W5 = tf.get_variable("W5", shape=[512, 10], initializer=tf.contrib.layers.xavier_initializer())

b5 = tf.Variable(tf.random_normal([10]))

hypothesis = tf.matmul(L4, W5) + b5


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)


sess = tf.Session()

sess.run(tf.global_variables_initializer())


# train my model

for epoch in range(training_epochs):

    avg_cost = 0

    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)

        # keep_prob : Network의 70%를 유지해 학습

        feed_dict = {X: batch_xs, Y: batch_ys, keep_prob: 0.7}

        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("---------------------------------------------------------------------")

print('Learning Finished!')


correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))

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

# keep_prob : 100%의 Network을 사용해 학습된 모델로 예측하겠다.

print('Accuracy:', sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels, keep_prob: 1}))


for epoch in range(5):

    r = random.randint(0, mnist.test.num_examples - 1)

    # print("Test Random Label: ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))

    print("\nTest Image -> ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))

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

    plt.show()

    print("Prediction: ", sess.run(tf.argmax(hypothesis, 1), feed_dict={X: mnist.test.images[r:r + 1], keep_prob: 1}))

</code></pre>

<pre><code class="python" style="font-size:15px">실행결과

98%까지 정확도가 올라간 것을 확인할 수 있다.

Epoch: 0001 cost = 0.474214064

...

Epoch: 0015 cost = 0.045329618

---------------------------------------------------------------------

Learning Finished!

Accuracy: 0.9806

</code></pre>


## Adam Optimizer 사용

____

- TensorFlow에는 다양한 Optimizer가 있지만 그 중에서 Adam Optimizer가 가장 성능이 좋다.

- 이전에는 GradientDescentOptimizer를 주로 사용했지만, 위의 예제에서 모두 Adam Optimizer를 Cost를 최소화했다.

<pre><code class="python" style="font-size:15px">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)

</code></pre>


> 소스코드 - 모두를 위한 머신러닝 김석훈 교수님 강의 참고 : ([https://hunkim.github.io/ml/](https://hunkim.github.io/ml/))