본문 바로가기
데이터 과학 관련 스터디/모두의 딥러닝

[모두의 딥러닝] 16장 이미지 인식의 꽃, CNN 익히기

by inhovation97 2020. 8. 15.

아직 여러 데이터를 접해보지 못했을 때에는 궁금했습니다.

비정형 데이터들이 어떤 식의 데이터로 넣어 머신러닝이 학습하는지 도무지 감이 오지 않았죠. 이 책을 통해서 접하면서 신세계인 느낌? 정형 데이터보다 더 더욱 재밌었습니다. 오늘은 비정형 데이터 중 MNIST 이미지 데이터를 다룹니다.

 

 

CNN은 제가 이 책으로만은 이해도나 궁금증이 해결되지 않아서 구글링을 하면서 공부한 것을 따로 포스팅 했습니다.

이 포스팅에서는 실습을 위주로 다루겠습니다.

https://inhovation97.tistory.com/15

 

CNN( Convolutional Neural Network)이 대체 뭐야?

모두의 딥러닝이라는 서적을 통해 딥러닝을 처음 접하면서 CNN(합성곱 신경망)이라는 모델을 공부했습니다. 통계 전공이지만 처음 알게되는 사실들이 많아 책보다는 좀 더 딥하게 공부하고 싶어

inhovation97.tistory.com

 

 

<이미지 데이터 전처리/시각화>

 

from keras.datasets import mnist
from keras.utils import np_utils

import numpy as np
import pandas as pd
import sys
import tensorflow as tf

# seed값 설정
seed=0
np.random.seed(seed)
tf.random.set_seed(3)

# MNIST 데이터셋 불러오기
(X_train, Y_class_train),(X_test, Y_class_test) = mnist.load_data()

print('학습셋 이미지 수 : %d 개' % (X_train.shape[0]))
print('테스트셋 이미지 수 : %d 개' % (X_test.shape[0]))

# 그래프로 확인
import matplotlib.pyplot as plt
plt.imshow(X_train[0], cmap='Greys')
plt.show()

## 코드로 확인
for x in X_train[0]:
    for i in x:
        sys.stdout.write('%d\t' % i)   # 1행에 28개 그 다음은 \n으로 다음행으로 넘어감
    sys.stdout.write('\n')

# 차원 변환 과정
X_train = X_train.reshape(X_train.shape[0], 784) # 60000행, 28*28열로 재배치
X_train = X_train.astype('float64')
X_train = X_train / 255

# 클래스 값 확인
print('class : %d' % (Y_class_train[0]))

# 바이너리화 과정

Y_train = np_utils.to_categorical(Y_class_train, 10)
Y_test = np_utils.to_categorical(Y_class_test, 10)

print(Y_train[0])

이미지 데이터는 이렇게 픽셀들을 명암의 숫자로 전처리하여 입력 데이터로 만들어 줍니다.

 

<다층 퍼셉트론으로 학습한 딥러닝 기본 프레임>

 

from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import ModelCheckpoint, EarlyStopping

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import os
import tensorflow as tf

# seed 값 설정
seed=0
np.random.seed(seed)
tf.random.set_seed(3) # 버전 달라서 random.set_seed로 코딩해야함

# mnist 데이터 불러오기
(X_train, Y_train),(X_test,Y_test) = mnist.load_data()

X_train = X_train.reshape(X_train.shape[0],784).astype('float32')/255 #float64보다 숫자의 범위는 작지만 메모리가 적게듦
X_test = X_test.reshape(X_test.shape[0],784).astype('float32')/255

Y_train = np_utils.to_categorical(Y_train, 10)
Y_test = np_utils.to_categorical(Y_test, 10)

# 모델 프레임 설정
model = Sequential()
model.add(Dense(512, input_dim=784, activation='relu'))
model.add(Dense(10, activation='softmax'))

# 모델 실행 환결 설정
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# 모델 최적화 설정
MODEL_DIR = './model2/'
if not os.path.exists(MODEL_DIR):
    os.mkdir(MODEL_DIR)

modelpath = './model2/{epoch:02d}-{val_loss:.4f}.hdf5'
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, save_best_only=True)
early_stopping_callback = EarlyStopping(monitor='val_loss',patience=10)


