Keras Fashion Mnist 실습

devseunggwan·2020년 6월 26일
0

시작하며

우연한 기회로 회사를 이직할 기회를 얻었고, 이직한 회사에선 인공지능 파트를 담당하게 되었습니다. 대략 9개월정도 인공지능 공부를 하지 않은 상태에서 다시금 복습하자는 의미에서 이번 글을 포스팅하게 되었습니다.

이번 글은 케라스(Keras)에 대한 간단한 설명과 케라스를 사용한 예제(Fashion Mnist)를 하는 과정을 소개할 예정입니다.

케라스(Keras) 란

케라스 다큐먼트(Link)에 의하면 케라스는 파이썬으로 작성된 고수준의 신경망 APITensorflow, CNTK, Theano와 함께 사용할 수 있다고 적혀있습니다. 텐서플로(2.2.0 기준) 내에서 케라스를 import 할 수 있으며, 기존 개발된 신경망 및 기법들이 API로 제공되어 사용이 용이하기 때문에 빠른 개발을 할 수 있습니다.

캐글에 게재되어 있는 Deep Learning Framework Power Scores(Link)에선 Online Job Listings, Google Search Volume, Medium Articles, Amazon Books, ArXiv Articles 등으로 딥러닝 프레임워크의 점수를 매겨났습니다. 그 중에서 케라스는 2위를 차지하는 모습을 보여주고 있습니다. 텐서플로 다음으로 딥러닝 프레임워크 생태계가 활발한 것으로 볼 수 있습니다.

케라스를 활용한 예제를 통해서 사용 방법을 알아보도록 하겠습니다.

예제: Fashion Mnist

Fashion Mnist는 옷, 바지 등 10가지 종류의 의류로 구성된 데이터입니다. 이 데이터는 (28, 28) 크기로 구성되어 있으며 Training Set 5만장, Test Set 1만장으로 총합 6만장으로 이루어져 있습니다. Keras에서 dataset을 import 할 수 있고, 처음 import 시 다운로드 하는 과정이 추가됩니다.

1. 라이브러리 Import

데이터 분석 및 딥러닝에 사용될 라이브러리를 import 합니다.

from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout

from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import seaborn as sns

import pandas as pd
import numpy as np

2. 데이터 확인

Fashion Mnist 를 불러옵니다.

