12.convolution


CNN

  • CNNConvolutional Neural Network

  • CNN은 합성곱 계층convolusion layer과 풀링 계층pooling layer으로 구성

  • 지정한 크기의 영역을 window라 하며, 이 window를 오른쪽, 아래쪽으로 움직이면서 hidden layer를 완성
  • 몇 칸씩 움직이는 값을 stride스트라이드라 함

  • 이렇게 input layer의 window를 hidden layer의 뉴런 하나로 압축할 때, convolution 계층에서는 window 크기(ex 3x3이면 9개의 가중치)만큼의 가중치와 1개의 bias이 필요함
  • 이 때 window의 크기와 bias를 kernel 혹은 filter라고 하며, 이 kernel은 해당 hidden layer를 만들기 위한 모든 window에 공통으로 적용
  • 기본 신경망으로 모든 뉴런을 연결하면 784개의 가중치를 찾아내야 하지만, convolution에서는 3x3개인 9개의 가중치만 찾아내면 되므로 시간이 빠름
  • 알고리즘을 진행하는데 튜닝하는 파라미터를 하이퍼 파라미터라함

In [1]:
import tensorflow as tf
import pandas as pd
import numpy as np
In [4]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
Extracting ./mnist/data/train-images-idx3-ubyte.gz
Extracting ./mnist/data/train-labels-idx1-ubyte.gz
Extracting ./mnist/data/t10k-images-idx3-ubyte.gz
Extracting ./mnist/data/t10k-labels-idx1-ubyte.gz


CNN 모델에서는 2차원 평면으로 구성하므로 조금 더 직관적인 형태로 구성할 수 있음.

  • X의 첫번째 차원인 None은 입력 데이터 갯수
  • 마지막 차원은 1, MNIST 데이터는 회색조 이미지라 색상이 한개 뿐이므로 depth=1을 사용
  • 출력값인 10개의 분류와, dropout, keep_prob를 정의
In [5]:
global_step = tf.Variable(0, trainable=False, name="global_step")
X = tf.placeholder(tf.float32, shape=[None, 28, 28, 1], name="X")
Y = tf.placeholder(tf.float32, shape=[None, 10], name="Y")
keep_prob = tf.placeholder(tf.float32, name="KEEP_PROB")


첫 번째 CNN 계층을 구성

  • 3x3 크기의 커널을 가진 convolution 계층을 구성
  • kernel에 사용할 가중치 변수와 tensorflow가 제공하는 tf.nn.conv2d()함수를 사용

In [6]:
# 3x3x1 크기의 커널과 (1)을 가지고32개의 커널
with tf.name_scope("layer1"):
    W1 = tf.Variable(tf.random_normal([3, 3, 1, 32], stddev=0.01))

# 입력층 x, 첫 번째 계층의 가중치 W1, 오른쪽과 아래쪽으로 1칸 , 
# padding="SAME" -> 이미지의 가장 외곽에서 한 칸 밖으로 움직임
# strides=[1, 오른쪽, 아래쪽, 1], 양 끝은 반드시 1
# [batch_size, image_rows, image_cols, number_of_colors]
    L1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1 ,1], padding="SAME")
    L1 = tf.nn.relu(L1)
# [batch_size, images_width, images_height, number_of_colors]
    L1 = tf.nn.max_pool(L1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

In [7]:
with tf.name_scope("layer2"):
# 3x3x1 -- 32개를 받아 64개로 convolution 계층 만듬
    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")

In [8]:
with tf.name_scope("layer3"):
# 7x7x64크기의 1차원 계층을 만들고 중간단계인 256개의 뉴런으로 연결하는 신경망을 만들어줌
# 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)
In [9]:
with tf.name_scope("layer4"):
    W4 = tf.Variable(tf.random_normal([256, 10], stddev=0.01))
    model = tf.matmul(L3, W4)
In [10]:
with tf.name_scope("cost"):
    cost = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
    opt = tf.train.AdamOptimizer(0.001).minimize(cost)
# opt = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
    tf.summary.scalar("cost", cost)
In [11]:
# batch_xs.reshape(-1, 28, 28, 1)
# mnist.test.images.reshape(-1, 28, 28, 1)
In [12]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

merged = tf.summary.merge_all()
writer = tf.summary.FileWriter("./logs/mnist_cnn", sess.graph)
cost_epoch = []


modeling

In [13]:
%%time
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)
        batch_xs = batch_xs.reshape(-1, 28, 28, 1)
        
        _, cost_val = sess.run([opt, cost], feed_dict={X: batch_xs,
                                                       Y: batch_ys,
                                                       keep_prob: 0.8})
        
        total_cost += cost_val
        cost_epoch.append(total_cost)
        
        summary = sess.run(merged, feed_dict={X:batch_xs, Y: batch_ys, keep_prob:0.8})
        writer.add_summary(summary, global_step=sess.run(global_step))
        
    print("Epoch:", "%4d" % (epoch+1), 
          "Avg.Cost:", "%.4f" % (total_cost / total_batch))
    
