티스토리 친구하기

본문 바로가기

딥러닝/Your own dataset

CNN code - your own mnist dataset

728x90

 이번 포스팅에서는 CNN(Convolutional Neural Network)를 이용해서 your own mnist dataset을 classification하는 코드에 대해 말씀드리도록 하겠습니다. DNN(Deep Neural Network)와 CNN의 가장 큰 차이점은 import한 이미지를 flat하게 1D로 바꾸는지(28x28=784), 아니면 2D(28x28) 이미지를 그대로 사용하는지에 있습니다. 그래서 수정할 코드는 Model을 design하는 부분입니다.

 

Model Design

 

- DNN

 

X = tf.placeholder(tf.float32, [None, 784]) 
Y = tf.placeholder(tf.float32, [None, num_classes]) 
keep_prob = tf.placeholder(tf.float32) 

W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01)) 
L1 = tf.nn.relu(tf.matmul(X, W1)) 
L1 = tf.nn.dropout(L1, keep_prob) 

W2 = tf.Variable(tf.random_normal([256, 256], stddev=0.01)) 
L2 = tf.nn.relu(tf.matmul(L1, W2)) 
L2 = tf.nn.dropout(L2, keep_prob) 

W3 = tf.Variable(tf.random_normal([256, 10], stddev=0.01)) 
model = tf.matmul(L2, W3)

 

 

- CNN

 

X = tf.placeholder(tf.float32, [None,height,width,channel])
Y = tf.placeholder(tf.float32, [None,num_classes])
keep_prob = tf.placeholder(tf.float32)

# Convolutional Operation
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.max_pool(L1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
L1 = tf.nn.relu(L1)

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.max_pool(L2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
L2 = tf.nn.relu(L2)

# Fully Connected Layer
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)

 

코드를 순서대로 설명하면 다음과 같습니다.

 

1. DNN에서 [None, 784]의 tensor가 input으로 사용되는데, CNN에서는 이미지 그대로 [None, 28, 28, 1]의 tensor가 사용됩니다. 마지막은 channel의 수인데 mnist dataset의 이미지가 gray image이기 때문에 '1' 입니다. 만약 RGB 이미지라면 channel=3 이어야 합니다. 

 

2. DNN에서는 weight의 크기를 정할 때, [None, 784] - [784, 256] - [256, num_classes]로 크기가 연결되도록 정하면 되고, CNN은 channel의 수를 주목해서 weight의 크기를 정하면 됩니다.

- Convolution 부분

 DNN과 비슷하게 앞의 output_channel의 크기와 뒤의 input_channel의 크기를 잘 맞춰서 크기를 정하면 됩니다.

[None, 28, 28, channel=1] - [3, 3, input_channel=1, output_channel=32] - [3, 3, input_channel=32, output_channel=64]

- Fully Connected Layer 부분

 Convolution 연산을 통해 만들어진 feature map을 이용하여 classification 하기 위해서  28x28 크기의 이미지가 pooling으로 인해 7x7 크기로 작아졌습니다. channel의 수는 64이기 때문에, 이미지의 크기와 channel의 크기를 고려하여 Fully connected layer의 weight 크기를 정합니다: [7*7*64, 256]. 그리고 Convolution Layer의 결과인 [None, 7, 7, 64] 크기의 feature map을 fully connected layer의 weight의 크기에 맞게 flatten 하는 작업을 합니다: [-1, 7*7*64]. 여기서, None에 들어갈 숫자는 한번에 학습할 이미지의 수인데, 학습할 때 batch_size로 결정하게 됩니다. 결국 다음과 같은 연산이 이루어지도록 크기를 결정하면 됩니다.

[-1, 7*7*64] - [7*7*64, 256] - [256,  10=num_classes]

 

 

Learning & Evaluation

 

- DNN

 

image, label = sess.run(iterator.get_next())

batch_xs = image.reshape(batch_size,784)
batch_ys = tf.one_hot(label, depth=num_classes).eval(session=sess)

-, loss_val = sess.run([optimizer, cost], feed_dict={X: batch_xs, Y: batch_ys, keep_prob: 0.7})
total_loss += loss_val
batch_xs_test = image_test.reshape(batch_size,784)
batch_ys_test = tf.one_hot(label_test, depth=num_classes).eval(session=sess)

 

 

- CNN

 

image, label = sess.run(iterator.get_next())

batch_xs = image.reshape(-1,28,28,1)
batch_ys = tf.one_hot(label, depth=num_classes).eval(session=sess)

_, loss_val = sess.run([optimizer, loss], feed_dict={X:batch_xs, Y:batch_ys, keep_prob:0.7})
total_loss += loss_val
batch_xs_test = image_test.reshape(batch_size_test,28,28,1)
batch_ys_test = tf.one_hot(label_test, depth=num_classes).eval(session=sess)

 

 

 DNN에서는 loss를 계산하기 위해 feed해줄 batch_xs의 크기를 [batch_size, 784]로 정하지만, CNN에서는 2D image를 input으로 사용하기 때문에 [-1, 28, 28, 1]의 크기로 reshape 해줍니다.

 

 

 

반응형