본문 바로가기

머신러닝&딥러닝/Tensorflow

(Tensorflow) CNN을 이용한 gray 이미지 분류

Intro



이번 포스트에서는 HCI 강의 과제였던 Tensorflow으로 CNN을 이용하여 gray로 변한 된 cifar-10 데이터셋을 학습 및 분류 할 것입니다.


Dataset은 CIFAR에서 교육용으로 무료로 제공하는 이미지를 사용했습니다.

CIFAR은 CIFAR-10과 CIFAR-100으로 나눠진다. CIFAR-10은 총 10개의 class가 있고 CIFAR-100dms 100개의 class가 있습니다.

Datset은 https://www.cs.toronto.edu/~kriz/cifar.html 에서 다운받을 수 있습니다.


이번 포스트에서는 Pyhton 버전의 CIFAR-10 dataset에서 data_batch_1 (class별 1000장씩 10000개의 데이터)가 gray 이미지로 변환된 것을 사용합니다.

CNN



합성곱 신경망(Convolutional Neural Network, CNN)은 이미지 인식과 음성 인식 등 다양한 곳에서 사용되는데, 특히 이미지 인식 분야에서 딥러닝을 활용한 기법은 거의 다 CNN을 기초로 한다.


CNN의 네트워크 구조는 합성곱 계층(convolutional layer)과 풀링 계층(pooling layer)이 등장한다.

합성곱 계층

합성곱 계층에서는 합성곱 연산을 처리합니다. 
합성곱 연산은 이미지 처리에서 말하는 필터 연산에 해당합니다.
합성곱 연산은 필터의 윈도우를 일정 간격을 이동해가며 입력 데이터에 적용하며 계산의 예는 다음과 같습니다.

출처 :  http://deeplearning.stanford.edu/wiki/images/6/6c/Convolution_schematic.gif


합성곱 계층에서 입출력 데이터를 특징 맵(feature map), 입력 데이터를 입력 특징 맵(input feature map), 출력 데이터를 출력 특징 맵(output feature map)이라고 합니다.


패딩

합성곱 연산을 수행하기 전에 입력 데이터 주변을 특정 값(e.g., 0)으로 채우기도 합니다. 이를 패딩(padding)이라고 합니다.
패딩은 주로 출력 크기를 조정할 목적으로 사용합니다. 왜냐하면 합성곱 연산을 몇번이나 되풀이하는 심층 신경망에서 합성곱 연산을 거칠 때마다 어느 시점에서는 출력 크기가 1이 되버려 더 이상 합성곱 연산을 적용할 수 없어지기 때문입니다.

스트라이드

필터를 적용하는 위치의 간격을 스트라이드(Stride)라고 합니다.
예를 들어 스트라이드를 2로 하면 필터를 적용하는 윈도우가 두 칸씩 이동하게 됩니다.

풀링 계층

풀링은 세로, 가로 방향의 공간을 줄이는 연산으로 overfitting을 방지하기 위해 사용합니다.
풀링은 최대 풀링(max pooling), 평균 풀링(average pooling) 등이 있습니다.
최대 풀링은 대상 영역에서 최댓값을 취하는 연산이며, 평균 풀링은 대상 영역의 평균을 계산합니다.

풀링의 특징으로는 다음과 같습니다.
  1. 학습해야 할 매개변수가 없다.
  2. 채널 수가 변하지 않는다.
  3. 입력의 변화에 영향을 적게 받는다.

CNN을 이용한 gray 이미지 분류


전체 구조



CNN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# X reshape 및 normalization
# img 32x32x1
X_img = tf.reshape(X, [-132321])   

 
# L1 ImgIn shape=(?, 32, 32, 1)
#    Conv     -> (?, 32, 32, 32)
#    Pool     -> (?, 16, 16, 32)
F1 = tf.Variable(tf.random_normal([33132], stddev=0.01))
L1 = tf.nn.conv2d(X_img, F1, strides=[1111], padding='SAME')
L1 = tf.nn.relu(L1)
L1 = tf.nn.max_pool(L1, ksize=[1221],
                    strides=[1221], padding='SAME')
 
# L2 ImgIn shape=(?, 16, 16, 32)
#    Conv      ->(?, 16, 16, 64)
#    Pool      ->(?, 8, 8, 64)
F2 = tf.Variable(tf.random_normal([333264], stddev=0.01))
L2 = tf.nn.conv2d(L1, F2, strides=[1111], padding='SAME')
L2 = tf.nn.relu(L2)
L2 = tf.nn.max_pool(L2, ksize=[1221],
                    strides=[1221], padding='SAME')
 
L2_flat = tf.reshape(L2, [-18 * 8 * 64])
cs

