티스토리 뷰

모두의 딥러닝

Convolutional Neural Networks

강의-1

이번 강의는 영상 분석에서 많이 사용하는 CNN이다.

CNN 강의 유명한 cs231n 강의에서 모든 자료는 발췌했다고 한다.

고양이에게 어떤 영상을 보여주고, 고양이 뇌를(뉴런) 분석하니, 특정 모양에서 특정 뉴런들이 반응하는 확인하였다. 그걸 보고 똑같이 학습을 시켜 보자란 취지에서 착악된게 CNN 학습법이다.

CNN 학습하는 방법에 대해 나타낸 이미지이다. 우선 Convolution , ReLU 한다. 작업을 반복하다, Pooling 한다. 그리고 마지막으로 Fully Connected Layer 만들어 Softmax 클래스로 분류한다. 물론, 어떻게 Layer 구조를 정하는지는 정해져 있지 않았다.

우선 Convolution 대해 알아보자. 위의 이미지는 Convolution하는 과정을 나타낸 이미지이다.

우선 32x32x3(가로x세로x필터) 이미지를 Convolution 해보자, 필터가 3 이유는 해당 이미지는 컬러(Red, Green, Blue)이기 때문이다.

픽셀(pixel, 화소) 1개는 흑백의 경우 1바이트를 사용하기 때문에 256단계의 gray scale 표현할 있고, 컬러의 경우 RGB 1바이트씩 할당하기 때문에 256x256x256만큼의 색상을 표현할 있다.

참조: http://pythonkim.tistory.com/52

 

여기서 주의할 점은, 우리가 사용하는 필터의 색상 값과 입력 값의 색상 값은 같아야 한다.

우리는 여기서 하나의 숫자를 구하는데, 구하는 함수는 기존에 사용하던 Wx+b 방식과 똑같다. 그리고 이후 나온 값에 ReLU 해주면 우리가 원하는 Convolution 구할 있다.

위의 이미지 처럼 Filter 지정한 크기(Stride) 만큼 이미지를 이동하며 하나의 값을 가져온다.

참고로 위의 이미지에서 Filter 크기는 5x5x3이므로 75개의 w(w1~w75) 정해진다. 해당 w 모든 이미지(stride 통해 이동되는) 동일하게 적용된다.

해당 이미지처럼 7x7 이미지에서 Filter(3x3) 칸씩 이동을 하게 된다. 칸씩 이동하는 이유는 Stride라고 하는 것을 1 설정했기 때문이다. 그래서 나오는 이미지의 크기는 5x5 된다.

다음은 동일한 크기의 이미지와 Filter에서 Stride 2 설정했을 때의 이미지이다. Stride 2이기 때문에 Filter 2 이동하게 된다. 그래서 최종적으로 결과값은 3x3 된다.

위의 이미지는 이미지가 Filter 거친 가지게 되는 크기를 계산하는 식이다.

7x7이미지에서 3x3 Filter 사용하고 Stride 1 설정했다. Output 원본 이미지 크기 그대로 7x7 하고 싶으면 어떻게 하면 될까? 대한 해답을 알려주는 이미지이다. 원본 이미지 크기를 유지할 있는 방법이 존재하는데 부족한 부분을 위의 이미지와 같이 0(Pad)으로 채워 Filter 하면 원본이미지 크기를 유지할 있다. 물론 Stride 커질 수록 Pad 또한 커져야 된다.

다음 이미지는 Filter 통해 생성된 이미지들이 6개가 있는 모습이다. 6Filters 또는 6Channel이라고 부르는데, 각각의 Chanel 다른 Filter 갖는다. 여기서 다른 Filter 의미는 다른 w b값을 갖는다 이다. 그래서 6 filters (5x5x3) Filter 거친 이미지 6개를 가진다는 이야기 이다.

Convolution layers 하는 과정을 보여주는 이미지이다. 처음에는 6개의 Filter 만들고 다음으로는 10개의 Filter 만들었다. Filter 갯수가 많아짐에 따라 이미지의 굵기는 굵어졌지만, Pad값을 정하지 않았기 때문에, 가로x세로의 크기는 줄어들게 되는 모습이다.

변수의 개수는 몇개일까? 6Filter 5x5x3이므로 6*5*5*3 = 450개가 변수의 개수(빨간이미지)이다.

