본문으로 바로가기

최근 딥러닝 관련 학습이 남녀노소(^^) 자신의 전공분야를 떠나서 마구마구 인기를 끌고 있죠. 저도 꽤 예전부터 기초부터 익히려 했으나(ㅠㅠ) 그 놈의 게으름을 그냥 뜨문뜨문 공부했더니 정리가 잘 되지 않은 함정에 빠졌죠. 더구나 너무나 좋은 툴들이 범람하고, 그 너무나 좋은 툴들이 또 너무나 빠르게 버전 업로드가 이뤄지고 있어서, 이제는 그나마 간신히 이해한 것 조차 의미가 없어질까바 또 그것도 걱정인 참.. 황당한 시대에 살고 있습니다.^^. 지금까지는 텐서플로우를 이용해서 단층신경망으로 MNIST 필기 숫자를 인식하고[바로가기] accruracy가 한 90%쯤 나와서 좋아하다가^^, 다시 조금 더 깊은 신경망을 적용하고, 가중치를 초기화하는 부분을 Xavier 방법을 사용[바로가기] accuracy가 97.5%쯤 나와서 더~ 좋아했었죠^^ 여기까지는 텐서플로우를 사용했는데요. 갑자기 텐서플로우에서 케라스(KERAS)의 간결함에 빠져서-라고 쓰고, 공부하기 쉬워서^^ 다시 케라스로 타이타닉 생존자 분석[바로가기]을 했었죠^^

사실, MNIST와 같은 이미지 분석에는 Convolutional Neural Network를 사용한다는 것을 알고 있습니다만, 제가 블로그에 글을 쓰는 습관이 그러해서 미뤄두고 있었는데요. 오늘은 그걸 올릴려는 거죠^^. 그런데, Keras가 마음에 들어서, 텐서플로우로 잘 따라오다가, 오늘 CNN을 이용한, MNIST 손글씨 판독은 케라스로 수행하기로 했습니다.^^.

언제나 그랬지만, 오늘도 역시 Adventures in machine learning의 Keras tutorial[바로가기]에 나온 Keras 튜토리얼로 학습했습니다. 아주 일부의 내용을 수정하거나, 혹은 추가했습니다.

뭐 그렇다는 거죠^^ 오늘도 필요한 모듈을

import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)

import sys
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
import numpy as np
np.random.seed(7)

print('Python version : ', sys.version)
print('TensorFlow version : ', tf.__version__)
print('Keras version : ', keras.__version__)

import하구요~

저는 얼마전부터 텐서플로우는 1.5.0에서 멈췄고, keras는 2.1.5에서 멈춰있습니다.^^

img_rows = 28
img_cols = 28

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

input_shape = (img_rows, img_cols, 1)
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

batch_size = 128
num_classes = 10
epochs = 12

y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

그리고, keras에서 제공하는 MNIST데이터를 받고, 사용할 수 있게 train과 test 데이터를 만들어 줍니다.

이제 중요한 CNN의 구조인데요.

출처 : Adventures in machine learning

처음에 언급한, Adventures machine learning에서 제공하는 Keras tutorial에서 제시한 구조를 학습할 겁니다. 정말 keras가 마음에 드는 것은, 위 구조와 