(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

데이터 포멧을 확인합니다.

print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(60000, 28, 28)
(60000,)
(10000, 28, 28)
(10000,)

레이블 이름을 튜플로 저장합니다.

item = {
      0: 'T-shirt/top'
    , 1: 'Trouser'
    , 2: 'Pullover'
    , 3: 'Dress'
    , 4: 'Coat'
    , 5: 'Sandal'
    , 6: 'Shirt'
    , 7: 'Sneaker'
    , 8: 'Bag'
    , 9: 'Ankle boot'
}

3. EDA(Exploratory Data Analysis)

Fashion Mnist 데이터에 대한 분석을 진행합니다. 직관적인 분석을 위해 데이터를 그래프로 그려줍니다.

레이블 카운팅

레이블 별로 데이터가 모두 존재하는 지 확인합니다.

plt.figure(figsize=(10, 3))

plt.subplot(1, 2, 1)
sns.countplot(y_train, palette=['#' + ('{}'.format(i))*6 for i in range(10)])
plt.title('train labels count')

plt.subplot(1, 2, 2)
sns.countplot(y_test, palette=['#fb'+ ('{}'.format(i))*4 for i in range(10)])
plt.title('test labels count')

plt.plot()

Train 및 Test 이미지 확인

이미지의 모습을 직관적으로 확인하기 위해 이미지를 화면에 그립니다.

Train Image

plt.figure(figsize=(12, 12))
for i in range(36):
    plt.subplot(6, 6, i+1)
    plt.suptitle('Train Images', fontsize=20)
    plt.title(item[y_train[i]])
    plt.imshow(x_train[i], cmap=plt.cm.gray)
    plt.axis("off")

plt.show()

Test Image

plt.figure(figsize=(12, 12))
for i in range(36):
    plt.subplot(6, 6, i+1)
    plt.suptitle('Test Images', fontsize=20)
    plt.title(item[y_test[i]])
    plt.imshow(x_test[i], cmap=plt.cm.gray)
    plt.axis("off")

plt.show()

4. 전처리(Preprocessing)

신경망에 데이터를 입력하기 전, 전처리를 통해 올바르게 신경망에 들어갈 수 있도록 합니다.

이미지 데이터 전처리

x_train = x_train.reshape(-1, 28, 28, 1)
x_train = x_train.astype('float32')
x_train = x_train/255

x_test = x_test.reshape(-1, 28, 28, 1)
x_test = x_test.astype('float32')
x_test = x_test/255

기존에 3차원이던 데이터를 4차원으로 변경 후, Data Type을 Float32 로 변경 및 Normalization을 진행했습니다.

레이블 데이터 전처리

y_onehot_train = to_categorical(y_train, num_classes=10)
y_onehot_test = to_categorical(y_test, num_classes=10)

데이터를 원 핫 인코딩(One-hot Encoding) 하여 10개의 레이블이 0과 1로 표현되도록 변경하였습니다.

결과

for i in [x_train, y_onehot_train, x_test, y_onehot_test]:
    print(i.shape)
(60000, 28, 28, 1)
(60000, 10)
(10000, 28, 28, 1)
(10000, 10)

이미지 데이터는 3차원에서 4차원으로 변경된 것을 볼 수 있고, 레이블 데이터는 One-Hot Encoding을 통해 2차원으로 변한 것을 볼 수 있습니다.

5. Keras를 활용한 모델 생성

Keras를 사용하여 옷 종류를 분류하는 신경망을 구성합니다.

Hyper Parameter 생성

신경망 모델에 들어가는 Hyper Parameter 을 설정해줍니다.

INPUT_SHAPE = (28, 28, 1) # 입력 데이터가 들어가는 포멧 설정
OUTPUT_SHAPE = 10 # 출력 데이터가 나오는 포멧 설정
BATCH_SIZE = 128 # 한 번에 처리할 데이터량 설정
EPOCHS = 10 # 신경망을 학습할 횟수
VERBOSE = 1 # 학습 진행 상황 출력 모드 설정 

Model 생성

model = Sequential([
  Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=INPUT_SHAPE),
  MaxPooling2D(pool_size=(2, 2)),

  Flatten(),

  Dense(128, activation='relu'),
  Dropout(0.25),

  Dense(64, activation='relu'),
  Dropout(0.25),

  Dense(10, activation='softmax')
])

Model 컴파일

model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

Model Summary

