brunch

You can make anything
by writing

C.S.Lewis

by 유윤식 Sep 16. 2018

Python: m.l with Keras #2

# CNN, # CIFAR10, # CIFAR100, # MinMaxSC

소프트웨어 엔지니어.

나는 개발자들이 잘 만들어 놓은 툴, 함수, 구조를 잘 이해하고 서비스 계층에서 사용 할 수 있도록

새로운 툴과 함수를 만들어 낸다.


머신러닝을 말하는데 왜 궅이 이렇게 서론이 길까? 하는 의문에 대한 답이다.

케라스(Keras)가 바로 그러한 소프트웨어 엔지니어의 성격을 가진다.

이를 이용해서 머신러닝을 하려고 한다면

이와 맞는 마음가짐과 지향점을 함께 가져야 한다.


나는 케라스를 통해서 이미 많은 예제에도 나와있는 CIFAR10 이미지 분류 예제를 포스팅 하려고 한다.

CNN은 솔직히 이미지 분류에서밖에 사용해 보지 못했다.


CNN?

Concolution neural network...


파이썬 3.5를 사용하며,

GPU NVIDIA GEFORCE 1080 8G 를 사용하며,

Jupyter 환경에서 진행했다.


CNN을 간단하게 설명하자면,

이미지를 보고, 특징점을 찾고, 그 특징점을 모아서 이미를 추론하는 방식을 취한다.


많은 튜토리얼, 공식 케라스 문서 등에서 그림과 함께 잘 성명해주고 있다.


자~!

그럼 이제 이미지 분류를 CNN을 통해 학습하고,

학습한 결과를 확인하고, 저장하고,

이미지화 하고,

결론도 확인하자.


1. 필요한 Library 를 가져오자.


from __future__ import print_function

import keras

from keras.datasets import cifar10

from keras.preprocessing.image import ImageDataGenerator

from keras.models import Sequential

from keras.layers import Dense, Dropout, Activation, Flatten

from keras.layers import Conv2D, MaxPooling2D

from keras.optimizers import SGD

from sklearn.preprocessing import MinMaxScaler

from sklearn import model_selection, metrics

import matplotlib.pyplot as plt

import numpy as np

import pandas  as pd

from sklearn.metrics import classification_report, confusion_matrix

import seaborn as sbn

import os


요정도?


데이터를 가져오고, 직접 어떻게 생긴건지 확인을 좀 해보고 싶다?


(x_train, y_train), (x_test, y_test) = cifar10.load_data()

class_names = ['airplane','automobile','bird','cat','deer', 'dog','frog','horse','ship','truck']

fig = plt.figure(figsize=(8,3))

for i in range(10):

    ax = fig.add_subplot(2, 5, 1 + i, xticks=[], yticks=[])

    idx = np.where(y_train[:]==i)[0]

    features_idx = x_train[idx,::]

    img_num = np.random.randint(features_idx.shape[0])

    im = features_idx[img_num,::]

    ax.set_title(class_names[i])

    plt.imshow(im)



요렇게?


슬쩍 결론의 답도 섞어 보자면,

데이터의 Dimention 을 자유자재로 가지고 놀 수 있는 부분이 머신러닝의 꽃이라고 생각한다.(개인적)

만약 Theano 를 Backend 로 사용한다면,

channel 설정이 다르기 때문에 이미지의 Dimention 을 수정해 주어야 한다.


그림으로도 보았다면!


데이터 정규화! 요게 또 중요한데

요걸 안하면... 솔직히 머신러닝 자체가 의미가 없을 정도이다.


이미지 데이터, 결과 데이터 순으로 정규화를 진행한다.


x_train = x_train.astype('float32')

x_test = x_test.astype('float32')


scaler = MinMaxScaler()

# 이걸 써도 괜찮고, 여러가지 데이터 정규화 방법이 있지만 가장 간단한 것은, 255.0 으로 나누는 것.


X_train = scaler.fit_transform(x_train.reshape(x_train.shape[0], -1)).reshape(x_train.shape)

X_test = scaler.transform(x_test.reshape(x_test.shape[0], -1)).reshape(x_test.shape)


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

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


이건 좀 가벼웠다.


함수형 구조 설계이므로 그냥 쭉쭉 밑으로 써내려가면 된다.

클래스를 만들고 객체지향을 지향하느니 마느니 그런 말은 하지 말고

입맛에 맞게 알아서! 원하는 방향으로!


이번엔 모델을 만들껀데.

모델은 웬만하면 이쁘고 멋있게.


 


model = Sequential()

model.add(Conv2D(32, (3, 3), padding='same', input_shape=X_train.shape[1:])) # 32, 32, 3

model.add(Activation('relu'))

model.add(Conv2D(32, (3, 3)))

model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Dropout(0.2))


model.add(Conv2D(64, (3, 3), padding='same'))

model.add(Activation('relu'))

model.add(Conv2D(64, (3, 3)))

model.add(Activation('relu'))

model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Dropout(0.2))


# model.add(Conv2D(128, (3, 3), padding='same'))

# model.add(Activation('relu'))

# model.add(Conv2D(128, (3, 3)))

# model.add(Activation('relu'))

# model.add(MaxPooling2D(pool_size=(2, 2)))

# model.add(Dropout(0.2))


model.add(Flatten())

model.add(Dense(512))

model.add(Activation('relu'))

model.add(Dropout(0.5))


model.add(Dense(num_classes))

model.add(Activation('softmax'))


이건 좀 설명이 불편한데, 그 이유는 100% 정답은 없기때문에...

최적화된 모델 설계를 따라가는 것도 하나의 방법이다.


중간 중간의 모델은 인터넷에서 열심히 뒤져보시고

처음과 마지막에 주목!

input_shape 를 이미지 채널 형태에 맞게 주어야 한다.

지금 이지미의 형태와 Tensorflow 를 Backend 로 사용하고 있다면

32, 32, 3 의 형태가 맞다.

그리고,

마지막 output은 10개의 이미지를 분류하는데 사용 할 것이므로, 10이 맞다.

이건 y_train 의 형태에서 1번째 인덱스의 값을 가져올 수 있다.


이어서 바로! 컴파일 해준다.


model.compile(loss='categorical_crossentropy',

              optimizer='sgd',

              metrics=['accuracy'])


사실 여기가 진짜 나에게는 BlackBox 이다.

Acc 정보도 나중에 볼 수 있도록 metrics 에 추가한다.

default 는 loss 만 준다.


이제 학습을 할 것이다.

시간이 좀 걸릴 수 있다.



history = model.fit(X_train, 

                    y_train, 

                    batch_size=batch_size, 

                    epochs=epochs, 

                    validation_data=(X_test,y_test),

                    shuffle=False)



끝났는가?

인내심도 함께 배울 수 있기를...

잘 진행되고 있는가?

대략 이런 로그들이 보일 것이다.



CNN을 통한 이미지 분류 머신러닝의 첫 발을 내딛었다.

사실 앞으로 해야 할 것들이 더 많다.


마지막으로 간단하게 결과(history) 화면을 보면,


막 이렇게 생겼다.


여기서 머신러닝에서 개인적으로 중요하게 여기는 부분을 답하라면

자신있게


"데이터를 바라보는 눈과 데이터의 형태를 올바르게 인식하고 있다."

"또한 그에 맞는 정확한 모델의 예를 찾고 응용할 수 있다."


다음에는 RNN, LSTM 을 이용하고 활용하는 부분에 대해서 포스팅 하려고 한다.

작가의 이전글 Python: m.l with Keras #1
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari