실전문제로 배우는 머신러닝 - 2주차
딥러닝을 사용해 이미지 분류하기
세계 패션 산업은 3조 달러의 규모로 세계 GDP의 2%를 차지하고 있습니다.
패션 산업은 새로운 컴퓨터 비전과 머신러닝, 딥러닝 기술을 받아들이며 극적인 변화를 겪고 있는데요
이번 프로젝트에서는 고객의 인스타그램과 페이스북 이미지를 살펴보고, 고객이 착용한 가방, 드레스, 바지 등의 패션 카테고리를 분류해보겠습니다😎
프로젝트 목적
- 패션 이미지를 보고 그 이미지가 어떤 옷인지 알려주는 모델을 만들기
- 예) 이미지를 보고 반바지인지 가방인지 모자인지를 인식
적용할 수 있는 점
- 패션 트렌드를 감지하고 예측해 적절한 마케팅 캠페인을 제시 가능
- 특정 고객만을 타겟으로 한 마케팅 가능
데이터
- 7만개의 패션 MNIST 데이터
- 학습 데이터 세트 : 6만개, 테스트 데이터 세트 : 1만개
- 다운로드 링크 : train_data, test_data
프로젝트 진행 방향
- 흑백 이미지가 어떤 패션 아이템인지 분류
프로젝트를 진행하기에 앞서, 이미지를 데이터로 어떻게 표현할까요?

보통 분석을 할 때 흑백 이미지를 사용하는데, 흑백은 0~255 사이의 숫자로 색상을 나타낼 수 있습니다.
만약 검은 선이나 검은 점을 표현하고 싶다면 픽셀 안에 숫자 0을 넣으면 됩니다. 또한, 색상이 흰색임을 나타내고 싶다면 255를 넣으면 되는 식입니다.
따라서 이 위치가 이정도 색상을 가지고 있다면 이건 가방이구나! 이런식으로 학습을 하게 됩니다.
그럼 프로젝트를 시작해봅시다!
1️⃣ 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
2️⃣ MNIST 데이터셋 불러오기
fashion_train_df = pd.read_csv('다운로드한 본인 파일 경로/fashion-mnist_train.csv', sep=',')
fashion_test_df = pd.read_csv('다운로드한 본인 파일 경로/fashion-mnist_test.csv', sep=',')
3️⃣ 데이터 시각화
- 이미지들은 28X28 픽셀, 즉 784 픽셀로 표현이 된다 (column의 수)
- 이미지를 평탄화해서 각 행이 이미지를 나타내도록 한 것이다
print(fashion_train_df.shape)
print(fashion_test_df.shape)

fashion_train_df.head()

training = np.array(fashion_train_df, dtype = 'float32')
testing = np.array(fashion_test_df, dtype = 'float32')
- 하나의 이미지를 시각화
- • plt.imshow 사용
plt.imshow(training[10,1:].reshape(28,28))

- 무작위 값을 설정해서 테스트해보기
import random
i = random.randint(1,10000)
plt.imshow(training[i,1:].reshape(28,28))
label = training[i,0]
label

- 데이터를 행렬 형태로 도식화
# 간단한 형태로 행렬(격자) 만들기
W_grid = 15
L_grid = 15
# 격자 차원으로 하위 그래프 생성
fig, axes = plt.subplots(L_grid, W_grid, figsize = (17,17))
# 배열과 축을 15x15로 평탄화
axes = axes.ravel()
# 학습 데이터 길이 정의
n_training = len(training)
# 도식화하고자하는 전체 이미지 출력
# 무작위 변수를 만들고 변수의 인덱스와 변수에 해당하는 이미지 출력
for i in np.arange(0, W_grid * L_grid):
index = np.random.randint(0, n_training)
axes[i].imshow(training[index,1:].reshape((28,28)))
axes[i].set_title(training[index,0], fontsize = 8)
axes[i].axis('off')
# 이미지 사이의 높이인 hspace 지정
plt.subplots_adjust(hspace=0.4)

