TigerCow.Door


안녕하세요. 문범우입니다.

이번 포스팅에서는 TensorFlow에서 CNN을 이용하여 MNIST를 99%로 예측해보도록 하겠습니다.


* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/



1. 기본 구조


이번 실습에서 우리가 진행해볼 구조는 위의 그림과 같습니다.

Convolution layer와 pooling layer가 두번 반복된 구조를 통해 나온 결과를 Fully-Connected layer를 통해 10개의 숫자들 중에서 예측합니다.


2. Layer 1


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf
import matplotlib.pyplot as plt
import random
from tensorflow.examples.tutorials.mnist import input_data
 
# input, 784개의 값을 가지며 n개의 이미지이다.
= tf.placeholder(tf.float32, [None,784]) 
# input 을 이미지로 인식하기 위해 reshape을 해준다. 28*28의 이미지이며 단일색상, 개수는 n개이므로 -1
X_img = tf.reshape(X, [-1,28,28,1]) 
# output
= tf.placeholder(tf.float32, [None,10]) 
 
# layer 1
# 3*3크기의 필터, 색상은 단일, 총 32개의 필터
W1 = tf.Variable(tf.random_normal([3,3,1,32], stddev=0.1)) 
# conv2d 를 통과해도 28*28 크기를 가짐, 대신 32개의 필터이므로 총 32개의 결과가 생김
L1 = tf.nn.conv2d(X_img, W1, strides=[1,1,1,1], padding='SAME'
L1 = tf.nn.relu(L1)
# max pooling을 하고 나면 스트라이드 및 패딩 설정에 의해 14*14크기의 결과가 나옴
L1 = tf.nn.max_pool(L1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME'
cs


먼저 첫번째 레이어는 위와 같이 구성합니다.

초기에 mnist 데이터를 받아오는 것은 그동안 몇번 실습을 하며 익숙해지셨을 것입니다. 들어오는 input 데이터를 처리하고, 이를 이미지로 인식시킵니다.


그리고 첫번째 레이어를 확인해보면, strid는 1, padding은 SAME으로 설정하여 convolution layer를 통과시키고, 이후 relu를 통과시킨 후에 max pooling을 합니다. 이렇게 첫번째 레이어를 통과하면 그 결과는 14*14의 형태를 가집니다.



3. Layer 2


1
2
3
4
5
6
7
8
9
10
# layer 2
# 이번에는 64개의 필터
W2 = tf.Variable(tf.random_normal([3,3,32,64], stddev = 0.1))
# conv2d layer를 통과시키면, [?,14,14,64] 형태를 가짐
L2 = tf.nn.conv2d(L1, W2, strides=[1,1,1,1], padding='SAME')
L2 = tf.nn.relu(L2)
# max pooling 에서 stride가 2 이므로, 결과는 7 * 7 형태를 가질 
L2 = tf.nn.max_pool(L2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# 이후 쭉 펼친다.
L2 = tf.reshape(L2, [-1,7 * 7 * 64])
cs


이후 두번째 레이어도 위에서와 동일한 방식으로 처리합니다.

그리고 마지막에서 fully-connected layer에 넣기 위해 reshape을 처리합니다.



4. Fully-connected layer


1
2
3
4
5
6
7
# fully-connected layer
W3 = tf.get_variable("W3", shape=[7 * 7 * 6410],initializer = tf.contrib.layers.xavier_initializer())
= tf.Variable(tf.random_normal([10]))
hypothesis = tf.matmul(L2, W3) + b
 
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=hypothesis, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)
cs


그리고 두번째 레이어를 통과한 결과 값을 fully-connected layer에 통과시킵니다.



5. Train & Test


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# init
sess = tf.Session()
sess.run(tf.global_variables_initializer())
mnist = input_data.read_data_sets("~/deep_learning_zeroToAll/", one_hot=True)
training_epochs = 15
batch_size = 100
 
# train
print('Learning started. It takes sometimes.')
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('Learning Finished!')
 
# Test
correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.arg_max(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}))
cs


이후 그동안 했던 것처럼 train을 하고 test를 실시합니다.


이렇게 하여 전체 코드를 실행시켜 결과를 확인하면 다음과 같습니다.



99% 이상은 아니지만 약 99%에 가까운 정확도가 나왔습니다.

그리고 추가적으로 99%이상의 정확도를 갖기 위해서, 우리가 진행했던 구조에서 convolution layer와 fully-connected layer를 하나씩 추가하면 됩니다.

위에서 진행한 전체코드는 하단에 첨부하겠습니다. 추가적으로 layer를 더해보는 것은 각자 해보시면 좋을 것 같습니다, :)




블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는 Tensorflow에서 CNN을 다루는 기본적인 내용에 대해서 알아보도록 하겠습니다.


* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/



1. CNN


CNN은 이미지 분류나 텍스트 분류 등 다양한 분야에서 굉장히 좋은 성능을 내고 있습니다. 이에 대한 이론적인 내용은 ML&DL 카테고리에서 다루었습니다.

