티스토리 뷰

AI

[CNN] Convolution Neural Network 2

감자형 2018. 10. 30. 01:59
안녕하세요, 감자코딩에 감자개발자입니다.
이번시간에는 CNN 2번째 시간인데요, 좀더 시각화적으로 이해하기위한 포스팅입니다. yoonicon님의 포스팅글을 참조하였습니다.





1.Convlution Neural Network(CNN)
CNN의 핵심은 사진을 학습하는것. input으로 Label이 붙은 이미지 파일을 주고 수많은 이미지를 학습시켜 추후에 새로운 이미지가 입력되었을때 정확히 Label을 붙이는것을 목적으로 한다. 
예를 들어) 강아지,고양이,새 등 여러 동물의 이미지를 보여주고 새로운 강아지의 이미지를 입력하였을때 컴퓨터가 이미지를 판단하는것이 CNN목적이다.
우리의 뇌 = 부분적인식 = CNN


CNN의 기본 골격
Convolutional layer(Conv), Pooling layer(Pool), ReLU layer(for nonlinearity), Fully connected layer(FC)

2.Data

Input = 이미지
이미지의 구조는 3개의 숫자로 표현될 수 있음. 3차원 배열로 width X height X depth 의 이미를 지닌다.
(가로,세로,색깔) 
가로 세로 = 이미지의크기
세번째항, 색이 있는 이미지 여부( 이값이 1일 경우 흑백, 3(RGB)이라면 컬러 이미지 의미)
배열의 각항들은 0~255 사이의 값을 가지고 있음 3채널로 처리하는거 아니면 24비트로 처리 하는것

예)
(x,y,0) R의 정보 / (x,y,1) G의 정보 / (x,y,2)B의 정보

Output의 경우는 이미지가 어떤 Label을 가질 확률로 제시된다.


03. Layer I

 01) Convolutional layer(Conv)

  (1) Filter

본격적으로 Layer에 대해 살펴보겠습니다. 먼저 Convolutional layer입니다. 이름에서도 알 수 있듯이 CNN의 핵심이 되는 Layer입니다. Conv는 이미지의 특성을 뽑아내는 Layer라고 할 수 있습니다. 아래 이미지는 Conv의 원리를 그대로 보여주고 있습니다.

Input된 이미지에  Filter를 이용하여 이미지의 특성을 뽑아낸다.
Image의 이미지 여부와 * Filter와 곱해서 Convolved Feature를 뽑아낸다.

 여기서 Filter는 빨간색 숫자로 표시된   를 의미합니다.(Filter를 다른 말로 Kernel, Neuron이라고도 합니다. 또한 Filter가 비추는 영역을 가리켜 Receptive field라고 합니다.)
 Filter는 2차원 배열입니다. 다만 R, G, B 정보를 담은 2차원 배열에서 각각 정보를 추출해야하기 때문에 컬러 사진(Depth = 3)에서는 Filter의 Depth 역시 3이 됩니다. 위 그림에서 Filter는 정확히 1칸씩 움직이며 정보를 추출해내고 있습니다. 움직이는 칸수를 Stride라고 합니다.
 필터를 통해 추출해낸 숫자를 담은 배열을 Activation map이라고 부릅니다. Activation map의 개수는 사용한 Filter의 개수와 같습니다.
Filter는 이미지에서 정보를 추출하는 Feature identifier라고 하면 이해하기 쉬울 것입니다. 예를 하나 들어보겠습니다. II

 * 예시

다음과 같은 귀여운 쥐의 이미지가 Input으로 주어졌습니다. 우리는 Filter를 이용하여 이미지의 정보(Feature)를 추출해낼 것입니다.
여러 종류의 Filter를 쓸테지만 가장 먼저 이와 같은 Filter를 사용할 것입니다.
먼저 왼쪽에서부터 Filter에 들어맞는 Feature가 있는지 살펴보겠습니다. 위 그림에서 노란색으로 표시된 Receptive field에 Filter를 가져다대보겠습니다.
계산값(6600)이 매우 크게 나옵니다. 이 말은 해당 Receptive field에 Filter에 담긴 정보가 존재한다는 뜻입니다.
이와 반대로 오른쪽 귀퉁이의 Receptive field에 Filter를 가져다대봤더니 전혀 맞지 않았습니다. 다시 말해 오른쪽에는 Filter에 해당하는 정보가 없다는 것을 알 수 있습니다.

 (2) Activation map(Feature map)