그리고 노란 이미지의 경우는, 10*5*5*6 이므로 1500개의 변수가 세팅된다.

강의-2

이번 동영상은 Pooling Fully connected 대해서 알아보자.

위의 이미지가 Pooling layer 하는 모습을 나타낸 것이다. Pooling 하면 Filter(굵기?) 크기는 그대로이나, 가로x세로의 길이가 작아진다.

Pooling 종류가 몇개가 있다고 하나, 가장 흔히 쓰이는게 Max Pooling이라고 한다. Max Pooling이란 Filter 중에 제일 값을 가져와 Resize한다. 위의 이미지의 경우, 2x2 Filter stride 2이다. 여기서 Filter(굵기) 중요하지 않은데, 왜냐하면 Pooling 하더라도 Filter값은 변하지 않기 때문이다.

위의 4x4이미지를 2x2 Filter Stride 2 설정하면, 오른쪽과 같은 2x2이미지로 Resize된다.

Fully Connected Layer 우리가 이전에 사용했던 Softmax 라고 생각하면 된다.

http://cs.stanford.edu/people/karpathy/convnetjs/demo/cifar10.html

위의 링크에서 CNN Demo 확인할 있다.

강의-3

이번 강의는 CNN 이용한 ImageNet에서 구성했던 그리고 CNN 초창기에 구성했던 형태에 대해 다룬다.

우선 CNN 초창기 모습이다. LeCun 교수님이 처음 CNN 대해 발표를 하셨고, 위와 같이 구성되었다.

위의 이미지를 보면 이제는 어느정도 해석이 가능할 같다. 96 채널로 11x11x3 Filter Stride 4 설정해서 227x227x3 이미지를 Convolution 한다. 그러면 이미지는 55x55x96으로 구성이되고, 해당 이미지를 구성한 변수는 11*11*3*96= 35k 된다.

2번째 Layer Pooling이다. 이미지의 크기는 55x55x96이고, Filter 크기는3x3x96이고 Stride 4이다. 그러면 Output Layer 27x27x96 된다. 그리고 Pooling 경우는 w값이 필요 없기 때문에 Parameter 없다.

위의 이미지는 AlexNet 어떻게 구성했는지 보여주는 이미지이다.

위의 이미지는 GoogLeNet 구성 방법이다. 김성훈 교수님은 창의적으로 뉴런을 구성했지만, 우리도 충분히 있을 같다고 말한다.

위의 이미지는 ResNet이라고 2015년도에 ImageNet에서 우승을 구성인데, 이전의 Layer보다 훨씬 많은 Layer 구성되어있다. 그럼 학습이 제대로 이루어질까란 의문을 가질 있지만, ResNet 조금 색다르게 Layer 구성된다.

위의 이미지와 같이 학습을 시킬 , Layer 뛰어넘고, 기존 Layer 합치는 방법으로 구성이 된다.

위의 이미지는 ResNet 계산되는 방법이다. 학습이 잘되는지에 대해서는 누구도 없지만, 위의 이미지처럼 학습이 이루어진다.

그리고 자랑스러운 우리나라 김윤 박사님이 만든 CNN으로 구성된 문자 분류이다. 문자의 경우 나중에 배우는 RNN으로 학습을 많이 시키는데, CNN으로 학습 모델을 구성했고, 많은 사람들이 사용하는 모델 하나라고 말씀하셨다.

위의 이미지는 딥러닝으로 유명한 알파고에 대한 이미지와 학술지 Nature 나온 알파고를 구성한 모델에 대한 설명이다. 알파고 또한 CNN으로 학습되었고,

“19x19x48 이미지를 Input으로 넣고 초기 필터값은 5x5x48 채널은 192, stride 1, pad 2 설정하였다. 2번째 Convolution 3x3x192 채널은 192, stride 1, pad 1 설정하였다….”

생각보다, 학술지를 이해하는데 어렵지 않았다. 학술지 또는 논문을 보며, 딥러닝에 대해 연구해보자는 생각이 들었다.


Lab-1

이제는 CNN 한번 구성하여, MNIST 99% 정확도가 되게 만들어보자.

위의 그림과 같이 CNN Convolution Sampling 그리고 Fully connected 구성되어있다. 위의 이미지는 Convolution 2 Sampling 2 그리고 Fully connected 구성된 이미지이다.

위의 이미지는 Padding 설정에 따른 처리 방법을 이미지로 나타낸 이다.

