본문 바로가기
ML, DL, RL

[DL] Image Classification using CNN with CIFAR-10 Dataset on Keras

by llHoYall 2020. 11. 15.

이미지 분류에 주로 사용되는 CNN의 기본 개념을 이해하고 CIFAR-10 데이터세트에 적용을 해보겠습니다.

CIFAR-10도 유명한 데이터세트이죠.

10 종류의 이미지와 정답 레이블이 들어있습니다.

즉, 우리의 목표는 CNN을 통해 이 10가지 종류의 이미지들을 적절하게 분류해 내는 것입니다.

 

부족한 설명은 이전 포스팅을 참고하시면 도움이 될 겁니다.

2020/11/10 - [DeepLearning] - Classifying Handwriting with Keras

2020/11/14 - [DeepLearning] - Regression about Boston House Prices with Keras

Input Dataset

Getting Dataset

케라스에 이미 들어있기 때문에 손쉽게 가져올 수 있습니다.

from keras.datasets import cifar10

(train_images, train_labels), (test_images, test_labels) = cifar10.load_data()

Analyzing Dataset

가져온 데이터세트를 살펴보겠습니다.

print(train_images.shape, train_labels.shape)
# (50000, 32, 32, 3) (50000, 1)

print(test_images.shape, test_labels.shape)
# (10000, 32, 32, 3) (10000, 1)

32 x 32 크기의 RGB 채널로 구성된 이미지가 각각 학습용 5만개, 테스트용 1만개가 들어있네요.

import matplotlib.pyplot as plt
%matplotlib inline

for i in range(5):
    plt.subplot(2, 5, i + 1)
    plt.imshow(train_images[i])
    print(train_labels[i], end=", ")
plt.show()

개구리, 트럭, 사슴, 자동차가 보이는 군요... 레이블은 0~9까지의 숫자로 되어있나보네요.

Preprocessing Dataset

이미지의 RGB 채널은 각각 0~255까지의 값을 갖고 있습니다.

이를 0~1 사이의 값을 갖도록 normalization을 해주도록 합니다.

레이블도 원-핫 인코딩으로 변환을 해줍니다.

from keras.utils import to_categorical

train_images = train_images.astype('float32') / 255.0
test_images = test_images.astype('float32') / 255.0

train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)

Model

Generating Model

from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Dropout, Flatten, Dense

model = Sequential()

# Convolutional Block (Conv-Conv-Pool-Dropout)
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# Convolutional Block (Conv-Conv-Pool-Dropout)
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# Classifying
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

3개의 블럭을 층층이 쌓아올리고, 각 블럭 내부에서도 마찬가지로 층층히 쌓아올려 꽤나 복잡한 모델을 만들었습니다.

Convolution Layer

이 레이어에서는 입력 데이터의 주요 특징을 추출해내는 역할을 합니다.

예를 들어 왼쪽과 같은 입력 데이터가 주어졌고, 가운데와 같은 필터(Filter)가 있다고 할 때, 이를 convolution을 하면,

오른쪽과 같은 결과가 됩니다.

 

필터는 커널(Kernel)이라고도 하고, 가중치 배열이라고도 하며 학습을 한다는 것은 이 값을 조정하는 것을 의미합니다.

위의 예에서 사용한 커널의 크기는 3x3이 되죠. 즉, 학습해야할 가중치가 9개 있는 것이죠.

커널을 이동시키는 거리를 스트라이드(stride)라고 합니다. 특별한 언급이 없다면 이는 1로 가정합니다.

 

Convolution을 하게되면 입력 데이터의 크기가 줄어들게 됩니다.

따라서 이를 여러번 수행할 경우, 주변에 값이 0인 셀들을 추가해서 입력 데이터의 크기를 유지시키기도 합니다.

Pooling Layer

이 레이어는 입력 데이터의 국소적인 회전이나 평행이동 등의 영향에 강해지는 효과가 있습니다.

Convolution 레이어의 출력을 압축하는 효과도 있습니다.

보통 최대값을 이용하거나, 평균값을 이용합니다.

위의 예에 이어서 적용하면 요렇게 됩니다.

Compiling Model

from keras.optimizers import Adam

model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001), metrics=['acc'])

손실 함수로는 분류에 적합한 categorical_crossentropy를 사용하였고, 최적화 함수로는 학습률 0.001의 Adam 함수를 사용했습니다.

평가지표로는 정확도를 사용했고요.

Training

자~ 이제 학습을 시킬 시간입니다. ^^

history = model.fit(train_images, train_labels, batch_size=128, epochs=20, validation_split=0.1)

 

파라미터들은 이전에 다 설명을 했던 내용들이네요.

 

CNN은 학습에 소요되는 시간이 상당합니다. GPU를 사용하거나 빵빵한 성능의 CPU를 사용하는 것을 추천드립니다.

저도 Google Colab에서 처음으로 GPU를 사용했네요.

이렇게 오래 걸리는데 매번 다시 학습을 시키려면 고통스럽겠죠?

모델을 저장하고, 저장한 모델을 불러오는 방법을 배울 차례네요.

from keras.models import load_model

model.save('CNN_CIFAR10.h5')
model = load_model('CNN_CIFAR10.h5')

 

간단하게, save 메소드와 load_model 메소드를 사용하면 됩니다. ^^

 

그럼 학습결과를 한 번 살펴보겠습니다.

plt.plot(history.history['acc'], label='acc')
plt.plot(history.history['val_acc'], label='val_acc')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(loc='best')
plt.show()

대략 10epochs 이후로는 학습 효과가 미비하네요. ㅎㅎ

Evaluation

test_loss, test_acc = model.evaluate(test_images, test_labels)
# 313/313 [==============================] - 1s 3ms/step - loss: 0.6763 - acc: 0.7890

테스트 데이터로 평가를 해봐도 검증용 데이터로 평가한 것과 비슷한 수준의 정확도를 보이고 있네요.

Prediction

자 모델에 직접 데이터를 넣어서 확인을 해볼까요?

5개 중에 4개를 맞췄으니 대략 80% 정도 정확도를 보이네요.

 

이제 이 모델을 개선해서 정확도를 늘려보세요. ^^

댓글