Filter를 사용하여 뽑아낸 숫자를 모아놓은 것을 Activation map이라고 한다고 했습니다. Activation map의 크기는 Filter의 크기와 Stride, 그리고 Padding에 의해 결정됩니다. Activation map의 크기에 대해 아는 것이 왜 중요할까요? Filter를 통해 Convolution을 하여 만든 Activation map은 본래의 이미지 크기보다 작을 수밖에 없습니다. 크기가 작아진다는 개념을 아는 것은 중요하지만 직접 구하는 것은 그리 중요치 않으므로 계산값만 알고 넘어가겠습니다.
이와 더불어 Padding의 개념을 아는 것이 중요합니다. Convolution을 자꾸 하다 보면 이미지가 자꾸 작아진다고 하였는데 Padding 값을 주어 이를 막을 수 있습니다.
위와 같은 식으로 본래 이미지의 둘레에 0으로 둘러쌀 수가 있는데 이를 Zero padding이라고 부릅니다. 이는 이미지 정보 손실을 방지함과 동시에 모서리 정보를 전달하는 기능도 합니다.


02) ReLU Layer

 * 활성화 함수

더 보기↓
중요한 점은 이 Layer에서 ReLU 함수를 사용한다는 것입니다. 이는 Nonlinearity를 부여하는 역할을 합니다. Linear과 Nonlinear의 개념은 아래와 같습니다.
Conv 를 통과한 데이터는 덧셈, 곱셈으로만 이루어져있습니다. 다시 말해 Linear한 상태입니다. Linear할 경우 단순한 데이터 분류는 가능하지만 복잡한 데이터 분류는 힘듭니다.
*중요* 따라서 CNN에서는 ReLU를 이용하여 Non-Linearity 속성을 부여하게 됩니다.

@ Systematic evaluation of CNN advances on the ImageNet
Linear하지 않은 함수를 이용하지 않을 경우 정확도가 매우 낮음을 보여주는 그래프입니다.

 03) Pooling Layer

Pooling layer는 Sub-Sampling을 목적으로 구성되어져있습니다. Conv를 거친 데이터로부터 한번 더 표본을 뽑아내겠다는 소리입니다. 그것도 좋은 녀석들로만 골라서 말입니다.
왼쪽 행렬은 Conv를 지난 Activation map입니다. Activation map의 구획을 나누어 구획에서 대표 표본을 뽑아내는 것이 Pooling의 목적입니다. 위 그림은 Pooling의 방법 중 하나인 Max pooling을 보여주는 그림입니다. Max pooling은 말 그대로 구획에서 가장 큰 값을 뽑아내는 방법입니다. Average pooling, L2-norm pooling 등이 있다고 하나 Max 가 가장 좋은 방법이라고 합니다. 아무튼, 이렇게 Pooling을 하면 크게 두 가지 효과를 얻을 수 있습니다. 첫째, 정말 꼭 필요한 데이터만 뽑아낼 수 있다는 것, 둘째, 그로 인해 데이터의 양이 작아진다는 것입니다. 예를 들어 주황색 칸에서 1, 0 등은 딱히 쓸모가 없는 값이잖아요. 또한 원본 이미지에서 맥락에 맞지 않는 약간의 노이즈가 들어갈 경우에도 Pooling 과정을 거치면 노이즈를 일부 제거하고 데이터를 학습시킬 수가 있게 됩니다.
 

@ Andrej Karpathy CS231n Course Notes, Stanford University
여기까지의 결과물이 위 그림입니다.

 04) Fully Connected Layer (FC layer)

마지막 FC layer에서 이전까지의 정보를 모두 모아 Softmax classification을 통해 숫자를 예측하게 됩니다.


tf.Reshape의 의미 : 1차원 배열로 쭈욱늘어트리는 것을 의미한다.

실습

이번 실습 역시 MNIST로 시작해보도록 하겠습니다.

1
2
3
4
5
6
import tensorflow as tf
import matplotlib.pyplot as plt
import random
 
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)




학습을 위한 셋팅을 먼저 해주시고요.

1
2
3
4
# 학습의 속도와 Epoch, 그리고 데이터를 가져올 batch의 크기를 지정해 줍니다.
learning_rate = 0.001
training_epochs = 3
batch_size = 100





1
2
3
4
5
6
7
8
# 먼저 이미지의 정보를 담을 X를 placeholder로 지정해줍니다.
X = tf.placeholder(tf.float32, [None, 784])
 
# 가져온 정보를 이미지화 하기 위하여 reshape합니다.
X_img = tf.reshape(X, [-1, 28, 28, 1])   # img 28x28x1 (black/white)
 