우선 설정은 VALID SAME두가지의 방법이 있다. Valid 경우, Padding없이 그대로 필터를 거치게 됨으로 1,2,2,1 같은 결과 이미지가 나오게 된다.

Same 경우, 이미지와 크기를 똑같은 결과가 나오게 하는 설정으로 부족한 부분만큼 0으로 Padding 채운다. 그래서 결과는 Input이미지와 동일한, 1,3,3,1 나오게 된다.

Max Pooling 대한 이미지이다. Image 2,2 크기로 stride 1로해서 padding same설정으로 처리한다는 내용이다.


Lab-2

 

import tensorflow as tf
import random

from tensorflow.examples.tutorials.mnist import input_data

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

learning_rate =
0.001
training_epochs = 15
training_batch = 100

X = tf.placeholder(tf.float32, shape=[None, 784])
X_image = tf.reshape(X
, [-1, 28, 28, 1])
Y = tf.placeholder(tf.float32
, shape=[None, 10])

W1 = tf.Variable(tf.random_normal([
3, 3, 1, 32], stddev=0.01))

L1 = tf.nn.conv2d(X_image
, W1, 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')

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')

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

W3 = tf.get_variable(
"W3", shape=[7 * 7 * 64, 10], initializer=tf.contrib.layers.xavier_initializer())
b = tf.Variable(tf.random_normal([
10]))
logits = tf.matmul(L2_flat
, W3) + b

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=Y))
train = tf.train.AdamOptimizer(
learning_rate=learning_rate).minimize(cost)

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

for epoch in range(training_epochs):
    avg_cost =
0
   
total_batch = int(mnist.train.num_examples / training_batch)

   
for batch in range(total_batch):
        batch_xs
, batch_ys = mnist.train.next_batch(training_batch)
        c_
, _ = sess.run([cost, train], feed_dict={X: batch_xs, Y: batch_ys})
        avg_cost += c_ / total_batch

   
print(epoch, '%04d' % (epoch + 1), 'cost = ', '{:9f}'.format(avg_cost))

correct_prediction = tf.equal(tf.argmax(logits
, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction
, tf.float32))

print('Accuracy:', sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels}))

r = random.randint(
0, mnist.test.num_examples - 1)
print('Label: ', sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))
print('Prediction: ', sess.run(tf.argmax(logits, 1), feed_dict={X: mnist.test.images[r:r + 1]}))

위의 소스는 기존에 있던 CNN 소스화 시킨 내용이다.

하나하나 해석을 하면 784개의 변수를 가진 이미지를 28x28x1 reshape 시킨다.

그리고 정답은 0~9까지 10개이므로 Y 변수는 10으로 설정한다.

첫번째 Convolution에서 3,3,1,32 Filter, Stride 1, Padding ‘SAME’ 통과를 시킨다.

그러면 동일한 크기의 (필터를 거친) 이미지가 생성된다.(, 32개의 채널을 가진다.)

그리고 Relu함수를 사용한 다음, Max Pooling 통해, 2x2 크기의 stride 2, Padding ‘SAME’ 통과 시킨다.

Padding 2이나, Stride 2이므로, 이미지의 크기는 14x14x32 된다.

다음 똑같은 과정(w2) 거친다.

그런 다음, 일자로 정렬시키기 위해, reshape 다시 한번 한다. W2필터를 거친 이미지는 7x7x64 크기가 되므로, 해당 이미지를 reshape시키기 위해, 모든 것을 곱하여(7*7*64) reshape 해준다.

다음으로 이전에 배웠던 것과 비슷한 뉴럴 네트워크가 비슷한, Fully connected 연결해준다.

초기값과 학습방법은 이전에 배웠던 Xavier Initializer AdamOptimizer 사용한다.

다음 내용은 이전과 동일하므로 생략한다.

해당 소스를 돌리면, 다음과 같은 결과값이 나온다. 확실히 거의 99% 가깝게 정확도가 올라 가는걸 확인할 있다.

 

이번에는 조금 Deep 학습을 시켜보자.

import tensorflow as tf
import random

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(
"MNIST_data/", one_hot=True)

training_epoch =
15
training_batch = 100
learning_rate = 0.001
keep_prob = tf.placeholder(tf.float32)