모델을 생성 후 구조에 대해 summary() 를 사용하여 확인해볼 수 있습니다.

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
flatten (Flatten)            (None, 5408)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               692352    
_________________________________________________________________
dropout (Dropout)            (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                8256      
_________________________________________________________________
dropout_1 (Dropout)          (None, 64)                0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                650       
=================================================================
Total params: 701,578
Trainable params: 701,578
Non-trainable params: 0
_________________________________________________________________

Model 학습

위에서 설계한 신경망을 가지고 학습을 진행합니다.

history = model.fit(
    x_train, y_onehot_train,
    epochs=EPOCHS,
    batch_size=BATCH_SIZE,
    verbose=VERBOSE,
    validation_split=0.3
)
Epoch 1/10
329/329 [==============================] - 18s 55ms/step - loss: 0.6393 - accuracy: 0.7751 - val_loss: 0.3787 - val_accuracy: 0.8633
Epoch 2/10
329/329 [==============================] - 18s 54ms/step - loss: 0.3886 - accuracy: 0.8641 - val_loss: 0.3330 - val_accuracy: 0.8766
Epoch 3/10
329/329 [==============================] - 18s 54ms/step - loss: 0.3318 - accuracy: 0.8827 - val_loss: 0.2928 - val_accuracy: 0.8951
Epoch 4/10
329/329 [==============================] - 18s 53ms/step - loss: 0.2923 - accuracy: 0.8955 - val_loss: 0.2695 - val_accuracy: 0.9023
Epoch 5/10
329/329 [==============================] - 18s 53ms/step - loss: 0.2711 - accuracy: 0.9024 - val_loss: 0.2660 - val_accuracy: 0.9031
Epoch 6/10
329/329 [==============================] - 18s 54ms/step - loss: 0.2525 - accuracy: 0.9086 - val_loss: 0.2588 - val_accuracy: 0.9072
Epoch 7/10
329/329 [==============================] - 18s 53ms/step - loss: 0.2340 - accuracy: 0.9143 - val_loss: 0.2496 - val_accuracy: 0.9121
Epoch 8/10
329/329 [==============================] - 17s 53ms/step - loss: 0.2192 - accuracy: 0.9208 - val_loss: 0.2504 - val_accuracy: 0.9121
Epoch 9/10
329/329 [==============================] - 17s 53ms/step - loss: 0.2042 - accuracy: 0.9238 - val_loss: 0.2542 - val_accuracy: 0.9125
Epoch 10/10
329/329 [==============================] - 17s 53ms/step - loss: 0.1924 - accuracy: 0.9289 - val_loss: 0.2492 - val_accuracy: 0.9147

6. 결과 확인

신경망 학습 후 성능에 대한 결과를 확인합니다.

Accuracy & Loss

plt.figure(figsize=(14, 5))

plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')

plt.show()

모델 평가

테스트 데이터를 통한 평가

model.evaluate(x_test, y_onehot_test)
313/313 [==============================] - 2s 5ms/step - loss: 0.2678 - accuracy: 0.9053
[0.2678438723087311, 0.9053000211715698]

테스트 데이터에 대한 성능이 90.53% 이 나오는 것을 확인할 수 있습니다.

모델 예측

y_pred_enc = model.predict(x_test)
y_pred = [np.argmax(i) for i in y_pred_enc]
fig, ax = plt.subplots(figsize=(18, 8))
for idx, row in enumerate(x_test[:8]):
    plt.subplot(2, 4, idx+1)
    plt.title(item[y_pred[idx]])
    img = row.reshape(28, 28)
    fig.suptitle("Predicted values", fontsize=20)
    plt.axis('off')
    plt.imshow(img, cmap=plt.cm.gray)

모델에 대한 평가를 싸이킷 런(sklearn) 라이브러리 내에 있는 classification_report 를 통해 한눈에 볼 수 있습니다.

print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       0.87      0.84      0.85      1000
           1       1.00      0.97      0.98      1000
           2       0.81      0.88      0.85      1000
           3       0.89      0.92      0.91      1000
           4       0.87      0.83      0.85      1000
           5       0.99      0.97      0.98      1000
           6       0.74      0.73      0.74      1000
           7       0.94      0.98      0.96      1000
           8       0.98      0.98      0.98      1000
           9       0.97      0.95      0.96      1000

    accuracy                           0.91     10000
   macro avg       0.91      0.91      0.91     10000
weighted avg       0.91      0.91      0.91     10000

분류결과표, 혼동 행렬(Confusion Matrix)

모델이 예측한 결과를 분류결과표를 사용해 분석할 수 있습니다. 분류 결과를 봤을 때, 형태가 비슷한 옷들(T-short/top, Shirt, Dress, Coat)에 대해 오판단이 많았습니다.

fig, ax = plt.subplots(figsize=(10, 10))
sns.heatmap(
    confusion_matrix(y_test, y_pred), 
    annot=True, 
    cbar=False, 
    fmt='3d', 
    cmap='Blues', 
    ax=ax
)
ax.set_title(
    'Confusion Matrix', 
    loc='left', 
    fontsize=16
)
ax.set_xlabel('Predicted')
ax.set_ylabel('Actual')
ax.set_xticklabels(item.values())
ax.set_yticklabels(item.values(), rotation=0)

plt.show()

마치며

케라스를 사용하여 간단한 분류 모델을 생성 후 평가를 진행했습니다. 간단한 신경망을 사용해 분류했기 때문에 성능이 크게 좋진 않습니다. 하지만, 차후에 이뤄지는 포스팅에는 이미지 분류 및 검출에서 좋은 성능을 보여준 모델들을 리뷰하고 구현하는 포스팅을 작성하도록 하겠습니다.

Reference

  • tensorflow.keras Docs(Link)

  • 분류 성능 평가(Link)

profile
변화를 두려워하지 않는 개발자입니다.

0개의 댓글