레플리
글 수 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
제목 글쓴이 날짜 조회 수sort
전신 사진을 생성하는 GAN 깊은바다 2019-05-05 832
알렉스넷과 Seq2Seq의 창시자 일리야 수츠케버(Ilya Sutskever) 깊은바다 2020-11-17 831
당근마켓에서 딥러닝 활용하기 - 불량 게시물 검사 깊은바다 2017-12-23 821
자동회귀(autoregressive)로 이미지를 생성하는 iGPT file 깊은바다 2020-06-18 821
AutoML-Zero, 진화적 알고리즘을 사용하여 신경망 구조 설계 [2] 깊은바다 2020-03-13 820
사진을 텍스트로 설명 - CaptionBot file 깊은바다 2016-04-07 794
딥러닝 이론에서 텐서플로 실습까지 [2] 깊은바다 2017-11-08 786
Stable Diffusion을 사용한 사진 변환 앱 Lensa AI, 앱스토어 1위 달성 깊은바다 2022-12-09 786
스케치와 색을 지정하여 셀카를 편집하는 SC-FEGAN 깊은바다 2019-02-22 771
딥러닝이 작동하는 원리는? 깊은바다 2019-11-17 770
미드저니로 생성한 90년대 중국 사진들 - 콘텐츠 산업의 혁신 file 깊은바다 2023-03-30 770
딥러닝 역사 깊은바다 2018-07-10 749
Semantic Segmentation을 활용한 차량 파손 탐지 딥러닝 모델 개발기 깊은바다 2020-02-14 734
얀 르쿤, 자기지도학습이 강화학습보다 중요 깊은바다 2020-05-03 730
순차적으로 여러가지 일을 동시에 배우는 신경망 깊은바다 2017-03-16 729