X = tf.placeholder(tf.float32
, [None, 784])
X_img = tf.reshape(X
, [-1, 28, 28, 1])
Y = tf.placeholder(tf.float32
, [None, 10])

W1 = tf.Variable(tf.random_normal([
3, 3, 1, 32], stddev=0.01))

L1 = tf.nn.conv2d(X_img
, W1, 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.nn.dropout(L1
, keep_prob=keep_prob)

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')
L2 = tf.nn.dropout(L2
, keep_prob=keep_prob)

W3 = tf.Variable(tf.random_normal([
3, 3, 64, 128], stddev=0.01))

L3 = tf.nn.conv2d(L2
, W3, strides=[1, 1, 1, 1], padding='SAME')
L3 = tf.nn.relu(L3)
L3 = tf.nn.max_pool(L3
, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
L3 = tf.nn.dropout(L3
, keep_prob=keep_prob)

L3_flat = tf.reshape(L3
, [-1, 128 * 4 * 4])

W4 = tf.get_variable(
'W4', shape=[128 * 4 * 4, 625], initializer=tf.contrib.layers.xavier_initializer())
b4 = tf.Variable(tf.random_normal([
625]))
L4 = tf.nn.relu(tf.matmul(L3_flat
, W4) + b4)
L4 = tf.nn.dropout(L4
, keep_prob=keep_prob)

W5 = tf.get_variable(
'W5', shape=[625, 625], initializer=tf.contrib.layers.xavier_initializer())
b5 = tf.Variable(tf.random_normal([
625]))
L5 = tf.nn.relu(tf.matmul(L4
, W5) + b5)
L5 = tf.nn.dropout(L5
, keep_prob=keep_prob)

W6 = tf.get_variable(
'W6', shape=[625, 10], initializer=tf.contrib.layers.xavier_initializer())
b6 = tf.Variable(tf.random_normal([
10]))
logits = tf.matmul(L5
, W6) + b6

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=Y))
train = tf.train.AdamOptimizer(
learning_rate=learning_rate).minimize(cost)

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

for epoch in range(training_epoch):
    avg_cost =
0
   
total_batch = int(mnist.train.num_examples / training_batch)

   
for batch in range(total_batch):
        batch_xs
, batch_ys = mnist.train.next_batch(batch_size=training_batch)
        feed_dict = {X: batch_xs
, Y: batch_ys, keep_prob: 0.7}
        c_
, _ = sess.run([cost, train], 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(logits
, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction
, tf.float32))
print('Accuracy:', sess.run(accuracy, feed_dict={
      X: mnist.test.images
, Y: mnist.test.labels, keep_prob: 1}))