model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), strides=(1, 1), padding='same',
                 activation='relu',
                 input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, (2, 2), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(1000, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.summary()

이 코드가 너무 쉽게 눈에 들어온다는 거죠^^

넵.. 입출력 관계와 층구조를 바로 알 수 있지만~~~ 극도로 이쁜걸 좋아하다보니...

from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
%matplotlib inline

SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

이 코드로 다시 보면...

이렇네요^^

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
hist = model.fit(x_train, y_train,
                 batch_size=batch_size,
                 epochs=epochs,
                 verbose=1, 
                 validation_data=(x_test, y_test))

그리고, 그저 이렇게.. fit~을 시작합니다. 킁..

에휴..  한 epoch하는데 1분이라늬ㅠㅠ. 저의 맥북은 비록 2015 mid이지만 그래도 2.2GHz의 Core i7인데.. 이딴것 보다.. GPU가 필요한가봅니다.ㅠㅠ. 이제 조만간... 어마어마한 음성 데이터를 만져야하는 운명에 점점 다가가는데... 장비의 사양이 몹시 걱정이지요^^

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

여하튼 test 데이터에 대한 accuracy는 

99.34%입니다. 이 정도면.. 테스트 데이터 10000개 중에서 66개만 틀렸다는 거죠^^ 그냥 수작업으로 결과를 확인하고 싶다면...

n = 0
plt.imshow(x_test[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
plt.show()

print('The Answer is ', model.predict_classes(x_test[n].reshape((1, 28, 28, 1))))

정도의 코드면

요런 결과를 얻을 수 있겠습니다.^^ 그러나 66개 데이터에 대해 랜덤하게 한 16개 정도 팍팍 틀린아이들을 확인하고 싶다면...

import random

predicted_result = model.predict(x_test)
predicted_labels = np.argmax(predicted_result, axis=1)

test_labels = np.argmax(y_test, axis=1)

wrong_result = []

for n in range(0, len(test_labels)):
    if predicted_labels[n] != test_labels[n]:
        wrong_result.append(n)

samples = random.choices(population=wrong_result, k=16)

count = 0
nrows = ncols = 4

plt.figure(figsize=(12,8))

for n in samples:
    count += 1
    plt.subplot(nrows, ncols, count)
    plt.imshow(x_test[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
    tmp = "Label:" + str(test_labels[n]) + ", Prediction:" + str(predicted_labels[n])
    plt.title(tmp)

plt.tight_layout()
plt.show()

이런 코드면 괜찮지 않을까 합니다.

흠.. 저정도라면 저도 못 맞출것 같은 아이도 있네요. 뭐 아무튼.. 오늘은 케라스로 CNN을 투토리얼 해 보았습니다.~~~~~~^^


댓글을 달아 주세요

  1. BlogIcon 요니피그 2018.04.16 08:11 신고

    핑크윙크님은 진짜 천재이심요!!!전 아무리봐도 모르겠는데 어떻게 요런 어려운 걸 척척 해나가시는지 대단하심돠 존경함

    • BlogIcon PinkWink 2018.04.16 18:45 신고

      에이.. 정말 그러고 싶어요 ㅎㅎㅎ
      그러나 현실은 간단한 예제도 못돌려서 삽질을 엄청하는 캐릭터입니다.ㅠㅠ.
      아무튼 감사합니다.^^

  2. BlogIcon 드래곤포토 2018.04.16 08:18 신고

    활기찬 월요일 되세요 ^^

  3. BlogIcon 휴식같은 친구 2018.04.16 11:32 신고

    신기한데요.
    간단한 코딩으로 필기를 인식하니 말입니다.
    ㅎ잘 보고 갑니다.

  4. BlogIcon 북두협객 2018.04.16 13:41 신고

    20년전에 C언어 배웠는데 당시 너무 재밌게 배웠던 것 같아요

    분야 살리지 못하고 다른일 하고 있지만요

  5. BlogIcon 보미 2018.04.16 14:25 신고

    정말 텐서플로우는 어려워요~

  6. BlogIcon IT넘버원 2018.04.16 18:15 신고

    저도 보기 어려운 문자가 있는거 같아요.ㅎㅎㅎ

  7. BlogIcon 스티마 2018.04.16 23:35 신고

    PinkWink님 예제만 따라해도 머신러닝 할 수 있을 것 같아요!

  8. BlogIcon luvholic 2018.04.17 00:19 신고

    딥러닝으로 글씨쓰기인가봐요~~
    너무너무 신기하네요!!!!!

  9. BlogIcon peterjun 2018.04.17 01:04 신고

    딥러닝 분야의 발전이 정말 빠른가봐요...
    그 속에서 이렇게 배우고, 이런저런 걸 해보시는 게 정말 멋집니다. ㅎㅎ

  10. BlogIcon 시골청년v 2018.04.17 01:22 신고

    뭔가 어렵네요 ㅋㅋ

  11. BlogIcon 핑구야 날자 2018.04.17 06:35 신고

    글자 인식이 정말 재미있가도 하겠지만 어려울 거 같아요

  12. BlogIcon 공수래공수거 2018.04.17 07:32 신고

    요즘 코딩을 초등학생때부터 배우는 모양이더군요
    신기합니다 ㅎ
    기분좋은 하루 되세요^^

  13. BlogIcon Bliss :) 2018.04.17 08:03 신고

    전에 MNIST 숫자 판독하신 것과 조금 다른 코드인가봐요? 매번 신기합니다!! 행복한 한 주 되세요^^

  14. BlogIcon Deborah 2018.04.17 13:15 신고

    멋진 팁인데 잘 활용을 해야 하는데 아직도 헤메이고 있네요.

  15. BlogIcon 잉여토기 2018.04.17 16:18 신고

    프로그램을 직접 만드시는군요.
    와, 프로그램 문외한에게는 정말 어렵네요~
    화요일도 파이팅입니다.

  16. BlogIcon 즐거운 우리집 2018.04.18 07:52 신고

    맞아요 ㅋ
    저 정도라면 제 눈도...ㅎㅎㅎ

  17. dg 2018.06.07 14:38 신고

    안녕하세요~ 작성글들 잘 보았습니다.
    혹시 위의 코드를 활용하여 MNIST 데이터셋 대신 제가 이미지에 라벨링을 하여 데이터셋을 만드는 법에 대한 강의글 올려주실 수 있으신가요~??

  18. 배우는중 2018.08.02 15:58 신고

    samples = random.choices(population=wrong_result, k=16)

    이 부분에서 random.py에서 choices reference를 찾지 못 한다고 나오는데 어떻게 해야하나요...?