CNN에서는 크게 3가지로 나눠볼 수 있는데, 첫번째로는 입력되는 이미지, 입력되는 벡터와 같은 것을 convoultion을 통해 filter를 사용하는 방법. 그리고 뽑아낸 값에 대해 데이터를 작게 만드는 subsampling 과정. 그리고 이미지나 벡터에서의 특징을 뽑아내는 feature extraction 과정이 있습니다. 그리고 이렇게 뽑아진 특징들은 우리가 이전에 일반적으로 사용했던 일반적인 Neural Network을 이용하여 classification 등을 하게 됩니다.


CNN이 이미지에 큰 기여를 하고 있는데, 그 중 하나의 예가 위와 같은, CT이미지를 분석하는 것 입니다.



CNN은 우리가 이론에서 알아보았던 것처럼 주어진 이미지에 filter를 통해 stride 만큼 움직이면서 각각 하나의 값을 추출합니다. 그리고 이렇게 얻은 값들을 통해 sampling을 진행합니다.

이러한 것들을 우리가 직접 tensorflow로 진행해볼텐데, 처음인 만큼 간단한 이미지를 통해 진행해보도록 하겠습니다.


위와 같이 3x3 이미지에 2x2 filter를 이용하고 이때 stride 는 1x1로 진행합니다.

이러한 과정을 통하면 총 2x2의 데이터가 나올 것 입니다.


2. TensorFlow 실습


그럼 먼저 image를 만들어보도록 하겠습니다.

실습은 jupyter notebook으로 진행합니다.



위와 같이 필요한 라이브러리를 import 하고 이미지를 만들었습니다.

아래에서 출력된 이미지와 함께 비교해보면 높은 값일수록 어두운 색을 내도록 하는 라이브러리를 이용했음을 알 수 있습니다.



위 그림에서 제일 좌측에 있는 입력이미지를 방금 만들었습니다.

그리고 filter는 2x2로 만들것이고 하나의 색상을 가지고, 1개의 필터를 만들 것이기 때문에 Filter: 2,2,1,1 로 표현되었습니다.

그리고 필터의 값이 이미지에서 대응되는 값과 곱해지고 그 합이 출력되는 값에 입력될 것 입니다. 즉 출력되는 2x2 에서 제일 상단 왼쪽의 값은, 1*1+2*1+4*1+5*1 = 12 가 될 것입니다.


이제 이것을 직접 tensorflow에서 구현해보면 아래와 같습니다.



코드의 가운데에서 사용되는 conv2d 함수가 바로 우리가 위에서 계산했던 것들을 손쉽게 해결해주는 함수입니다.

image와 weight를 알맞게 설정하여 strides와 함께 해당 함수에 넣어주면 위에서 볼 수 있는 올바른 결과가 출력되는 것을 볼 수 있습니다.


이때 우리가 padding을 valid로 주었는데, padding 을 same으로 두면 우리의 결과가 입력의 shape과 일치하도록 텐서플로우에서 자동으로 필요한 모서리를 0으로 채우게 됩니다.



즉 우리의 입력이미지에 대해서 padding을 SAME으로 둔다면 위의 왼쪽그림과 같이 0이 채워질 것입니다.


그리고 이를 코드로 구현해본다면,

위와 같이 padding 을 SAME으로 설정해주고 for 문에서 진행하는 reshape을 3,3으로 설정해주면 올바른 결과가 나오는 것을 볼 수 있습니다.


이제 이렇게 우리가 convolution을 진행해보았는데 다음으로는 pooling이라는 작업을 할 수 있습니다.


물론 pooling 또한 convoultion에 대해 이해를 하셨으면 쉽게 진행할 수 있습니다.

우리가 주어지는 입력 이미지에 대해서 filter 사이즈를 정하고, stride와 padding을 정해주면 됩니다.

그리고 많이 사용하는 max_pooling을 사용해볼 것 입니다.

위의 내용을 코드로 구현해보면 아래와 같습니다.


3. MNIST data


이번에는 예전에 다루어보었던 mnist데이터를 다뤄보도록 하겠습니다.


위와 같이 코드를 구현하면 그 결과와 같이 mnist이미지가 나옵니다.

그리고 이를 convolution layer에 통과시킬 수 있습니다.


코드를 대략적으로 살펴보면, 우리의 입력 imgsms 28x28 크기의 한가지 색상을 갖는 이미지이고 n개의 이미지이기 때문에 그 갯수는 정해져 있지 않습니다. 따라서 -1의 값을 주었습니다.

그리고 strides에서는 2x2를 주었는데, 이렇게 되면 출력은 14x14가 될 것입니다.

그리고 아래의 코드는 단지 이미지를 출력하기 위한 코드이니 아직은 대략적으로 넘기시면 됩니다.


그리고 결과에서 볼 수 있듯이 하나의 이미지에서 약간씩 다른 결과 5개를 확인할 수 있습니다.


그리고 이어서 pooling 을 진행해보도록 하겠습니다.



이또한 strides를 2x2로 하였기 때문에 그 크기가 줄어들어 결과에서 7x7로 나타나는 것을 볼 수 있습니다.


블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요