# 모델의 실행
history = model.fit(X_train, Y_train, validation_data = (X_test, Y_test), epochs=30, batch_size=200, verbose=0, callbacks=[early_stopping_callback, checkpointer])

# 테스트 정확도 출력
print('\n Test Accuracy: %.4f' % (model.evaluate(X_test,Y_test)[1]))

학습이 23번째에서 멈추고 최종적인 정확도는 0.9833이 나왔습니다.

 

 

 

이제 train과 test 데이터의 오차를 그래프로 비교해보겠습니다.

# 테스트셋의 오차
y_vloss=history.history['val_loss']

# 학습셋의 오차
y_loss = history.history['loss']

# 그래프로 표현
x_len = np.arange(len(y_loss))
plt.figure(figsize=(15, 10)) # 크기 지정
plt.plot(x_len, y_vloss, marker='.',c='red', label='Testset_loss')
plt.plot(x_len, y_loss, marker='.',c='blue', label='Trainset_loss' )

# 그래프에 그리드를 주고 레이블을 표시
plt.legend(loc='upper right')
# plt.axis([0,20,0,0.35])
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.figure(figsize=(15, 10)) # 크기 지정
plt.show()

test셋의 오차가 10번의 반복에도 오차가 개선되지 않아서 학습을 그만두는 것을 알 수 있습니다.

 

 

<CNN(Convolution Neural Network)으로 학습시키기>

 

# CNN 설계하기
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.callbacks import ModelCheckpoint, EarlyStopping

import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf

# seed값 설정
seed=0
np.random.seed(seed)
tf.random.set_seed(3)

# 데이터 불러오기
(X_train, Y_train),(X_test, Y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 28, 28,1).astype('float32') / 255
X_test = X_test.reshape(X_test.shape[0], 28, 28,1).astype('float32') / 255

Y_train = np_utils.to_categorical(Y_train)
Y_test = np_utils.to_categorical(Y_test)

# 컨볼루션 신경망 설정
model = Sequential()
model.add(Conv2D(32, (3,3), input_shape=(28,28,1), activation='relu'))
model.add(Conv2D(64, (3,3),activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
model.compile(loss = 'categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# 모델 최적화 설정
CNNMODEL_DIR = './CNNmodel/'
if not os.path.exists(CNNMODEL_DIR):
    os.mkdir(CNNMODEL_DIR)
    
modelpath='./CNNmodel/{epoch:02d}-{val_loss:.4f}.hdf5'
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, save_best_only=True)
early_stopping_callback = EarlyStopping(monitor='val_loss',patience=10)

# 모델의 실행
history= model.fit(X_train,Y_train, validation_data=(X_test,Y_test),epochs=30, verbose=0, batch_size=200, callbacks=[early_stopping_callback, checkpointer])

# 테스트 정확도 출력
print('\n Test Accuray: %.4f' % (model.evaluate(X_test,Y_test)[1]))

# 테스트셋의 오차
y_vloss = history.history['val_loss']

#학습셋의 오차
y_loss = history.history['loss']

# 그래프로 표현
x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, marker='.', c='red', label='Testset_loss')
plt.plot(x_len, y_loss, marker='.', c='blue', label='Trainset_loss')

# 그래프에 그리드를 주고 레이블을 표시

plt.legend(loc = 'upper right')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

 

모델을 설계하는 부분을 봅시다. 원래의 입력층 앞에 컨볼루션층 맥스풀링층을 추가하고 드롭아웃으로 과적합을 방지해주는 것을 알 수 있습니다.

컨볼루션 층1(32개의 필터) -> 컨볼루션 층2(64개의 필터) -> 맥스풀링 -> 드롭아웃(25%) -> 플래튼(데이터 1차원화) -> FC층(중간에 드롭아웃25%) -> 레이블 출력(소프트 맥스)

CNN모델은 정확도가 0.9937으로 엄청나게 향상함을 알 수 있습니다. 책에서는 이미지 데이터 중에서도 숫자가 아닌 이상한 이미지들 때문에 100%를 기록하지 못했다고 합니다. 학습 시간은 CPU를 이용했는데 데이터가 가벼워서 그런지 엄청 오래걸리지는 않았습니다.

댓글