CNN(Convolution Neural Network) 이용하기

실습 환경은 Python 3.6과 tensorflow 1.5이다.

 

CNN(합성곱 신경망)

이미지 인식 분야에 주로 사용되는 신경망. 기본적으로 컨볼루션 계층과 풀링 계층으로 구성된다.

 

  • 컨볼루션(합성곱) 계층

2차원 평면 행렬에서 지정된 윈도우의 값에 가중치와 편향을 적용해 하나의 값으로 압축하는 계층

한 윈도우당, 가중치는 윈도우의 크기와 같은 가중치를 곱해야 한다. 편향은 1개만 있으면 된다.

ex) 28x28 입력층(이미지)에 대하여 3x3의 윈도우를 구성했을 때 필요한 최소 가중치의 개수는 3x3 9개, 편향의 개수는 9개이다.

왜 최소라고 적었냐면, 윈도우가 이동할 때 몇 칸씩 이동하냐에 따라 필요한 윈도우 개수가 달라지기 때문이다. 이 이동 범위를 우리는 스트라이드(stride)라고 부른다.

또한 이 한 윈도우에 필요한 가중치와 편향을 우리는 커널(kernal) 또는 필터(filter) 라고 부른다.

복잡한 특징을 가진 이미지들을 잘 분석하기 위해서, 윈도우 당 여러 개의 커널이 사용된다.

 

  • 풀링 계층

지정된 윈도우 내에서 단순히 한 값을 선택해 다음 계층으로 내보내는 계층

 


합성곱 신경망을 사용하여 이전의 MNIST 모델을 재구성해보자. 계층 구성과 학습의 일부분만 수정하였다.

 

2020/07/19 - [개발 일지/ML] - MNIST 학습 모델 만들기

 

MNIST 학습 모델 만들기

실습 환경은 Python 3.6과 tensorflow 1.5이다. MNIST 손으로 쓴 숫자 이미지를 모아 둔 데이터셋. 데이터가 잘 정제되어 있어, 학습자들에게 머신러닝 학습의 기초로 쓰인다. 1. 데이터셋 읽어 오기 import

devpanpan.tistory.com

 

  • 계층 구성 with 컨볼루션 계층, 풀링 계층
# 컨볼루션 계층
W1 = tf.Variable(tf.random_normal([3, 3, 1, 32], stddev=0.01))
L1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1, 1], padding='SAME')
L1 = tf.nn.relu(L1)
# 풀링 계층
L1 = tf.nn.max_pool(L1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# 은닉층 2
W2 = tf.Variable(tf.random_normal([3, 3, 32, 64], stddev=0.01))
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')

# 완전 연결 계층: 인접한 계층의 모든 뉴런과 상호 연결
# 직전의 풀링 개수 7*7*64
W3 = tf.Variable(tf.random_normal([7*7*64, 256], stddev=0.01))
L3 = tf.reshape(L2, [-1, 7*7*64])
L3 = tf.matmul(L3, W3)
L3 = tf.nn.relu(L3)
L3 = tf.nn.dropout(L3, keep_prob)

# 출력층
W4 = tf.Variable(tf.random_normal([256, 10], stddev=0.01))
model = tf.matmul(L3, W4)

 

  • 학습: 규격에 맞는 입력값의 재구성
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

batch_size = 100
total_batch = int(mnist.train.num_examples / batch_size)

for epoch in range(15):
    total_cost = 0

    for i in range(total_batch):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        # 모델에 입력값을 28x28 형태로 전달하기 위한 이미지 재구성
        batch_xs = batch_xs.reshape(-1, 28, 28, 1)
        # 학습 시에는 뉴런의 0.8만 사용
        _, cost_val = sess.run([optimizer, cost], feed_dict={X: batch_xs,
                                                             Y: batch_ys,
                                                             keep_prob: 0.8})

        total_cost += cost_val

    print('Epoch:', '%04d'%(epoch+1),
          'Avg. cost =', '%.3f'%(total_cost/total_batch))

is_corerct = tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_corerct, tf.float32))
print("정확도:", sess.run(accuracy, feed_dict={X: mnist.test.images.reshape(-1, 28, 28, 1),
                                            Y: mnist.test.labels,
                                            keep_prob: 1}))

 

학습 속도가 상당히 느리다(이 포스팅을 쓰는 동안 고작 4회 학습하였다). 

 

한참을 기다려 얻어낸 결과는 다음과 같았다.

Epoch: 0001 Avg. cost = 0.356 
Epoch: 0002 Avg. cost = 0.109 
Epoch: 0003 Avg. cost = 0.074 
Epoch: 0004 Avg. cost = 0.057 
Epoch: 0005 Avg. cost = 0.047 
Epoch: 0006 Avg. cost = 0.039 
Epoch: 0007 Avg. cost = 0.034 
Epoch: 0008 Avg. cost = 0.029 
Epoch: 0009 Avg. cost = 0.025 
Epoch: 0010 Avg. cost = 0.022 
Epoch: 0011 Avg. cost = 0.018 
Epoch: 0012 Avg. cost = 0.016 
Epoch: 0013 Avg. cost = 0.015 
Epoch: 0014 Avg. cost = 0.014 
Epoch: 0015 Avg. cost = 0.013 
정확도: 0.9907

기다린 보람이 있었다!

CNN을 이용하지 않은 MNIST 모델의 정확도는 0.9837이었다. 즉, 0.007만큼 정확도가 상승한 것이다.