# Get one and predict
r = random.randint(0, mnist.test.num_examples - 1)
print("Label: ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))
print("Prediction: ", sess.run(
    tf.argmax(logits
, 1), feed_dict={X: mnist.test.images[r:r + 1], keep_prob: 1}))

위의 소스와 차이점은 overfitting 방지하기 위해, Dropout 사용한 부분과 그리고 조금 Deep하게 Convolution 하였고, Fully connected 했다는 말고는 차이점이 없다.

그러나 결과는 다음과 같다.

거의 100% 육박할 만큼 99% 정확도를 나타내고 있다.


Lab-3

이번 강의에서는

·       Python Class 이용하여 학습을 모델화 시키는 방법.

·       Layers API 사용하여 학습시키는 방법.

·       Ensemble 대해 배운다.

Ensemble 대해서 간략히 설명하자면, 학습을 시키는 모델을 여러 개를 학습을 시키는 방법이다. 그러면 그만큼 신뢰할 있는 모델이 만들어질 것이다.

 

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data

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

training_epoch =
15
training_batch = 100
learning_rate = 0.001


class Model:
   
def __init__(self, sess, name):
       
self.sess = sess
       
self.name = name
       
self._build()

   
def _build(self):
       
with tf.variable_scope(self.name):
            
self.keep_prob = tf.placeholder(tf.float32)

           
self.X = tf.placeholder(tf.float32, [None, 784])
            X_img = tf.reshape(
self.X, [-1, 28, 28, 1])
           
self.Y = tf.placeholder(tf.float32, [None, 10])

            W1 = tf.Variable(tf.random_normal([
3, 3, 1, 32], dtype=tf.float32))

            L1 = tf.nn.conv2d(X_img
, W1, 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.nn.dropout(L1
, keep_prob=self.keep_prob)

            W2 = tf.Variable(tf.random_normal([
3, 3, 32, 64], dtype=tf.float32))

            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')
            L2 = tf.nn.dropout(L2
, keep_prob=self.keep_prob)

            W3 = tf.Variable(tf.random_normal([
3, 3, 64, 128], dtype=tf.float32))

            L3 = tf.nn.conv2d(L2
, W3, strides=[1, 1, 1, 1], padding='SAME')
            L3 = tf.nn.relu(L3)
            L3 = tf.nn.max_pool(L3
, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
            L3 = tf.nn.dropout(L3
, keep_prob=self.keep_prob)

            L3_flat = tf.reshape(L3
, [-1, 4 * 4 * 128])

            W4 = tf.get_variable(
'W4', shape=[128 * 4 * 4, 625],
                                
initializer=tf.contrib.layers.xavier_initializer())
            b4 = tf.Variable(tf.random_normal([
625]))
            L4 = tf.nn.relu(tf.matmul(L3_flat
, W4) + b4)
            L4 = tf.nn.dropout(L4
, keep_prob=self.keep_prob)

            W5 = tf.get_variable(
'W5', [625, 625], initializer=tf.contrib.layers.xavier_initializer())
            b5 = tf.Variable(tf.random_normal([
625]))
            L5 = tf.nn.relu(tf.matmul(L4
, W5) + b5)
            L5 = tf.nn.dropout(L5
, keep_prob=self.keep_prob)

            W6 = tf.get_variable(
'W6', [625, 10], initializer=tf.contrib.layers.xavier_initializer())
            b6 = tf.Variable(tf.random_normal([
10]))
           
self.logits = tf.matmul(L5, W6) + b6

       
self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
           
logits=self.logits, labels=self.Y))
       
self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)

        correct_prediction = tf.equal(tf.argmax(
self.logits, 1), tf.argmax(self.Y, 1))
       
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

   
def predict(self, x_test, keep_prop=1.0):
       
return self.sess.run(self.logits, feed_dict={self.X: x_test, self.keep_prob: keep_prop})

   
def get_accuracy(self, x_test, y_test, keep_prob=1.0):
       
return self.sess.run(self.accuracy, feed_dict={self.X: x_test, self.Y: y_test, self.keep_prob: keep_prob})

   
def train(self, x_data, y_data, keep_prob=0.7):
       
return self.sess.run([self.cost, self.optimizer],
                            
feed_dict={self.X: x_data, self.Y: y_data, self.keep_prob: keep_prob})


sess = tf.Session()
m1 = Model(sess
, 'm1')

sess.run(tf.global_variables_initializer())

print('Learning Started!')

for epoch in range(training_epoch):
    avg_cost =
0
   
total_batch = int(mnist.train.num_examples / training_batch)

   
for batch in range(total_batch):
        batch_xs
, batch_ys = mnist.train.next_batch(training_batch)
        c
, _ = m1.train(batch_xs, batch_ys)
        avg_cost += c / total_batch

   
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

print('Learning Finished!')

print('Accuracy:', m1.get_accuracy(mnist.test.images, mnist.test.labels))

 

우선 Python Class 이용하여 Model 구성하여 학습을 시키는 소스이다. 기존의 내용과 다른 점은 없어 이해하는데 어려운 부분은 없을 꺼라 생각되어 생략하겠다.

 

다음은 Layers API 이용하여 소스를 구성해보자.

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data

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

training_epoch =
15
training_batch = 100
learning_rate = 0.001

keep_prob = 0.7


class Model:
   
def __init__(self, sess, name):
       
self.sess = sess
       
self.name = name
       
self._build()

   
def _build(self):
       
with tf.variable_scope(self.name):
           
self.training = tf.placeholder(tf.bool)

           
self.X = tf.placeholder(tf.float32, [None, 784])
            X_img = tf.reshape(
self.X, [-1, 28, 28, 1])
           
