레플리
글 수 203

텐서플로우에서 딥러닝 CNN으로 숫자 인식 구현

조회 수 5010 추천 수 0 2017.03.11 12:20:03


http://bcho.tistory.com/1156

 

 

 

지난번에는 MNIST 숫자 이미지 데이터를 소프트맥스로만 학습을 하였습니다. 이번에는 딥러닝의 합성곱 신경망(Convolutional  Neural Network)으로 구현해보겠습니다. CNN에 대한 자세한 설명은 아래 링크를 참조하세요.

 

http://aidev.co.kr/deeplearning/782

 

 

 

Screen_Shot_2017-01-09_at_2.05.42_PM.png

 

CNN의 위의 그림과 같이 합성곱 레이어와 완전연결 레이어로 구성되어 있습니다. 합성곱 레이어의 역할은 다음과 같습니다.

 

Convolutional filter

-> 입력을 필터와 합성곱하여 특징을 추출하고 Feature Map을 생성

 

ReLu

-> 활성함수로 기존 신경망에서 사용하던 시그모이드 대신 사용

 

MaxPool

-> 피처맵의 크기를 줄임

 

 

 

완전연결 레이어는 합성곱 레이어에서 특징들을 뽑아낸 피처맵을 입력으로 하여 기존 다층 신경망과 동일한 방법으로 학습을 합니다. 이렇게 저수준의 특징에서 반복적으로 고수준의 특징을 만들면 복잡한 데이터도 쉽게 학습이 됩니다.

 

CNN의 가장 큰 특징은 필터를 자동으로 학습하여 생성한다는 것입니다. 다만 필터의 개수와 합성곱 레이어를 어떻게 배치할 것인가는 데이터에 맞게 직접 조정해야 합니다.

 

이전 소프트맥스만 사용하여 학습할때는 정확도가 90%정도였습니다. 하지만 CNN으로 동일한 학습을 했을때 정확도가 97%로 높이 향상되었습니다.

 

 

 

텐서플로우 소스코드는 아래와 같습니다.

 

---------------------------------------------------------------------------

import tensorflow as tf

import numpy as np

from tensorflow.examples.tutorials.mnist import input_data

 

 

#-----------------------------

# 초기화

#-----------------------------

 

# 그래프 변수값들을 초기화

tf.reset_default_graph() 

 

# 랜덤 초기화

np.random.seed(20160704)

tf.set_random_seed(20160704)

 

# 숫자 이미지 데이터 로드

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

 

 

 

#-----------------------------

# 첫번째 레이어 정의

#-----------------------------

 

# 첫번째 레이어 필터 개수

num_filters1 = 32

 

# 입력값 플레이스홀더 설정

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

 

# 1차원 배열인 입력을 28x28 행렬로 변환

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

 

# 가중치 변수 설정

W_conv1 = tf.Variable(tf.truncated_normal([5,5,1,num_filters1], stddev=0.1))

 

# 합성곱 가설 설정

h_conv1 = tf.nn.conv2d(x_image, W_conv1, strides=[1,1,1,1], padding='SAME')

 

# 편향값 변수 설정

b_conv1 = tf.Variable(tf.constant(0.1, shape=[num_filters1]))

 

# ReLU 활성함수 설정

h_conv1_cutoff = tf.nn.relu(h_conv1 + b_conv1)

 

# 풀링 설정

h_pool1 = tf.nn.max_pool(h_conv1_cutoff, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

 

 

 

#-----------------------------

# 두번째 레이어 정의

#-----------------------------

 

# 두번째 레이어 필터 개수

num_filters2 = 64

 

# 가중치 변수 설정

W_conv2 = tf.Variable(tf.truncated_normal([5,5,num_filters1,num_filters2], stddev=0.1))

 

# 합성곱 가설 설정

h_conv2 = tf.nn.conv2d(h_pool1, W_conv2, strides=[1,1,1,1], padding='SAME')

 

# 편향값 변수 설정

b_conv2 = tf.Variable(tf.constant(0.1, shape=[num_filters2]))

 

# ReLU 활성함수 설정

h_conv2_cutoff = tf.nn.relu(h_conv2 + b_conv2)

 

# 풀링 설정

h_pool2 = tf.nn.max_pool(h_conv2_cutoff, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

 

 

 

#-----------------------------

# 완전연결 레이어 정의

#-----------------------------

 

# 두번째 레이어의 출력을 1차원 배열로 변경

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*num_filters2])

 

# 입력 노드의 개수

num_units1 = 7*7*num_filters2

 

# 히든 노드의 개수

num_units2 = 1024

 

# 가중치 변수 설정

w2 = tf.Variable(tf.truncated_normal([num_units1, num_units2]))

 

# 편향값 변수 설정

