z2soo's Blog

Deep learning 예제: CNN 활용 과정 2 본문

Big data & AI/AL&DL

Deep learning 예제: CNN 활용 과정 2

z2soo 2020. 1. 15. 17:30
반응형

목차

지금까지 배운 내용과 tensorflow에서 제공하는 MNIST 데이터 자료를 가지고 CNN을 구현해보되, 이전까지 사용한 것보다 간편한 코드를 사용해본다. 

 

  1. Data pre-processing
  2. Convolution layer process
  3. Fully conndected process
  4. 더 나아가기

Data pre-processing

1. 모듈 삽입

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import pandas as pd

2. 데이터 불러오기

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

3. 데이터 전처리

결측치, 이상치, 정규화, feature engineering에 대한 과정이 진행되어야 한다. 하지만 현재 tensorflow에서 제공하는 MNIST 데이터는 이미 전처리가 완료된 상태이므로 생략하도록 한다. 

 

Convolution layer process : Model 정의 및 그래프 생성

1. 그래프 초기화

tf.reset_default_graph()

2. Placeholder

사용하는 tenssorflow의 버전에 따라 dropout 함수가 제공하는 변수가 rate, keep_prob 으로 달라진다는 점 유의한다.

단, 이번에는 기존 사용하던 nn 패키지가 아닌 layers 라는 새로운 패키지에서 제공하는 dropout 함수를 사용할 것이므로 rate 변수를 사용할 것이다. 

 

  • tf.layers : CCN 을 위한 함수를 제공하는 패키지로 기존 함수보다 간결한 함수를 제공
함수명 설정
tf.layers.convd inputs = 해당 이미지 데이터, filters = 필터 갯수, kernel_size = [필터크기],  padding = "VALID/SAME", strides = 정방형 숫자, activation = 합성곱 이후 수행할 함수 
tf.layers.max_pooling2d inputs = 해당 이미지 데이터, pool_size = [ pool 크기 ], padding = "VALID/SAME",       strides = 정방형 숫자 
tf.layers.dropout inputs = 해당 이미지 데이터, rate = placeholder로 잡아준 죽일 node 비율 
tf.layers.dense inputs = 해당 flatten 데이터, units = 출력 값 크기, activation = 다음 수행할 함수 

 

X = tf.placeholder(shape=[None, 784], dtype=tf.float32)
Y = tf.placeholder(shape=[None, 10], dtype=tf.float32)
drop_rate = tf.placeholder(tf.float32)
# keep_rate = tf.placeholder(tf.float32)

Convolution layer process 

1. Image data 설정

입력 데이터 X를 4차원으로 변환해준다. 해당 데이터의 갯수를 명확히 알지 못하기에 -1로 설정하고, 28 * 28 크기의, 1개의 channel을 가진 흑백 데이터로 설정해준다. 

x_img = tf.reshape(X,[-1,28,28,1])

2. Convolution 과정

convolution 과정 중 layer 패키지를 사용하여 convolution > relu > pooling > dropout 과정을 수행한다.

함수명 설정
tf.layers.convd inputs = 해당 이미지 데이터, filters = 필터 갯수, kernel_size = [ 필터크기 ], padding = "VALID/SAME", strides = 정방형 숫자, activation = 합성곱 이후 수행할 함수 
tf.layers.max_pooling2d inputs =  해당 이미지 데이터, pool_size = [ pool 크기 ], padding = "VALID/SAME",  strides = 정방형 숫자 
tf.layers.dropout inputs= 해당 이미지 데이터, rate= placeholder로 잡아준 죽일 node 비율 

 

# [본래 코드]
'''
F1 = tf.Variable(tf.random_normal([3,3,1,32]), name='filter1')
L1 = tf.nn.conv2d(x_img,
                  F1,
                  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")
'''

# [새로운 코드]
L1 = tf.layers.conv2d(inputs = x_img,
                      filters = 32,
                      kernel_size = [3,3],
                      padding ="SAME",
                      strides = 1,
                      activation = tf.nn.relu)
L1 = tf.layers.max_pooling2d(inputs = L1,
                             pool_size = [2,2],
                             padding = "SAME",
                             strides = 2)
L1 = tf.layers.dropout(inputs = L1, 
                       rate = drop_rate)
                       
L2 = tf.layers.conv2d(inputs = L1,
                      filters = 64,
                      kernel_size = [3,3],
                      padding ="SAME",
                      strides = 1,
                      activation = tf.nn.relu)
L2 = tf.layers.max_pooling2d(inputs = L2,
                             pool_size = [2,2],
                             padding = "SAME",
                             strides = 2)
print(L2.shape)
# (?, 7, 7, 64)

Fully connected process

1. Data flatten

CNN을 통해 얻은 데이터는 4차원이기 때문에 이를 2차원으로 변경해준다.

