코딩이것저것

CNN_deep CNN mnist

황TL 2017. 8. 7. 00:01



CNN을 이용해서 무엇을 할 수 있는지 알려준다.

밑에 설명하겠지만 이미지를 잘게 나누어 layer를 쌓는 과정을 반복하여 인식한다.






예를들어 32x32x3 이미지는 위에서 나온 자동차의 이미지와 같다

5x5x3 filter가 자동차 이미지를 잘게 나눌것이다.

끝자리 3은 dpeth = color을 의미한다.






예제)

1) 위의 자동차의 이미지를 7x7이라고 가정하자

2) 우리는 3x3필터를 사용하여 output을 결정하려고 한다.

3) stride가 1일때 (1칸씩 옆으로 이동)

4) output size는 5x5 가 된다.


위의 output size 공식을 참고하면 이해하는데 도움이 될것이다.






filter를 이용해서 이미지를 나누다보면 원래 이미지의 형상을 기억하지 못할수도 있다.

그래서 padding이라는 도구를 사용하여 원래 이미지의 바깥쪽에 0이라는 픽셀을 삽입한다.

padding을 넣은곳은 filter가 stride하면서 0을 포함하기 때문에 나중에 fully connected 할때도 문제가 없다.





간단하게 소개한 내용을 종합하여 Convolution layer를 만들어보자


예제)

1) 처음 소개 했던 자동차 그림을 32x32x3 이미지라고 가정하자(회색블럭). 32x32는 픽셀을 의미, 3는 RGB(3가지색)을 의미한다

2) CONV, ReLU를 사용하여 5x5x3 filter를 6개 쌓는다(빨간블럭), 회색블럭의 depth=3 이므로 5x5x3 filter 사용

3) CONV, ReLU를 사용하여 5x5x6 filter를 10개 쌓는다(노란블럭), 빨간블럭의  depth=6 이므로 5x5x6 filter 사용

4) 5x5x3 filter가 6개 있으므로 w=5x5x3x6=450, 5x5x6 filter가 10개 있으므로 w=1500개

 







위의 layer를 정리한 모습이다.





CNN을 구현하는 과정을 소개한다.


예제)

1) 맨처음 자동차 이미지를 필터를 이용하여 4x4로 출력한다.

2) max pooling을 이용하여 2x2로 출력한다

3) max pooling은 filter가 stride하면서 가장 큰값을 출력하는 방법이다.

4) max pooing의 결과물이 오른쪽에 나와있다.




# Lab 11 MNIST and Deep learning CNN

import tensorflow as tf

import random

# import matplotlib.pyplot as plt


from tensorflow.examples.tutorials.mnist import input_data

tf.set_random_seed(777)  # reproducibility


#mnist 데이터를 mnist로 정의한다.

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

# Check out https://www.tensorflow.org/get_started/mnist/beginners for

# more information about the mnist dataset


# hyper parameters

# 훈련에 필요한 변수들

learning_rate = 0.001

training_epochs = 15

batch_size = 100


# dropout (keep_prob) rate  0.7~0.5 on training, but should be 1 for testing

# 저번 시간에 소개했던 drop out. 0.5는 layer 진행중에 노드의 절반을 없애는것이고, 1을 훈련때 모든 노드를 예측에 참여시키는것.

keep_prob = tf.placeholder(tf.float32)


# input place holders

#X,Y노드 설정. X노드는 784픽셀, Y노드는 0~9개숫자갯수 =10개

#X_img -> -1 : 몇개든 상관없음,None / 28,28 : 28x28픽셀 / 1 : color(gray)

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

X_img = tf.reshape(X, [-1, 28, 28, 1])   # img 28x28x1 (black/white)

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


# L1 ImgIn shape=(?, 28, 28, 1)

# filter data = weight data

W1 = tf.Variable(tf.random_normal([3, 3, 1, 32], stddev=0.01)) #3x3픽셀 / 1 color / 필터갯수 32개 

#    Conv     -> (?, 28, 28, 32)

#    Pool     -> (?, 14, 14, 32)

L1 = tf.nn.conv2d(X_img, W1, strides=[1, 1, 1, 1], padding='SAME') #원래의 이미지에 W1필터를 stride시킨다.

L1 = tf.nn.relu(L1) # stride 시킨 layer를 ReLU 시킨다

L1 = tf.nn.max_pool(L1, ksize=[1, 2, 2, 1],

                    strides=[1, 2, 2, 1], padding='SAME') #ReLU시킨 layer를 max pooling 시킨다.

L1 = tf.nn.dropout(L1, keep_prob=keep_prob) # max pooling 시킨 layer를 drop out 시킨다.

'''

각각의 network를 거친 shape을 나타낸다.

Tensor("Conv2D:0", shape=(?, 28, 28, 32), dtype=float32)

Tensor("Relu:0", shape=(?, 28, 28, 32), dtype=float32)

Tensor("MaxPool:0", shape=(?, 14, 14, 32), dtype=float32)

Tensor("dropout/mul:0", shape=(?, 14, 14, 32), dtype=float32)

'''


# L2 ImgIn shape=(?, 14, 14, 32)

W2 = tf.Variable(tf.random_normal([3, 3, 32, 64], stddev=0.01)) # 3x3픽셀 / 32 color(이전 layer의 depth를 따라감) / 필터갯수 64개

#    Conv      ->(?, 14, 14, 64)

#    Pool      ->(?, 7, 7, 64)