b2 = tf.Variable(tf.constant(0.1, shape=[num_units2]))

 

# 입력과 가중치를 곱하여 행렬 계산

hidden2 = tf.nn.relu(tf.matmul(h_pool2_flat, w2) + b2)

 

# 드롭아웃 확률 플레이스홀더 설정

keep_prob = tf.placeholder(tf.float32)

 

# 드롭아웃 설정

hidden2_drop = tf.nn.dropout(hidden2, keep_prob)

 

# 드롭아웃 가중치 변수 설정

w0 = tf.Variable(tf.zeros([num_units2, 10]))

 

# 드롭아웃 편향값 설정

b0 = tf.Variable(tf.zeros([10]))

 

# 드롭아웃 가중치 행렬 계산

k = tf.matmul(hidden2_drop, w0) + b0

 

# 최종적으로 소프트맥스를 사용하여 결과값 출력

p = tf.nn.softmax(k)

 

 

 

#-----------------------------

# 학습 설정

#-----------------------------

 

# 이미지 입력의 실제 결과 레이블(0~9 숫자를 대표) 플레이스홀더 설정

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

 

# 소프트맥스 크로스 엔트로피로 출력값과 실제값의 차이 계산

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(k,t))

 

# 경사하강법 대신 AdamOptimizer로 loss가 낮게 되도록 훈련 설정

train_step = tf.train.AdamOptimizer(0.0001).minimize(loss)

 

# 정확도 계산

correct_prediction = tf.equal(tf.argmax(p, 1), tf.argmax(t, 1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

 

 

 

#-----------------------------

# 학습 수행

#-----------------------------

 

# 세션 초기화

sess = tf.InteractiveSession()

sess.run(tf.global_variables_initializer())

 

# 50개씩 데이터를 랜덤추출해 1000번 학습 반복

i = 0

for _ in range(1000):

    i += 1

    batch_xs, batch_ts = mnist.train.next_batch(50)

    sess.run(train_step, feed_dict={x:batch_xs, t:batch_ts, keep_prob:0.5})

 

    # 100번 마다 정확도 출력

    if i % 100 == 0:

        loss_vals, acc_vals = [], []

 

        for c in range(4):

            start = len(mnist.test.labels) / 4 * c

            end = len(mnist.test.labels) / 4 * (c+1)

 

            loss_val, acc_val = sess.run([loss, accuracy],

                feed_dict={x:mnist.test.images[start:end],

                           t:mnist.test.labels[start:end],

                           keep_prob:1.0})

 

            loss_vals.append(loss_val)

            acc_vals.append(acc_val)

 

        loss_val = np.sum(loss_vals)

        acc_val = np.mean(acc_vals)

        print ('Step: %d, Loss: %f, Accuracy: %f' % (i, loss_val, acc_val))

 

# 세션 종료

sess.close()

---------------------------------------------------------------------------

 

 

 

< 인공지능 개발자 모임 >

- 페이스북 그룹에 가입하시면 인공지능에 대한 최신 정보를 쉽게 받으실 수 있습니다.

https://www.facebook.com/groups/AIDevKr/

 

List of Articles
제목 글쓴이 날짜 조회 수
Selfie, 비지도학습 이미지 사전훈련 모델 file 깊은바다 2019-06-15 3522
목소리와 입모양을 변경할 수 있는 GAN 모델 깊은바다 2019-06-13 1382
딥러닝의 미래는 바로 비지도학습 깊은바다 2019-06-06 6368
YOLO, Object Detection Network - 알고리즘 설명 file 깊은바다 2019-06-02 25052
사진 한 장으로 GAN 영상 생성 깊은바다 2019-05-23 1966
객체 검출 딥러닝 모델인 YOLO의 테드 영상 깊은바다 2019-05-22 2819
스냅챕의 성별 변환 필터는 GAN을 사용했을까 깊은바다 2019-05-15 685
신경망에 활성화 함수가 필요한 이유 file 깊은바다 2019-05-14 23723
핸즈온 머신러닝 2판 영문 초고 다운로드 깊은바다 2019-05-12 2362
GTA5로 자율주행 구현 영상 깊은바다 2019-05-08 1992
전신 사진을 생성하는 GAN 깊은바다 2019-05-05 832
인공신경망 학습 레시피 - 안드레이 카파시의 딥러닝 실전 노하우 깊은바다 2019-04-27 1052
MS의 챗봇 린나, 딥러닝으로 노래를 부르는 가수로 데뷔 깊은바다 2019-04-10 561
10분안에 배우는 머신러닝 - GAN 알고리즘 원리와 응용분야 깊은바다 2019-04-01 1131
구글 텐서플로우 첫걸음 - Tensorflow2.0 소개 [1] 깊은바다 2019-03-27 4561