손글씨.py
MNIST 손글씨 숫자 분류 - CNN(합성곱 신경망) 사용
핵심 개념
- Conv2D: 합성곱 레이어
- MaxPooling2D: 최대 풀링
- Flatten: 4차원 → 2차원 변환
- MNIST 데이터셋 활용
#CNN-합성곱 사용
import numpy as np
from tensorflow.keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.optimizers import Adam
import time
from keras.utils import np_utils
np.random.seed(3)
# 1. 데이터셋 준비하기
# 훈련셋과 시험셋 로딩
(x_train, y_train), (x_test, y_test) = mnist.load_data() #데이터셋 mnist 데이터를 제공해준다
#3차원 -> 4차원으로 , 채널이 하나 추가된다. 1이면 흑백 3이면 컬러, 마지막 차원이 색에 대한 부분인데
#이미지가 흑백이므로 채널을 1로 지정한다.
x_train = x_train.reshape(60000, 28, 28, 1)
x_test = x_test.reshape(10000, 28, 28, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
from keras.utils import to_categorical
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import Adam
model = Sequential() #순차
#CNN으로 수정함
#3 by 3 필터 8개를 사용해서 이미지의 특성을 추출한다
model.add( Conv2D(8, (3,3) , padding='same', input_shape=(28,28,1), activation='relu'))
#합성곱의 출력은 4차원임 이걸 2차원으로 바꿔야 한다. Flattern()에 맡긴다
model.add(Flatten())
#출력레이어 : 뉴런의 개수, 활성화함수 : softmax 를 쓴다
#softmax 는 각 뉴런들의 출력값의 합이 1이 되도록 확률로 만들어 주는 일을 한다
model.add(Dense(10, activation='softmax'))
#loss 손실함수 - 비용을 최소화 하기 위한 함수를 categorical_crossentropy를 사용한다
#최적화는 Adam()(-2015년에 발표된 경사하강법의 새로운 알고리즘) 객체 사용
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])
import time
startTime = time.time()
#학습을 한다.
history = model.fit(x_train, y_train, epochs=20, batch_size=1000,
verbose=1, validation_data=(x_test, y_test))
#epochs - 학습갱신횟수지정 , 훈련데이터 60000개에 batch_size를 1000을 하면
#학습데이터를 모두 사용하는데 60개의 매개변수 갱신이 이루어짐 이를 1에포크라 한다
#batch-size:한번에 이루어지는 매개변수 갱신양
#verbose :0 학습내용 안보임, 1 학습내용 보임
#validateion_data, 검증데이터를 전달한다
#모델평가
loss1, acc1 = model.evaluate(x_train, y_train, verbose=0)
loss2, acc2 = model.evaluate(x_test, y_test, verbose=0)
print('Train loss:', loss1)
print('Train accuracy:', acc1)
print('Test loss:', loss2)
print('Test accuracy:', acc2)
print("Computation time:{0:.3f} sec".format(time.time() - startTime))
#이미지화 한다
import numpy as np
import matplotlib.pyplot as plt
plt.figure(1, figsize=(10, 4))
plt.subplots_adjust(wspace=0.5)
plt.subplot(1, 2, 1) #화면을 2개로 나눈다 왼쪽에 손실값을
plt.plot(history.history['loss'], label='training', color='black')
plt.plot(history.history['val_loss'], label='test', color='cornflowerblue')
plt.ylim(0, 10)
plt.legend()
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.subplot(1, 2, 2) #오른쪽에 정확도
plt.plot(history.history['accuracy'], label='training', color='black')
plt.plot(history.history['val_accuracy'],label='test', color='cornflowerblue')
plt.ylim(0, 1)
plt.legend()
plt.grid()
plt.xlabel('epoch')
plt.ylabel('acc')
plt.show()
def show_prediction(n_show):
y = model.predict(x_test) #예측을 한다
plt.figure(2, figsize=(12, 8))
plt.gray()
for i in range(n_show):
plt.subplot(8, 12, i + 1)
x = x_test[i, :]
x = x.reshape(28, 28)
plt.pcolor(1 - x)
wk = y[i, :]
prediction = np.argmax(wk)
plt.text(22, 25.5, "%d" % prediction, fontsize=12)
if prediction != np.argmax(y_test[i, :]):
plt.plot([0, 27], [1, 1], color='cornflowerblue', linewidth=5)
plt.xlim(0, 27)
plt.ylim(27, 0)
plt.xticks([], "")
plt.yticks([], "")
#-- 메인
show_prediction(90)
plt.show()