print("optimization completed")    
Epoch:    1 Avg.Cost: 0.3136
Epoch:    2 Avg.Cost: 0.0977
Epoch:    3 Avg.Cost: 0.0681
Epoch:    4 Avg.Cost: 0.0531
Epoch:    5 Avg.Cost: 0.0438
Epoch:    6 Avg.Cost: 0.0356
Epoch:    7 Avg.Cost: 0.0310
Epoch:    8 Avg.Cost: 0.0275
Epoch:    9 Avg.Cost: 0.0233
Epoch:   10 Avg.Cost: 0.0193
Epoch:   11 Avg.Cost: 0.0198
Epoch:   12 Avg.Cost: 0.0155
Epoch:   13 Avg.Cost: 0.0151
Epoch:   14 Avg.Cost: 0.0130
Epoch:   15 Avg.Cost: 0.0120
optimization completed
CPU times: user 38min 12s, sys: 1min 17s, total: 39min 29s
Wall time: 14min 52s


costfunction

In [14]:
%matplotlib inline
import matplotlib.pyplot as plt

plt.figure(figsize=(20, 8))
plt.plot(cost_epoch, "g")
plt.title("cost")
plt.show()


tensorgrapth

In [15]:
## jptensor.py 를 워킹디렉토리에 import
import jptensor as jp

tf_graph = tf.get_default_graph().as_graph_def()
jp.show_graph(tf_graph)
In [16]:
is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print("accuracy %.4f" % (sess.run(accuracy, feed_dict={
    X:mnist.test.images.reshape(-1, 28, 28, 1),
    Y:mnist.test.labels,
    keep_prob: 1
})))
accuracy 0.9909


labels

In [17]:
%matplotlib inline
labels = sess.run(model, feed_dict={X: mnist.test.images.reshape(-1, 28, 28, 1),
                                    Y: mnist.test.labels,
                                    keep_prob: 1})
fig = plt.figure()
for i in range(10):
    # (2, 5)의 그래프, i + 1번째 숫자 이미지 출력
    subplot = fig.add_subplot(2, 5, i+1)
    
    # x, y축 눈금 제거
    subplot.set_xticks([])
    subplot.set_yticks([])
    
    # 출력한 이미지 위에 예측한 숫자를 출력
    # np.argmax와 tf.argmax는 같은 기능
    # 결과값인 labels의 i번째 요소가 one-hot encoding으로 되어 있으므로
    # 해당 배열에서 가장 높은 값을 가진 인덱스를 예측한 숫자로 출력
    subplot.set_title("%d" % np.argmax(labels[i]))
    
    # 1차원 배열로 되어 있는 i번째 이미지 데이터를
    # 28 x 28형태의 2차원 배열로 변환
    subplot.imshow(mnist.test.images[i].reshape(28, 28))
plt.show()    
In [18]:
from IPython.core.display import display, HTML

display(HTML("<style> .container{width:100% !important;}</style>"))


'Deep_Learning' 카테고리의 다른 글

14.gan  (0) 2018.12.16
13.auto-encoder  (0) 2018.12.15
11.mnist_matplotlib_dropout_tensorgraph  (0) 2018.12.10
10.mnist_dropout  (0) 2018.12.10
00.write_csv  (0) 2018.12.09

+ Recent posts