L2 = tf.nn.conv2d(L1, W2, strides=[1, 1, 1, 1], padding='SAME')

L2 = tf.nn.relu(L2)

L2 = tf.nn.max_pool(L2, ksize=[1, 2, 2, 1],

                    strides=[1, 2, 2, 1], padding='SAME')

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

'''

Tensor("Conv2D_1:0", shape=(?, 14, 14, 64), dtype=float32)

Tensor("Relu_1:0", shape=(?, 14, 14, 64), dtype=float32)

Tensor("MaxPool_1:0", shape=(?, 7, 7, 64), dtype=float32)

Tensor("dropout_1/mul:0", shape=(?, 7, 7, 64), dtype=float32)

'''


# L3 ImgIn shape=(?, 7, 7, 64)

W3 = tf.Variable(tf.random_normal([3, 3, 64, 128], stddev=0.01))

#    Conv      ->(?, 7, 7, 128)

#    Pool      ->(?, 4, 4, 128)

#    Reshape   ->(?, 4 * 4 * 128) # Flatten them for FC

L3 = tf.nn.conv2d(L2, W3, strides=[1, 1, 1, 1], padding='SAME')

L3 = tf.nn.relu(L3)

L3 = tf.nn.max_pool(L3, ksize=[1, 2, 2, 1], strides=[

                    1, 2, 2, 1], padding='SAME')

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

L3_flat = tf.reshape(L3, [-1, 128 * 4 * 4])

'''

Tensor("Conv2D_2:0", shape=(?, 7, 7, 128), dtype=float32)

Tensor("Relu_2:0", shape=(?, 7, 7, 128), dtype=float32)

Tensor("MaxPool_2:0", shape=(?, 4, 4, 128), dtype=float32)

Tensor("dropout_2/mul:0", shape=(?, 4, 4, 128), dtype=float32)

Tensor("Reshape_1:0", shape=(?, 2048), dtype=float32)

'''


# L4 FC 4x4x128 inputs -> 625 outputs

W4 = tf.get_variable("W4", shape=[128 * 4 * 4, 625],

                     initializer=tf.contrib.layers.xavier_initializer()) # weight 초기화 (xavier 함수)

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

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

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

'''

Tensor("Relu_3:0", shape=(?, 625), dtype=float32)

Tensor("dropout_3/mul:0", shape=(?, 625), dtype=float32)

'''


# L5 Final FC 625 inputs -> 10 outputs

W5 = tf.get_variable("W5", shape=[625, 10],

                     initializer=tf.contrib.layers.xavier_initializer())

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

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

'''

Tensor("add_1:0", shape=(?, 10), dtype=float32)

'''


# define cost/loss & optimizer

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(

    logits=logits, labels=Y))

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)


# initialize

sess = tf.Session()

sess.run(tf.global_variables_initializer())


# train my model

print('Learning started. It takes sometime.')

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, 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('Learning Finished!')


# Test model and check accuracy


# if you have a OOM error, please refer to lab-11-X-mnist_deep_cnn_low_memory.py


correct_prediction = tf.equal(tf.argmax(logits, 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, keep_prob: 1}))


# Get one and predict

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

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

print("Prediction: ", sess.run(

    tf.argmax(logits, 1), feed_dict={X: mnist.test.images[r:r + 1], keep_prob: 1}))


# plt.imshow(mnist.test.images[r:r + 1].

#           reshape(28, 28), cmap='Greys', interpolation='nearest')

# plt.show()











위 코드에 언급한것과 같은 맥락이다.

예제)

1) 3x3x1 이미지에 2x2x1 filter를 적용한다. stride : 1x1이고 padding : VALID이다

2) 1~9까지의 3x3이미지에 1,1,1,1의 필터를 적용한다. (오른쪽그림)

3) 필터를 이미지에 매칭시키면 (12,16,24,28)의 이미지가 샘플링된다.

4) gray color로 출력한다. 





위에서 언급했던 padding의 내용이다. 이미지 주변에 0을 감싸준다.




예제)

1) 3x3x1 이미지에 2x2x1 filter를 적용한다. stride : 1x1이고 padding : SAME이다 (padding 적용)

2) 1~9까지의 3x3이미지에 1,1,1,1의 필터를 적용한다. (오른쪽그림)

3) 필터를 이미지에 매칭시키면 패딩의 정보가 포함된 이미지가 샘플링된다.

4) 샘플링된 이미지가 3x3으로 출력된다.(gray color)





예제)

1) 3x3x1 이미지에 2x2x1x3 filter를 적용한다.(필터가 3개) stride : 1x1이고 padding : SAME이다 (padding 적용)

2) 1~9까지의 3x3이미지에 1,1,1,1의 필터를 적용한다. (오른쪽그림)

3) 필터를 이미지에 매칭시키면 패딩의 정보가 포함된 이미지가 샘플링된다.

4) 샘플링된 이미지가 3x3으로 출력된다.(gray color)

5) 필터의 개수가 3이므로 3가지 모양의 픽셀이 출력된다.






위에 소개한 max pooling 방법이다.

filter에 적용된 값에 해당하는 가장 큰 값을 출력한다.

4,3,2,1이 출력되는것을 알 수 있다.

-> max pooling은 이미지의 사이즈가 반으로 줄어들게 한다.





CNN을 이용한 출력값.

원래 이미지가 28x28인데 stride를 2x2로 잡고나서 14x14로 출력된것을 볼 수 있음




14x14로 샘플링된 이미지를 max pooling을 이용하여 7x7로 만듬.