3 : input 이미지로 32x32 크기의 gray 이미지입니다.
9 ~ 13 : 첫번째 layer입니다. 
9: F1 크기 : 3x3, 입력 값: 1, 필터 개수: 32의 필터입니다.
10 : convolutional으로 stride = 1, 패딩을 사용합니다.
11 : 활성화 함수로 relu를 사용했습니다.
12 ~ 13 : ksize는 2x2, stride는 2이며 패딩을 사용합니다
ksize는 커널 크기를 의미한다.
[1,2,2,1]은 2x2 입력에 대해 출력 결과를 1개만 나타낸다는 뜻이다.

18 ~ 22 : 두번째 layer입니다.
18 : F2는 크기 : 3x3, 입력 값: 32, 필터 개수: 64의 필터 입니다.
입력 값이 32이가 된 이유는 layer 1에서 필터의 개수가 32개 였기 때문에 총 32개의 입력 값이 생겼기 때문입니다.

dropout

1
L2_flat = tf.nn.dropout(L2_flat, keep_prob)
cs

1 : dropout은 네트워크의 일부를 생략하여 학습을 진행하는 것으로 keep_prob는 참여 비율입니다.
    dropout은 모델이 데이터 overfitting되는 것을 방지하기 위해서 사용됩니다.


전체 코드

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import tensorflow as tf
import numpy as np
import cifar_10_load
 
def next_batch(x_data, y_data, batch_size):
    if (len(x_data) != len(y_data)):
        return None, None
    
    batch_mask = np.random.choice(len(x_data), batch_size)
    x_batch = x_data[batch_mask]
    y_batch = y_data[batch_mask]
    return x_batch, y_batch
 
learning_rate = 0.001
training_epochs = 20
batch_size = 100
 
# placeholders
= tf.placeholder(tf.float32, [None, 1024])
= tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder('float32')
 
# X reshape 및 normalization
# img 32x32x1
X_img = tf.reshape(X, [-132321])   
 
# L1 ImgIn shape=(?, 32, 32, 1)
#    Conv     -> (?, 32, 32, 32)
#    Pool     -> (?, 16, 16, 32)
F1 = tf.Variable(tf.random_normal([33132], stddev=0.01))
L1 = tf.nn.conv2d(X_img, F1, strides=[1111], padding='SAME')
L1 = tf.nn.relu(L1)
L1 = tf.nn.max_pool(L1, ksize=[1221],
                    strides=[1221], padding='SAME')
 
# L2 ImgIn shape=(?, 16, 16, 32)
#    Conv      ->(?, 16, 16, 64)
#    Pool      ->(?, 8, 8, 64)
F2 = tf.Variable(tf.random_normal([333264], stddev=0.01))
L2 = tf.nn.conv2d(L1, F2, strides=[1111], padding='SAME')
L2 = tf.nn.relu(L2)
L2 = tf.nn.max_pool(L2, ksize=[1221],
                    strides=[1221], padding='SAME')
 
L2_flat = tf.reshape(L2, [-18 * 8 * 64])
L2_flat = tf.nn.dropout(L2_flat, keep_prob)
 
# FC 8x8x64 inputs -> 10 outputs
W3 = tf.get_variable("W3", shape=[8 * 8 * 6410],
                     initializer=tf.contrib.layers.xavier_initializer())
= tf.Variable(tf.random_normal([10]))
hypothesis = tf.matmul(L2_flat, W3) + b
 
# cost/loss & optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(
    logits=hypothesis, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
 
# 초기화
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
#gray data, labels 불러오기
gray_data, gray_labels = cifar_10_load.load_cifar_gray_data_and_ohe_labels()
 
# 모델 학습
print('Learning started.')
for epoch in range(training_epochs):
    avg_cost = 0
    total_batch = int(7000 / batch_size)
 
    for i in range(total_batch):
        batch_xs, batch_ys = next_batch(gray_data[:7000], gray_labels[:7000], batch_size)
        feed_dict = {X: batch_xs, Y: batch_ys, keep_prob : 5.0}
        c, _ = sess.run([cost, optimizer], feed_dict=feed_dict)
        avg_cost += c / total_batch
        
 
    print('Epoch:''%04d' % (epoch + 1), 'cost =''{:.9f}'.format(avg_cost))
    correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    print('Accuracy:', sess.run(accuracy, feed_dict={
          X: gray_data[7000:], Y: gray_labels[7000:], keep_prob: 1.0}))
 
 
print('Learning Finished!')
 
# Test
correct_prediction = tf.equal(tf.argmax(hypothesis, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print('Accuracy:', sess.run(accuracy, feed_dict={
      X: gray_data[7000:], Y: gray_labels[7000:], keep_prob: 1.0}))
 
cs


'머신러닝&딥러닝 > Tensorflow' 카테고리의 다른 글

(Tensorflow) XOR Neural Network 만들기  (0) 2019.01.07