Data Science/Tensorflow2.0, Pytorch

Learning Tensorflow) 4. 합성곱신경망

HJChung 2020. 4. 19. 13:54

학습목표:

합성곱 신경망(Convolutional Neural Network)와 이와 관련된 구성 요소 및 메서드를 소개

 

1. 합성곱 신경망에 대한 소개

https://libertegrace.tistory.com/entry/1-Basic-CNN

 

1. Basic CNN-1

1. 합성곱 신경망의 기본 구조는 image -> Convolutional layer/Pooling layer/Activation function 의 반복-> Flatten/Fully connected layer -> result입니다. 1) Convolutional layer란 input -> filter -> ou..

libertegrace.tistory.com

 

2. MNIST 분류기를 통해 배워보는 tensorflow 로 CNN구현하기 - 헬퍼함수 정의 (layers.py로 모듈화 할 수 있다.)

 

1) Convolutional layer

 tf.nn.conv2d(x, W, strides = , padding = )
        1. x: input image 또는 네트워크를 따라 이전 합성곱 계층들에서 얻어진 아래층의 feature map 데이터 (각 계층의 출력)

          x의 형태) [이미지의 개수, pixel width, pixel height, color channel]로, 예를 들어, [None, 28, 28, 1] 인 경우, 이미지의 개수는 모르고, 각각은 28x28이며, 색 채널은 1개(gray)임을 나타냅니다. 
        2. W: filter로, 합성곱 필터를 나타내는 네트워크의 학습된 가중치가 매개변수화 된 것

          W의 형태) [filter width, height, dimension, filtermap 개수] 로 예를 들어, [5, 5, 1, 32] 인 경우, filter의 크기는 5x5이고, 1channel data즉, 2차원 영역에 적용되며 32개의 feature map개수로 결과적으로 합성곱계층의 가중치 집합을 여러개 가질 수 있을 때 여기서는 32개의 feature map이 있다는 의미입니다. 
        3. stride: input된 x위에서 공간적 이동을 제어하는 값입니다. 이는 CNN개념 설명에서 잘 나와있습니다. 

        4. padding: ‘SAME’으로 설정하면 연산 결과의 크기가 x의 크기와 같도록 테두리에 padding이 적용됩니다. 

2) 합성곱 결과에 activation function을 적용하고 싶다면

def conv_layer(input, shape):
	W = weigh_variable(shape)
	b = bias_variagle(shape[3])
	return tf.nn.relu(conv2d(input, W) + b) 

이렇게 사용할 수 있습니다. 

 

3) pooling

tf.nn.max_pool(x, ksize = , strides = , padding = )
        1. max pooling은 각 영역에서 입력값의 최대값을 출력합니다. 

        2. ksize : pooling의 크기를 정의

4) dropout

tf.nn.dropout(layer, keep_prob = )
        1. keep_prob: 각 단계에서 학습을 계속할 뉴런의 비율. 테스트 단계에서는 dropout을 적용하지 않아서 이 값이 1.0이 되어야 하는 등 값이 수정 가능해야 하므로 tf.placeholder를 사용해야 합니다. 

5) weight_variable()

: 네트워크의 fully connected layer이나 conv layer의 가중치를 지정해주는 부분입니다. 일반적으로 표준편차가 0.1인 절단정규분포를 사용하여 무작위로 초기화합니다. 

def weight_variable(shape):
	initial = tf.truncated_normal(shape, stddev = 0.1)
	return tf.Variable(initial)
	

6) bias_variable()

: 완전 연결 계층이나 합성곱 계층의 편향값을 정의합니다. 여기서는 모두 0.1로 초기화됩니다.

def bias_variable(shape):
	initial = tf.constant(0.1, shape = shape)
	return tf.Variable(initial)

7) fully connected layer

def full_layer(input, size):
	in_size = int(input.get_shape()[1])
	W = weight_variavle([in_size, size])
	b = bias_variable([size])
	return tf.matmul(input, W)+b

지금까지의 내용을 모아보면 다음과 같습니다. 

def weight_variable():
	initial = tf.truncated_normal(shape, stddev = 0.1)
	return tf.Variable(initial)

def bias_variable():
	initial = tf.constant(0.1, shape = shape)
	return tf.Variable(initial)