convoled_data = tf.reshape(L2, [-1,7*7*64])

2. Dense layer 설정

fully connected layer는 dense layer 라고도 불린다. 이에 대해서 다음과 같은 새로운 패키지가 제공해주는 함수를 활용해서 W, b를 비롯한 layer에 대한 모든 설정을 같이 해보도록 한다. 해당 패키지 함수는 W, b에 대한 곱을 비롯한 모든 계산을 알아서 해준다.

 

함수명
설정
tf.layers.dense inputs = 해당 flatten 데이터, units = 출력 값 크기, activation = 다음 수행할 함수
# [이전 코드]
'''
W1 = tf.get_variable("weight1", 
                     shape = [7*7*64, 256],
                     initializer = tf.contrib.layers.xavier_initializer_conv2d())
b1 = tf.Variable(tf.random_normal(shape=[256]),
                 name = 'bias1')
_layer1 = tf.nn.relu(tf.matmul(convoled_data, W1) + b1)
layer1 = tf.nn.dropout(_layer1, keep_prob = keep_rate)
'''

# [새로운 코드]
layer1 = tf.layers.dense(inputs = convoled_data,
                        units = 256,
                        activation = tf.nn.relu)
layer1 = tf.layers.dropout(inputs = layer1,
                           rate = drop_rate)


layer2 = tf.layers.dense(inputs = layer1,
                        units = 128,   
                        activation = tf.nn.relu)
layer2 = tf.layers.dropout(inputs = layer2,
                          rate = drop_rate)


layer3 = tf.layers.dense(inputs = layer2,
                        units = 512,  
                        activation = tf.nn.relu)
layer3 = tf.layers.dropout(inputs = layer2,
                          rate = drop_rate)

3. Hypothesis

# [이전 코드]
'''
logit = tf.matmul(layer2, W3) + b3
H = tf.nn.softmax(logit)
'''

# [새로운 코드]
# softmax를 적용하지 않아도 내부에서 적용이 되는 알고리즘으로 보인다.
H = tf.layers.dense(inputs = layer3, units=10)

4. Cost

새로운 함수를 이용하되, Y, H 의 순서가 바뀐 것에 유의한다. 

  • cost = tf.losses.softmax_cross_entry( Y, H ) 
# [이전 코드]
'''
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits = logit,
                                                                 labels = Y))
'''

# [새로운 코드]
cost = tf.losses.softmax_cross_entropy(Y, H)

5. Train

train = tf.train.AdadeltaOptimizer(learning_rate = 0.01).minimize(cost)

6. Session, 초기화

sess = tf.Session()
sess.run(tf.global_variables_initializer())

7. 학습

for i in range(10):
    tf.reset_default_graph()
    num_of_epoch = 30
    batch_size = 100
    
    for step in range(num_of_epoch):
            num_of_iter = int(mnist.train.num_examples / batch_size)
            cost_val = 0
            for j in range(num_of_iter):
                batch_x, batch_y = mnist.train.next_batch(batch_size)
                _,H_val,cost_val = sess.run([train,H,cost], feed_dict={X : batch_x,
                                                       Y : batch_y, 
                                                       dropout_rate : 0.3})

8. 정확도

predict = tf.argmax(H,1)
correct = tf.equal(predict, tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct, dtype=tf.float32 ))

더 나아가기

 

xavier를 사용한다고 하더라도 결론적으로 w, b의 값은 초기에 랜덤으로 잡히고 즉, 학습을 새로 시킬때마다 학습의 결과가 매번 다르게 나올 수 밖에 없다. 이에 대해 학습과 정확도에 대한 값을 높이고자 등장한 방법이 ensneble, 앙상블이다. 앙상블은 학습 모델을 여러개 만들어서 학습을 시키고, 그 학습 모델마다 각 이미지에 대한 예측값, H를 구하여 더한 값 중 가장 높은 값을 택한다.


모델1: [0.5, 0.3, 0.2, 0.001, 0.99, 0.44 ...]
모델2: [0.4, 0.3, 0.11, 0.05, 0.90, 0.64 ...]

...

모델10: [0.45, 0.4, 0.10, 0.04, 0.95, 0.62 ...]

이미지 하나에 대한 H 값이 위와 같이 나올때, 모든 모델의 값을 모두 더하여 가장 큰 값으로 prediction을 하는 원리이다. 이 과정은 프로그램을 사용하는 것이 아닌 logic으로 해결해야 하며, 객체지향에 대한 이해가 있다면 class 를 활용하면 편리하다. 

반응형

'Big data & AI > AL&DL' 카테고리의 다른 글

Web Crawling Keyword 용어  (0) 2022.04.07
Deep learning : XOR gate  (0) 2020.01.13
인공신경망과 딥러닝 (Neuron network & Deep learning)  (0) 2020.01.10
Comments