딥러닝
CNN - mnist 데이터 셋
J.H_DA
2022. 5. 11. 10:20
MNIST 데이터셋 CNN 활용하기
MNIST 데이터셋은 미국 국립표준기술원(NIST)이 고등학생과 인구조사국 직원 등이 쓴 손글씨를 이용해 만든 데이터로 구성되어 있음
- 70,000개의 글자 이미지에 각각 0부터 9까지 이름표를 붙인 데이터셋
- 머신러닝을 배우는 사람이라면 자신의 알고리즘과 다른 알고리즘의 성과
- 이미지는 가로 28 x 세로 28 = 총 784개의 픽셀로 이루어져 있음
- 각 픽셀은 발기 정도에 따라 0부터 255까지의 등급을 매김
- 흰색 배경이 0이라면 글씨가 들어간 곳은 1~255까지 숫자 중 하나로 채워져 긴 행렬로 이루어진 하나의 집합으로 변환됨
데이터 전처리
- 주어진 가로 28, 세로 28의 2차원 배열을 784개의 1차원 배열로 바꿔 주어야 함 이를 위해 reshape() 함수를 사용 reshape(총 샘플 수, 1차원 속성의 수) 형식으로 지정
- 현재 주어진 데이터의 값으 0부터 255까지의 정수로, 정규화를 위해 255로 나누어 주기 위해 실수형으로 바꾼다.
In [29]:
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense
from tensorflow.keras.callbacks import ModelCheckpoint,EarlyStopping
from tensorflow.keras.utils import to_categorical
import numpy
import sys
import tensorflow as tf
# seed 값 설정
seed = 0
numpy.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)
sys.stdout.write('\n')
# 차원 변환 과정
X_train = X_train.reshape(X_train.shape[0], 784)
X_train = X_train.astype('float64')
X_train = X_train / 255
X_test = X_test.reshape(X_test.shape[0], 784).astype('float64') / 255
#print(X_train[0])
# 클래스 값 확인
print("class : %d " % (Y_class_train[0]))
# 바이너리화 과정
Y_train = to_categorical(Y_class_train, 10)
Y_test = to_categorical(Y_class_test, 10)
print(Y_train[0])
학습셋 이미지 수 : 60000 개
테스트셋 이미지 수 : 10000 개

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 3 18 18 18 126 136 175 26 166 255 247 127 0 0 0 0
0 0 0 0 0 0 0 0 30 36 94 154 170 253 253 253 253 253 225 172 253 242 195 64 0 0 0 0
0 0 0 0 0 0 0 49 238 253 253 253 253 253 253 253 253 251 93 82 82 56 39 0 0 0 0 0
0 0 0 0 0 0 0 18 219 253 253 253 253 253 198 182 247 241 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 80 156 107 253 253 205 11 0 43 154 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 14 1 154 253 90 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 139 253 190 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 11 190 253 70 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 35 241 225 160 108 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 81 240 253 253 119 25 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 186 253 253 150 27 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 93 252 253 187 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 249 253 249 64 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 130 183 253 253 207 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 39 148 229 253 253 253 250 182 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 24 114 221 253 253 253 253 201 78 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 23 66 213 253 253 253 253 198 81 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 18 171 219 253 253 253 253 195 80 9 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 55 172 226 253 253 253 253 244 133 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 136 253 253 253 212 135 132 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
class : 5
[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
딥러닝 기본 프레임 만들기
In [28]:
model = Sequential()
model.add(Dense(512, input_shape=(784,) ,activation="relu"))
model.add(Dense(10, activation = "softmax"))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# 모델 최적화 설정
MODEL_DIR = './model/'
if not os.path.exists(MODEL_DIR):
os.mkdir(MODEL_DIR)
modelpath="./model/{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]))
# 테스트 셋의 오차
y_vloss = history.history['val_loss']
# 학습셋의 오차
y_loss = history.history['loss']
# 그래프로 표현
x_len = numpy.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.axis([0, 20, 0, 0.35])
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
Epoch 1: val_loss improved from inf to 0.14749, saving model to ./model\01-0.1475.hdf5
Epoch 2: val_loss improved from 0.14749 to 0.10245, saving model to ./model\02-0.1025.hdf5
Epoch 3: val_loss improved from 0.10245 to 0.08911, saving model to ./model\03-0.0891.hdf5
Epoch 4: val_loss improved from 0.08911 to 0.07654, saving model to ./model\04-0.0765.hdf5
Epoch 5: val_loss improved from 0.07654 to 0.07351, saving model to ./model\05-0.0735.hdf5
Epoch 6: val_loss improved from 0.07351 to 0.06725, saving model to ./model\06-0.0672.hdf5
Epoch 7: val_loss improved from 0.06725 to 0.06570, saving model to ./model\07-0.0657.hdf5
Epoch 8: val_loss improved from 0.06570 to 0.06225, saving model to ./model\08-0.0622.hdf5
Epoch 9: val_loss improved from 0.06225 to 0.06164, saving model to ./model\09-0.0616.hdf5
Epoch 10: val_loss did not improve from 0.06164
Epoch 11: val_loss did not improve from 0.06164
Epoch 12: val_loss did not improve from 0.06164
Epoch 13: val_loss improved from 0.06164 to 0.06138, saving model to ./model\13-0.0614.hdf5
Epoch 14: val_loss did not improve from 0.06138
Epoch 15: val_loss did not improve from 0.06138
Epoch 16: val_loss did not improve from 0.06138
Epoch 17: val_loss did not improve from 0.06138
Epoch 18: val_loss did not improve from 0.06138
Epoch 19: val_loss did not improve from 0.06138
Epoch 20: val_loss did not improve from 0.06138
Epoch 21: val_loss did not improve from 0.06138
Epoch 22: val_loss did not improve from 0.06138
Epoch 23: val_loss did not improve from 0.06138
313/313 [==============================] - 1s 4ms/step - loss: 0.0727 - accuracy: 0.9825
Test Accuracy: 0.9825

- 위의 그림을 통해 학습셋에 대한 오차는 계속해서 줄어들며
- 테스트셋의 과적합이 일어나기 전 학습을 끝낸 모습을 볼 수 있다.
더 깊은 딥러닝
- 위의 정확도 98.25%보인 딥러닝 프레임은 하나의 은닉층을 둔 아주 단순한 모델이다.
- 딥러닝은 이러한 기본 모델을 바탕으로, 프로젝트에 맞춰서 어떤 옵션을 더하고 어떤 층을 추가하느냐에 따라 성능이 좋아질 수 있다.
- 기본 딥러닝 프레임에 이미지 인식 분야에서 강력한 성능을 보이는 컨볼루션 신경망 (Convolutinal Neural Network, CNN)을 얹어보고자 한다.
컨볼루션 신경망
- 컨볼루션 신경망은 입력된 이미징서 다시 한번 특징을 추출하기 위해 마스크(필터, 윈도, 또는 커널)를 도입하는 기법이다.
##### 맥스 풀링
- 위의 결과가 여전히 크고 복잡하면 이를 다시 한번 축소해야함
- -> 이 과정을 풀링(pooling) 또는 서브 샘플링(sub sampling)이라고 함
- 맥스 풀링은 정해진 구역 안에서 가장 큰 값만 다음 층으로 넘기고 나머지는 버리는 것
- 노드가 많아지거나 층이 많아져 과적합 발생 -> 드롭아웃(drop out)기법 이용
In [41]:
# 케라스에서 컨볼루션 층을 추가하는 함수는 Conv2D()
# -> 첫 번째 인자: 마스크를 몇개 적용할지 정하는 것
# -> Kernel_size: 마스크의 크기를 정한다. kernel_size = (행, 열) 형식으로
# -> Dense 층과 마찬가지로 맨 처음 층에는 입력되는 값을 알려 주어야 한다.
# input_shape = (행, 열, 색상 또는 흑백) 형식으로 정한다.
# 만약 입력 이미지가 색상이면 3, 흑백이면 1을 지정
from tensorflow.keras.datasets import mnist
from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from tensorflow.keras.callbacks import ModelCheckpoint,EarlyStopping
# seed 값 설정
seed = 0
numpy.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, kernel_size = (3,3), input_shape=(28,28,1) ,activation ="relu"))
# 컨볼루션 층을 하나 더 추가
model.add(Conv2D(64, (3,3), activation = 'relu'))
# 맥스풀링
model.add(MaxPooling2D(pool_size=2))
# 25%의 노드를 끄기
model.add(Dropout(0.25))
# 위의 컨볼루션 층에 연결하기 위해 Flatten()함수를 이용하여 1차원으로 바꿔주기
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'])
# 모델 최적화 설정
MODEL_DIR = './model/'
if not os.path.exists(MODEL_DIR):
os.mkdir(MODEL_DIR)
modelpath="./model/{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]))
# 테스트 셋의 오차
y_vloss = history.history['val_loss']
# 학습셋의 오차
y_loss = history.history['loss']
# 그래프로 표현
x_len = numpy.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()
Epoch 1: val_loss improved from inf to 0.05248, saving model to ./model\01-0.0525.hdf5
Epoch 2: val_loss improved from 0.05248 to 0.03991, saving model to ./model\02-0.0399.hdf5
Epoch 3: val_loss improved from 0.03991 to 0.03818, saving model to ./model\03-0.0382.hdf5
Epoch 4: val_loss improved from 0.03818 to 0.03213, saving model to ./model\04-0.0321.hdf5
Epoch 5: val_loss improved from 0.03213 to 0.03154, saving model to ./model\05-0.0315.hdf5
Epoch 6: val_loss improved from 0.03154 to 0.02835, saving model to ./model\06-0.0283.hdf5
Epoch 7: val_loss did not improve from 0.02835
Epoch 8: val_loss did not improve from 0.02835
Epoch 9: val_loss did not improve from 0.02835
Epoch 10: val_loss did not improve from 0.02835
Epoch 11: val_loss did not improve from 0.02835
Epoch 12: val_loss did not improve from 0.02835
Epoch 13: val_loss improved from 0.02835 to 0.02686, saving model to ./model\13-0.0269.hdf5
Epoch 14: val_loss did not improve from 0.02686
Epoch 15: val_loss did not improve from 0.02686
Epoch 16: val_loss did not improve from 0.02686
Epoch 17: val_loss did not improve from 0.02686
Epoch 18: val_loss did not improve from 0.02686
Epoch 19: val_loss did not improve from 0.02686
Epoch 20: val_loss did not improve from 0.02686
Epoch 21: val_loss did not improve from 0.02686
Epoch 22: val_loss did not improve from 0.02686
Epoch 23: val_loss did not improve from 0.02686
313/313 [==============================] - 5s 15ms/step - loss: 0.0307 - accuracy: 0.9931
Test Accuracy: 0.9931

728x90