def conv2d(x, W):
	return tf.nn.conv2d(x, W, strides= [1, 1, 1, 1], padding = ‘SAME’)

def conv_layer(input, shape):
	W = weigh_variable(shape)
    b = bias_variagle(shape[3])
    return tf.nn.relu(conv2d(input, W) + b) 

def max_pool(x):
	return tf.nn.max_pool(x, ksize = [1, 2, 2, 1]., strides = [1, 2, 2, 1], padding = ‘SAME’)

def full_layer(input, size):
	in_size = int(input.get_shape()[1])
	W = weight_variavle([in_size, size])
	b = bias_variable([size])
	return tf.matmul(input, W)+b

3. MNIST 분류기를 통해 배워보는 tensorflow 로 CNN구현하기 - 모델 구성(minist_cnn.py로 모듈화 할 수 있습니다.)

1) 먼저 이미지와 정답 레이블의 placeholder를 정의합니다. 

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

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

 

2) input image 의 크기를 정해줍니다. (원래 크기를 넣어주거나, channel 추가하거나, reshape등을 할 수 있습니다. )

x_image = tf.reshape(x, [-1, 28, 28, 1])

 

3) 그리고 위에서 알아보았던 여러 메소드들을 조합하여 model architecture을 만듭니다. 

conv1 = conv_layer(x_image, shape = [5, 5, 1, 32]) #input size = 28x28
conv1_pool = max_pool(conv1) #input size = 14x14

conv2 = conv_layer(x_image, shape = [5, 5, 32, 64]) #input size = 14x14
conv2_pool = max_pool(conv1) #input size = 7x7

 

4) fully connected layer에서는 더이상 공간적 측면을 고려할 필요가 없으므로 그 전에 이미지를 vectorization 즉, flatten해 줍니다. 

conv2_flat = tf.reshape(conv2_pool, [-1, 7*7*65])

5) 그리고 fully connected layer을 적용시킵니다. 

full_1 = tf.nn.relu(full_layer(con2_flat, 1024)]

 

6) dropout

keep_prob = tf.placeholder(tf.float32)

full1_drop = tf.nn.dropout(full_1, keep_prob = keep_prob)

7) 결과

y_conv = full_layer(full1_drop, 10)

 

8) train_accuracy

매 batch회의 학습이 진행 될 때마다 모델의 정확도를 출력하여 모델 성능을 중간중간 확인할 수 있습니다. 

 

8) test_accuracy

최종적으로 test한 결과도 출력할 수 있습니다. 

 

전체 코드는 다음과 같습니다. 

x = tf.placeholder(tf.float32, shape = [None, 784])
y = tf.placeholder(tf.float32, shape = [None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])


conv1 = conv_layer(x_image, shape = [5, 5, 1, 32]) #input size = 28x28
conv1_pool = max_pool(conv1) #input size = 14x14
		
	
conv2 = conv_layer(x_image, shape = [5, 5, 32, 64]) #input size = 14x14
conv2_pool = max_pool(conv1) #input size = 7x7


conv2_flat = tf.reshape(conv2_pool, [-1, 7*7*65])

full_1 = tf.nn.relu(full_layer(con2_flat, 1024)]
keep_prob = tf.placeholder(tf.float32)
full1_drop = tf.nn.dropout(full_1, keep_prob = keep_prob)


y_conv = full_layer(full1_drop, 10)

mnist = input_data.read_data_sets(DATA__DIR, one_hot = True)

cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = y_conv, labels = y))

train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

correct_prediction = tf.equal(tf. argmax(y_conv, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	for i in range(STEPS):
		batch = mnist.train.next_batch(50)

	if i%100 == 0:
		train_accuracy = sess.run(accuracy, feed_dict = {x:batch[0], y:batch[1], keep_prob:1.0})
		print(“step {}, training accuracy{}”. format(i, train_accuracy))

sess.run(train_step, feed_dict = {x:batch[0], y:batch[1], keep_prob:0.5})

X = mnist.test.images.reshape(10, 1000, 784)
Y = mnist.test.images.reshape(10, 1000, 10)

test_accuracy = np.mean([ssess.run(accuracy, feed_dict = {x:X[i], y:Y[i], keep_prob:1.0} for i in range(10)])

print(“test accuracy:{}.”.format(tesst_accuracy))