# 이미지의 Label 정보를 담을 Y 역시 placeholder로 지정해줍니다.
Y = tf.placeholder(tf.float32, [None, 10])




기본적인 세팅은 끝났으니 본격적으로 Convolution부터 시작해보도록 하겠습니다. 우선 Filter를 만들어야 합니다.

1
2
3
4
5
6
# CNN에서 우리는 결국 제대로 된 Filter를 가진 Model을 구축해 나갈 것입니다.
# 다시 말해 Filter를 학습시켜 이미지를 제대로 인식하도록 할 것입니다.
# 그렇기에 Filter를 변수 W로 표현합니다.
# 32개의 3 x 3 x 1의 Filter를 사용하겠다는 뜻입니다.
 
W1 = tf.Variable(tf.random_normal([3,3,1,32], stddev=0.01))




이 Filter를 직접 적용해보도록 하겠습니다.

1
2
# 간단하게 conv2d 함수를 사용하면 됩니다.
L1 = tf.nn.conv2d(X_img, W1, strides=[1,1,1,1], padding='SAME')



ReLU layer와 Pooling layer 역시 간단한 코드 한줄로 구현이 가능합니다.

1
2
L1 = tf.nn.relu(L1)
L1 = tf.nn.max_pool(L1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')




이 과정을 반복해줍니다.

1
2
3
4
5
# W2는 두번째 Conv의 Filter입니다.
# 다만 이전 과정 Filter의 개수가 32개였기 때문에
# 그 숫자에 맞추어 depth를 32로 지정해줍니다.
 
W2 = tf.Variable(tf.random_normal([3,3,32,64], stddev=0.01))



역시 Conv를 한 후에 ReLU와 Pooling을 추가하여 줍니다.

1
2
3
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')




이제 마지막으로 Fully Connected Layer를 통과시켜봅시다. FC layer에서는 Softmax Classfication을 사용하여 가설과 실제 Label을 비교해보는 작업을 통해 학습이 이루어집니다.

1
2
3
4
5
# Softmax를 통한 FC layer를 활용하기 위해 shape를 변환해줍니다.
# 위에서 L2는 일종의 X 값이라고도 볼 수 있습니다.
# Softmax를 거칠 예측값(WX+b)을 만들어주기 위해 reshape 합니다.
 
L2 = tf.reshape(L2, [-1, 7*7*64])




W, b를 설정해봅시다.

1
2
3
4
5
6
# W3를 설정하는데 Xavier initializing을 통해 초기값을 설정할 것입니다.
# reshape된 L2의 shape이 [None, 7*7*64] 였으므로
# W3의 shape은 [7*7*64, num_label]이 됩니다.
 
W3 = tf.get_variable("W3", shape=[7*7*64, 10], initializer = tf.contrib.layers.xavier_initializer())
b = tf.Variable(tf.random_normal([10]))





따라서 가설은 익숙한대로 이렇게 됩니다.

1
hypothesis = tf.matmul(L2, W3) + b

끝으로 cost와 optimizer는 간단하게 아래와 같이 설정할 수 있습니다.

1
2
3
4
5
6
7
# Softmax 함수를 직접 사용하는 대신에 sofmax_corss_entropy_with_logits을 사용할 수 있습니다.
# 인자로 logits과 label을 전달해주면 됩니다.
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=hypothesis, labels=Y))
 
# 이전까지는 Gradient Descent Optimizer를 사용하였지만
# 좀 더 학습성과가 뛰어나다고 알려져있는 Adam Optimizer를 사용하겠습니다.
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)





이제 세션을 만들고 실행시켜주면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
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}
        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!')





끝으로 우리가 만든 학습 모델이 잘 학습되었는지 테스트를 해보도록 합시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 먼저 늘 그래왔듯 accuracy op를 만들고요.
correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
 
# MNIST의 테스트용 이미지를 feed_dict로 전달합니다.
print('Accuracy:', sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels}))
 
# 랜덤하게 하나의 이미지를 정확히 맞추는지 역시 테스트가 가능합니다.
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(hypothesis, 1), feed_dict={X: mnist.test.images[r:r + 1]}))
 
# matplotlib을 사용하여 랜덤하게 뽑힌 이미지를 출력할 수도 있습니다.
plt.imshow(mnist.test.images[r:r + 1].reshape(28, 28), cmap='Greys', interpolation='nearest')
plt.show()





너무 정리를 잘해놓으셔서 참조를 했습니다.





공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함