self.Y = tf.placeholder(tf.float32, [None, 10])

            conv1 = tf.layers.conv2d(
inputs=X_img, filters=32, kernel_size=[3, 3], padding='SAME',
                                    
activation=tf.nn.relu)
            pool1 = tf.layers.max_pooling2d(
inputs=conv1, pool_size=2, strides=2, padding='SAME')
            drop1 = tf.layers.dropout(
inputs=pool1, rate=keep_prob, training=self.training)

            conv2 = tf.layers.conv2d(
inputs=drop1, filters=64, kernel_size=[3, 3], padding='SAME',
                                    
activation=tf.nn.relu)
            pool2 = tf.layers.max_pooling2d(
inputs=conv2, pool_size=2, strides=2, padding='SAME')
            drop2 = tf.layers.dropout(
inputs=pool2, rate=keep_prob, training=self.training)

            conv3 = tf.layers.conv2d(
inputs=drop2, filters=128, kernel_size=[3, 3], padding='SAME',
                                    
activation=tf.nn.relu)
            pool3 = tf.layers.max_pooling2d(
inputs=conv3, pool_size=2, strides=2, padding='SAME')
            drop3 = tf.layers.dropout(
inputs=pool3, rate=keep_prob, training=self.training)

            flat = tf.reshape(drop3
, [-1, 128 * 4 * 4])

            dense4 = tf.layers.dense(
inputs=flat, units=128 * 4 * 4, activation=tf.nn.relu)
            drop4 = tf.layers.dropout(
inputs=dense4, rate=keep_prob, training=self.training)

           
self.logits = tf.layers.dense(inputs=drop4, units=10)

       
self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
           
logits=self.logits, labels=self.Y))
       
self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)

        correct_prediction = tf.equal(tf.argmax(
self.logits, 1), tf.argmax(self.Y, 1))
       
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

   
def predict(self, x_test, trainning=False):
       
return self.sess.run(self.logits,
                            
feed_dict={self.X: x_test, self.training: trainning})

   
def get_accuracy(self, x_test, y_test, trainning=False):
       
return self.sess.run(self.accuracy, feed_dict={self.X: x_test, self.Y: y_test,
                                                      
self.training: trainning})

   
def train(self, x_data, y_data, trainning=True):
       
return self.sess.run([self.cost, self.optimizer],
                            
feed_dict={self.X: x_data, self.Y: y_data, self.training: trainning})


sess = tf.Session()
m1 = Model(sess
, 'm1')

sess.run(tf.global_variables_initializer())

print('Learning Started!')

for epoch in range(training_epoch):
    avg_cost =
0
   
total_batch = int(mnist.train.num_examples / training_batch)

   
for batch in range(total_batch):
        batch_xs
, batch_ys = mnist.train.next_batch(training_batch)
        c
, _ = m1.train(batch_xs, batch_ys)
        avg_cost += c / total_batch

   
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

print('Learning Finished!')

print('Accuracy:', m1.get_accuracy(mnist.test.images, mnist.test.labels))

 

위의 내용에서 있듯이. 코드 수가 줄어드는 있다.

해당 Layers API 대한 설명은 https://www.tensorflow.org/api_docs/python/tf/layers 에서 자세히 나와있다.

 

마지막으로 Ensemble 대해 알아보자.

이전에 설명했듯이, 한번에 여러 개의 모델로 학습을 시켜 정확도를 높이는 방법이다.

위의 이미지와 같이 구성이 된다.


import tensorflow as tf
import numpy as np

from tensorflow.examples.tutorials.mnist import input_data

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

training_epoch =
15
training_batch = 100
learning_rate = 0.001

keep_prob = 0.7


class Model:
   
def __init__(self, sess, name):
       
self.sess = sess
       
self.name = name
       
self._build()

   
def _build(self):
       
with tf.variable_scope(self.name):
           
self.training = tf.placeholder(tf.bool)

           
self.X = tf.placeholder(tf.float32, [None, 784])
            X_img = tf.reshape(
self.X, [-1, 28, 28, 1])
            