4️⃣ 모델 학습
- 이미지를 스캔하여 이미지의 특징을 추출
X_train = training[:, 1:]/255
y_train = training[:, 0]
X_test = testing[:, 1:]/255
y_test = testing[:, 0]
from sklearn.model_selection import train_test_split
X_train, X_validate, y_train, y_validate = train_test_split(X_train, y_train,
test_size = 0.2,
random_state = 12345)
X_train = X_train.reshape(X_train.shape[0], *(28,28, 1))
X_test = X_test.reshape(X_test.shape[0], *(28,28, 1))
X_validate = X_validate.reshape(X_validate.shape[0], *(28,28, 1))
print(X_test.shape)
print(X_train.shape)
print(X_validate.shape)

import keras
# 완전 연결 네트워크 구축
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
from keras.optimizers import Adam
from keras.callbacks import TensorBoard
- 모델 구축
- 모델을 순차적인 형태로 구축
cnn_model = Sequential()
cnn_model.add(Conv2D(32, 3, 3, input_shape = (28, 28, 1), activation = 'relu'))
cnn_model.add(MaxPooling2D(pool_size = (2,2)))
cnn_model.add(Flatten())
cnn_model.add(Dense(32, activation = 'relu'))
cnn_model.add(Dense(10, activation = 'sigmoid'))
cnn_model.compile(loss = 'sparse_categorical_crossentropy', optimizer=Adam(lr=0.001), metrics = ['accuracy'])
epochs = 50
cnn_model.fit(X_train,
y_train,
batch_size = 512,
epochs = epochs,
verbose = 1,
validation_data = (X_validate, y_validate))

→ 50회 epoch를 수행한 후 정확도가 87%에 도달했다. 꽤 높다
5️⃣ 모델 평가
evaluation = cnn_model.evaluate(X_test, y_test)
print('Test Accuracy : {:.3f}'.format(evaluation[1]))

- 예측 클래스 사용해서 모델 평가하기
predicted_classes = cnn_model.predict_classes(X_test)
predicted_classes

L = 5
W = 5
fig, axes = plt.subplots(L, W, figsize = (12, 12))
axes = axes.ravel()
for i in np.arange(0, L*W):
axes[i].imshow(X_test[i].reshape(28,28))
axes[i].set_title('Prediction Class = {:.1f}\n True Class = {:0.1f}'.format(predicted_classes[i], y_test[i]))
axes[i].axis('off')
plt.subplots_adjust(wspace = 0.5)

- 혼동 행렬로 모델 평가하기
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, predicted_classes)
plt.figure(figsize = (14,10))
sns.heatmap(cm, annot = True)

→ 대각선 : 맞춘 개수 & 나머지 : 틀린 개수
from sklearn.metrics import classification_report
num_classes = 10
target_names = ['Class {}'.format(i) for i in range(num_classes)]
print(classification_report(y_test, predicted_classes, target_names = target_names))

Class별 옷 종류
0 : 티셔츠
1 : 바지
2 : 스웨터
3 : 원피스
4 : 코트
5 : 샌들
6 : 셔츠
7 : 운동화
8 : 가방
9 : 앵클 부츠
⇒ 셔츠의 분류 정확도가 가장 떨어진다는 것을 알 수 있다
6️⃣ 모델 개선
모델 개선을 위해서는 두 가지 방법이 있다.
- 32x32 커널을 64x64 또는 128x128로 바꿔보자
- 드롭 아웃
이 방법들은 본 프로젝트에서는 다루지 않습니다!
본 스터디는 Udemy의 <【한글자막】 Machine Learning 완벽 실습 : 6가지 실제 사례 직접 해결하기> 강의를 활용해 진행됐습니다. 강의에 대한 자세한 정보는 아래에서 확인하실 수 있습니다.
프밍 스터디는 Udemy Korea와 함께 합니다.