MNIST Dataset 이용한 CNN 모델 구축¶
In [2]:
# from IPython.core.display import display, HTML
# display(HTML("<style>.container { width:100% !important; }</style>"))
# ! pip install tqdm
# from tqdm import tqdm_notebook
In [2]:
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
import os
print(tf.__version__) # Tensorflow의 버전을 출력
mnist = keras.datasets.mnist
# MNIST 데이터를 로드. 다운로드하지 않았다면 다운로드까지 자동으로 진행됩
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print(len(x_train)) # x_train 배열의 크기를 출력
2.6.0 60000
In [3]:
plt.imshow(x_train[0],cmap=plt.cm.binary)
plt.show()
In [4]:
print(y_train[0]) #x_train[0]에 대응되는 y값
5
In [13]:
# index에 0에서 59999 사이 숫자를 지정해 보세요.
index=0
plt.imshow(x_train[index],cmap="gray") #camp로 호출색상변경가능
plt.show()
print( (index+1), '번째 이미지의 숫자는 바로 ', y_train[index], '입니다.')
1 번째 이미지의 숫자는 바로 5 입니다.
In [14]:
print(x_train.shape) # 28x28 크기의 숫자 이미지가 60,000장
(60000, 28, 28)
In [15]:
print(x_test.shape) # 28x28 크기의 숫자 이미지가 10,000장
(10000, 28, 28)
In [17]:
print(y_train.shape) #0~9 label 열벡터
(60000,)
In [18]:
print(y_test.shape) #0~9 label 열벡터
(10000,)
In [19]:
print('최소값:',np.min(x_train), ' 최대값:',np.max(x_train))
#손글씨 이미지의 실제 픽셀값 - 흑백사진
최소값: 0 최대값: 255
In [21]:
#정규화(0~1)사이 값으로 변환(nomalization)
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0
print('최소값:',np.min(x_train_norm), ' 최대값:',np.max(x_train_norm))
최소값: 0.0 최대값: 1.0
In [22]:
#sequential model 만들기
model=keras.models.Sequential()
model.add(keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(28,28,1)))
#필터갯수, 필터사이즈, 활성함수종류, 인풋 데이터 사이즈 행,열,채널(흑백 = 1, 칼라 =3)
model.add(keras.layers.MaxPool2D(2,2))
model.add(keras.layers.Conv2D(32, (3,3), activation='relu'))
model.add(keras.layers.MaxPooling2D((2,2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(32, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
print('Model에 추가된 Layer 개수: ', len(model.layers))
Model에 추가된 Layer 개수: 7
In [23]:
model.summary()
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 13, 13, 16) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 11, 11, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 5, 5, 32) 0 _________________________________________________________________ flatten (Flatten) (None, 800) 0 _________________________________________________________________ dense (Dense) (None, 32) 25632 _________________________________________________________________ dense_1 (Dense) (None, 10) 330 ================================================================= Total params: 30,762 Trainable params: 30,762 Non-trainable params: 0 _________________________________________________________________
In [24]:
# 데이터 크기 변경
print("Before Reshape - x_train_norm shape: {}".format(x_train_norm.shape))
print("Before Reshape - x_test_norm shape: {}".format(x_test_norm.shape))
x_train_reshaped=x_train_norm.reshape( -1, 28, 28, 1) # 데이터갯수에 -1을 쓰면 reshape시 자동계산됩니다.
x_test_reshaped=x_test_norm.reshape( -1, 28, 28, 1) #채널 수 정보 추가
print("After Reshape - x_train_reshaped shape: {}".format(x_train_reshaped.shape))
print("After Reshape - x_test_reshaped shape: {}".format(x_test_reshaped.shape))
Before Reshape - x_train_norm shape: (60000, 28, 28) Before Reshape - x_test_norm shape: (10000, 28, 28) After Reshape - x_train_reshaped shape: (60000, 28, 28, 1) After Reshape - x_test_reshaped shape: (10000, 28, 28, 1)
In [25]:
#모델 학습
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train_reshaped, y_train, epochs=10)
Epoch 1/10 1875/1875 [==============================] - 21s 3ms/step - loss: 0.1977 - accuracy: 0.9401 Epoch 2/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0644 - accuracy: 0.9804 Epoch 3/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0482 - accuracy: 0.9852 Epoch 4/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0379 - accuracy: 0.9882 Epoch 5/10 1875/1875 [==============================] - 7s 3ms/step - loss: 0.0309 - accuracy: 0.9904 Epoch 6/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0245 - accuracy: 0.9920 Epoch 7/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0208 - accuracy: 0.9934 Epoch 8/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0168 - accuracy: 0.9942 Epoch 9/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0149 - accuracy: 0.9950 Epoch 10/10 1875/1875 [==============================] - 6s 3ms/step - loss: 0.0113 - accuracy: 0.9964
Out[25]:
<keras.callbacks.History at 0x7fcd55ea05e0>
In [26]:
#모델 평가 - x_test_reshaped, y_test_reshaped로 테스트
test_loss, test_accuracy = model.evaluate(x_test_reshaped,y_test, verbose=2)
print("test_loss: {} ".format(test_loss))
print("test_accuracy: {}".format(test_accuracy))
313/313 - 1s - loss: 0.0376 - accuracy: 0.9899 test_loss: 0.037551283836364746 test_accuracy: 0.9898999929428101
In [27]:
predicted_result = model.predict(x_test_reshaped) # model이 추론한 확률값.
predicted_labels = np.argmax(predicted_result, axis=1)
idx=0 #1번째 x_test를 살펴보자.
print('model.predict() 결과 : ', predicted_result[idx])
print('model이 추론한 가장 가능성이 높은 결과 : ', predicted_labels[idx])
print('실제 데이터의 라벨 : ', y_test[idx])
model.predict() 결과 : [3.6367868e-13 7.7646960e-15 1.6492735e-09 2.0579480e-13 2.8197236e-10 3.0436607e-13 2.7596068e-13 1.0000000e+00 2.0266992e-17 2.5288668e-10] model이 추론한 가장 가능성이 높은 결과 : 7 실제 데이터의 라벨 : 7
In [28]:
plt.imshow(x_test[idx],cmap=plt.cm.binary)
plt.show()
In [29]:
import random
wrong_predict_list=[]
for i, _ in enumerate(predicted_labels):
# i번째 test_labels과 y_test이 다른 경우만 모아 봅시다.
if predicted_labels[i] != y_test[i]: #예측값과 실제값이 다를때
wrong_predict_list.append(i) #해당리스트에 값 어펜드
# wrong_predict_list 에서 랜덤하게 5개만 뽑아봅시다.
samples = random.choices(population=wrong_predict_list, k=5)
#잘못 예측한 리스트에서 랜덤값 뽑기
for n in samples:
print("예측확률분포: " + str(predicted_result[n]))
print("라벨: " + str(y_test[n]) + ", 예측결과: " + str(predicted_labels[n]))
plt.imshow(x_test[n], cmap=plt.cm.binary)
plt.show()
예측확률분포: [2.5002440e-04 1.0245690e-09 2.5353219e-15 1.1071266e-06 1.1941408e-08 5.2960891e-01 3.2309443e-05 1.4854484e-09 4.7010550e-01 2.1216056e-06] 라벨: 8, 예측결과: 5
예측확률분포: [3.9147219e-09 9.4214493e-01 2.1722393e-02 2.9773766e-02 9.7625096e-05 1.6245831e-04 1.0997548e-03 4.7171530e-03 3.1455016e-05 2.5042196e-04] 라벨: 7, 예측결과: 1
예측확률분포: [6.1155564e-01 2.8099885e-06 3.7654374e-08 3.4640699e-08 2.6121957e-02 3.1926160e-07 3.6227769e-01 3.9589918e-11 4.0666800e-05 8.7334104e-07] 라벨: 6, 예측결과: 0
예측확률분포: [2.0192154e-13 1.9170816e-06 2.0269565e-05 3.6810021e-04 9.3050992e-12 3.6814124e-10 1.9614443e-09 1.9616699e-08 9.9960977e-01 1.3182644e-08] 라벨: 2, 예측결과: 8
예측확률분포: [3.5222165e-05 1.2474277e-09 5.9516680e-01 2.4141665e-01 2.6469020e-12 6.7680681e-08 1.4167152e-07 3.4896590e-04 1.6301000e-01 2.2180300e-05] 라벨: 3, 예측결과: 2
In [31]:
# 바꿔 볼 수 있는 하이퍼파라미터들
n_channel_1=16 # 필터갯수 16개
n_channel_2=32 # 필터갯수 32개
n_dense=32 #밀도함수, flatten한 값을 output값으로 산출하기 전 복잡성 추가
n_train_epoch=10 #학습 횟수
model=keras.models.Sequential()
model.add(keras.layers.Conv2D(n_channel_1, (6,6), activation='relu', input_shape=(28,28,1)))
model.add(keras.layers.MaxPool2D(2,2))
model.add(keras.layers.Conv2D(n_channel_2, (3,3), activation='relu'))
model.add(keras.layers.MaxPooling2D((2,2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(n_dense, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
model.summary()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 모델 훈련
model.fit(x_train_reshaped, y_train, epochs=n_train_epoch)
# 모델 시험
test_loss, test_accuracy = model.evaluate(x_test_reshaped, y_test, verbose=2)
print("test_loss: {} ".format(test_loss))
print("test_accuracy: {}".format(test_accuracy))
Model: "sequential_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_4 (Conv2D) (None, 23, 23, 16) 592 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 11, 11, 16) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 9, 9, 32) 4640 _________________________________________________________________ max_pooling2d_5 (MaxPooling2 (None, 4, 4, 32) 0 _________________________________________________________________ flatten_2 (Flatten) (None, 512) 0 _________________________________________________________________ dense_4 (Dense) (None, 32) 16416 _________________________________________________________________ dense_5 (Dense) (None, 10) 330 ================================================================= Total params: 21,978 Trainable params: 21,978 Non-trainable params: 0 _________________________________________________________________ Epoch 1/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.2008 - accuracy: 0.9396 Epoch 2/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0690 - accuracy: 0.9793 Epoch 3/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0505 - accuracy: 0.9844 Epoch 4/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0407 - accuracy: 0.9872 Epoch 5/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0335 - accuracy: 0.9891 Epoch 6/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0278 - accuracy: 0.9913 Epoch 7/10 1875/1875 [==============================] - 5s 3ms/step - loss: 0.0241 - accuracy: 0.9923 Epoch 8/10 1875/1875 [==============================] - 5s 3ms/step - loss: 0.0199 - accuracy: 0.9937 Epoch 9/10 1875/1875 [==============================] - 5s 3ms/step - loss: 0.0192 - accuracy: 0.9939 Epoch 10/10 1875/1875 [==============================] - 5s 2ms/step - loss: 0.0155 - accuracy: 0.9948 313/313 - 1s - loss: 0.0327 - accuracy: 0.9908 test_loss: 0.032724201679229736 test_accuracy: 0.9908000230789185
'Computer Technology 기록부 > 코딩기록부 : Python' 카테고리의 다른 글
DecisionTreeClassifier 이용한 Data classification (0) | 2022.07.05 |
---|---|
LSTM 모델을 이용한 인공지능 작사가 구축 (2) | 2022.07.05 |
[최종] 카메라 스티커 만들기 - 예외처리 포함 (0) | 2022.01.13 |
카메라 스티커 만들기 (0) | 2022.01.11 |
n면 주사위 클래스 함수 만들기 (0) | 2022.01.11 |
댓글