self.Y = tf.placeholder(tf.float32, [None, 10])

            conv1 = tf.layers.conv2d(
inputs=X_img, filters=32, kernel_size=3, padding='SAME',
                                    
activation=tf.nn.relu)
            pool1 = tf.layers.max_pooling2d(
inputs=conv1, pool_size=2, strides=2, padding='SAME')
            drop1 = tf.layers.dropout(
inputs=pool1, rate=keep_prob, training=self.training)

            conv2 = tf.layers.conv2d(
inputs=drop1, filters=64, kernel_size=3, padding='SAME',
                                     
activation=tf.nn.relu)
            pool2 = tf.layers.max_pooling2d(
inputs=conv2, pool_size=2, strides=2, padding='SAME')
            drop2 = tf.layers.dropout(
inputs=pool2, rate=keep_prob, training=self.training)

            conv3 = tf.layers.conv2d(
inputs=drop2, filters=128, kernel_size=3, padding='SAME',
                                    
activation=tf.nn.relu)
            pool3 = tf.layers.max_pooling2d(
inputs=conv3, pool_size=2, strides=2, padding='SAME')
            drop3 = tf.layers.dropout(
inputs=pool3, rate=keep_prob, training=self.training)

            flat = tf.reshape(drop3
, [-1, 128 * 4 * 4])

            dense4 = tf.layers.dense(
inputs=flat, units=128 * 4 * 4, activation=tf.nn.relu)
            drop4 = tf.layers.dropout(
inputs=dense4, rate=keep_prob, training=self.training)

           
self.logits = tf.layers.dense(inputs=drop4, units=10)

       
self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
           
logits=self.logits, labels=self.Y))
       
self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)

        correct_prediction = tf.equal(tf.argmax(
self.logits, 1), tf.argmax(self.Y, 1))
       
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

   
def predict(self, x_test, trainning=False):
       
return self.sess.run(self.logits,
                            
feed_dict={self.X: x_test, self.training: trainning})

   
def get_accuracy(self, x_test, y_test, trainning=False):
        
return self.sess.run(self.accuracy, feed_dict={self.X: x_test, self.Y: y_test,
                                                      
self.training: trainning})

   
def train(self, x_data, y_data, trainning=True):
       
return self.sess.run([self.cost, self.optimizer],
                            
feed_dict={self.X: x_data, self.Y: y_data, self.training: trainning})


sess = tf.Session()

models = []
num_models =
2

for m in range(num_models):
    models.append(Model(sess
, 'model' + str(m)))

sess.run(tf.global_variables_initializer())

print('Learning Started!')

for epoch in range(training_epoch):
    avg_cost_list = np.zeros(
len(models))
    total_batch =
int(mnist.train.num_examples / training_batch)

   
for batch in range(total_batch):
        batch_xs
, batch_ys = mnist.train.next_batch(training_batch)

       
for idx, m in enumerate(models):
            c
, _ = m.train(batch_xs, batch_ys)
            avg_cost_list[idx] += c / total_batch

   
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

print('Learning Finished!')

test_size =
len(mnist.test.labels)
predictions = np.zeros(test_size *
10).reshape(test_size, 10)
for idx, m in enumerate(models):
   
print(idx, 'Accuracy:', m.get_accuracy(
        mnist.test.images
, mnist.test.labels))

    p = m.predict(mnist.test.images)
    predictions += p

ensemble_correct_prediction = tf.equal(tf.argmax(predictions
, 1), tf.argmax(mnist.test.labels, 1))
ensemble_accuracy = tf.reduce_mean(tf.cast(ensemble_correct_prediction
, tf.float32))

print('Ensemble accuracy: ', sess.run(ensemble_accuracy))

기존의 내용과 다른 없고, 마지막 부분만 조금 다르다.

우선 model 개수를 정하고, 배열에 담는다.

다음 각각의 모델을 순서대로 학습을 시킨다.

 

테스트(결과값) 데이터의 개수를 추출한 다음, Label 종류가 10개이므로, 10 곱해준다.

그리고 reshape 각각 테스트 데이터 형태를 (테스트크기, 10) 같은 형태로 변경해준다.

 

그리고 값들을 학습시킨 , 평균값을 낸다.

그리고 평균된 값을 기준으로, 최대값(argmax) 뽑으면 우리가 원하는 결과값이 나온다.



위의 설명을 이미지로 나타낸 모습이다.

 

'''
0 Accuracy: 0.9933
1 Accuracy: 0.9946
2 Accuracy: 0.9934
3 Accuracy: 0.9935
4 Accuracy: 0.9935
5 Accuracy: 0.9949
6 Accuracy: 0.9941

Ensemble accuracy: 0.9952
'''

다음은 Ensemble 사용한 , 결과값이다. 기존에도 정확도가 높아, 많은 수치의 변화는 없지만 확실히 증가된 것을 확인할 있고, 정확도가 높은 상태에서의 수치 증가는 비록 값이 작더라도, 엄청난 변화인 있다.


댓글
공지사항
최근에 올라온 글
링크
«   2024/05   »
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
글 보관함