반응형

Keras로 구현한 MNIST Image Classification입니다. 



2023. 05. 06  최초작성



import tensorflow as tf
import matplotlib.pyplot as plt


# MNIST 데이터셋을 로드하여 Train 데이터셋은 x_train, y_train에 대입히고 Test 데이터셋은 x_test, y_test에 대입됩니다.
# x_train과 x_test에는 28 x 28 크기의  정사각형 이미지가 저장되어 있으며
# y_train과 y_test에는 28 x 28 크기의 이미지가 나타내는 0 ~ 9 사이의 숫자가 저장되어 있으며 라벨(label)이라고 부릅니다.  
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

print(x_train.shape, y_train.shape)
# 10000개의 28 x 28 크기의 이미지가 x_train에 저장되어 있고 x_train에 있는 이미지에 대응하는 숫자가 y_train에 저장되어 있습니다.
# (10000, 28, 28) (10000,)

print(x_test.shape, y_test.shape)
# 10000개의 28 x 28 크기의 이미지가 x_test에 저장되어 있고 x_test에 있는 이미지에 대응하는 숫자가 y_test에 저장되어 있습니다.
# (10000, 28, 28) (10000,)


# 데이터셋을 학습에 사용하기 전에 이미지를 정규화 해줘야 합니다.
# 이미지는 픽셀로 구성됩니다.  5 x 5 크기의 이미지라면 5 x 5 = 25개의 픽셀로 이미지가 구성됩니다. 
# 본래 이미지를 구성하는 픽셀은 0 ~ 255 사이의 값을 가지지만
# 정규화를 해주면 픽셀은 0 ~ 1 사이의 값을 가지게 됩니다.
x_train, x_test = x_train / 255.0, x_test / 255.0


# 레이어를 사용하여 학습에 사용할 Sequential 모델을 구성합니다.
model = tf.keras.models.Sequential([
 
  # 입력을 1차원 배열로 변환합니다. 배치 크기에는 영향을 주지 않습니다.
  # 28 x 28 크기의 2차원 배열에 저장된 이미지가 28 * 28 = 784 크기의 1차원 배열이 됩니다. 
  tf.keras.layers.Flatten(input_shape=(28, 28)),

  # 뉴런 64개로 구성된 Dense 레이어입니다. 활성화 함수로 relu를 사용합니다. 
  tf.keras.layers.Dense(64, activation='relu'),

  # 뉴런 32개로 구성된 Dense 레이어입니다. 활성화 함수로 relu를 사용합니다. 
  tf.keras.layers.Dense(32, activation='relu'),

  # 뉴런 16개로 구성된 Dense 레이어입니다. 활성화 함수로 relu를 사용합니다. 
  tf.keras.layers.Dense(16, activation='relu'),

  # 뉴런 10개로 구성된 Dense 레이어입니다. 활성화 함수로 softmax를 사용합니다.
  # softmax는 출력의 합이 1이 되도록 출력값을 조정해줍니다.
  tf.keras.layers.Dense(10, activation='softmax')
])


# 옵티마이저로 adam, 손실함수로 sparse categorocal crossentropy, 성능 측정 단위로 accuracy를 지정합니다.
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])


# Train 데이터셋을 구성하는 이미지가 저장된 x_train과 이미지에 대응되는 라벨이 저장된 y_train을 사용하여 학습을 진행합니다.
# epochs에 지정된 횟수 만큼 전체 train 데이터셋을 학습에 사용합니다.
# validation_split에 지정한 수치만큼 전체 train 데이터셋의 일부를 validation 데이터셋으로 사용합니다.
# 학습에는 train 데이터셋만 사용하고 validation 데이터셋은 모델의 하이퍼파라미터를 튜닝하기 위해 사용됩니다.
# 또한 validation 데이터셋은 오버피팅(over fittinng)이 발생했는지 판단하기 위해서도 사용되며 early stopping으로 학습을 종료시킬때에도 사용됩니다.
# 전체 train 데이터셋이 학습에 사용되는 1 epoch마다 validation 데이터셋을 사용하여 모델의 성능을 평가하여 accuracy와 loss를 출력합니다.      
history = model.fit(x_train, y_train, epochs=10, validation_split=0.1)


# 4개의 그래프를 loss와 accuracy로 구분하여 그려줍니다.
fig, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].plot(history.history["loss"], label="Training Loss")
axs[0].plot(history.history["val_loss"], label="Validation Loss")
axs[0].legend()
axs[1].plot(history.history["accuracy"], label="Training Accuracy")
axs[1].plot(history.history["val_accuracy"], label="Validation Accuracy")
axs[1].legend()
plt.suptitle("mnist")
plt.show()



(60000, 28, 28) (60000,)

(10000, 28, 28) (10000,)

Epoch 1/10

   1/1688 [..............................] - ETA: 10:39 - loss: 2.4328 - accuracy: 0.1562

2023-05-05 07:12:30.543291: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - ETA: 0s - loss: 0.3581 - accuracy: 0.8933

2023-05-05 07:12:46.093243: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - 17s 10ms/step - loss: 0.3581 - accuracy: 0.8933 - val_loss: 0.1370 - val_accuracy: 0.9593

Epoch 2/10

1688/1688 [==============================] - 16s 10ms/step - loss: 0.1411 - accuracy: 0.9584 - val_loss: 0.1079 - val_accuracy: 0.9695

Epoch 3/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1015 - accuracy: 0.9690 - val_loss: 0.0977 - val_accuracy: 0.9713

Epoch 4/10

1688/1688 [==============================] - 15s 9ms/step - loss: 0.0814 - accuracy: 0.9747 - val_loss: 0.0843 - val_accuracy: 0.9745

Epoch 5/10

1688/1688 [==============================] - 15s 9ms/step - loss: 0.0648 - accuracy: 0.9794 - val_loss: 0.0838 - val_accuracy: 0.9738

Epoch 6/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.0562 - accuracy: 0.9825 - val_loss: 0.0857 - val_accuracy: 0.9740

Epoch 7/10

1688/1688 [==============================] - 15s 9ms/step - loss: 0.0475 - accuracy: 0.9846 - val_loss: 0.0866 - val_accuracy: 0.9720

Epoch 8/10

1688/1688 [==============================] - 15s 9ms/step - loss: 0.0412 - accuracy: 0.9868 - val_loss: 0.0929 - val_accuracy: 0.9752

Epoch 9/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.0361 - accuracy: 0.9884 - val_loss: 0.0907 - val_accuracy: 0.9735

Epoch 10/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.0318 - accuracy: 0.9896 - val_loss: 0.1082 - val_accuracy: 0.9720

 



그래프에서 X축은 학습하는 동안 데이터셋을 본 epoch 횟수이며 Y축은 그래프별로 각각 loss와 accuracy입니다. 

학습을 진행함에 따라 Train Loss 보다 Validation Loss가 커지고, Train Accuracy보다 Validation Accuracy가 낮기때문에 오버 피팅(Over Fitting)이 발생한 상황입니다.

 

오버 피팅이 발생하면 학습에 사용한 데이터셋에서는 좋은 성능을 보여주더라도 학습에 사용한적 없는 새로운 데이터셋에서는 성능이 떨어지게 됩니다. 





오버 피팅을 해결하는 여러 방법 중 Dropout을 사용해봅니다. Dropout 레이어를 모델에 추가해주면 됩니다. 

import tensorflow as tf
import matplotlib.pyplot as plt


(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(64, activation='relu'),
  tf.keras.layers.Dense(32, activation='relu'),
  tf.keras.layers.Dense(16, activation='relu'),
 
  # 이전 레이어에 포함된 레이어의 출력중 무작위로 선택된 50%의 뉴런의 출력만 다음 레이어의 입력으로 사용하도록 합니다.
  # Dropout에서 사용하는 수치는 상황에 따라 적절한 값을 선택하여 사용해야 합니다.
  tf.keras.layers.Dropout(0.5),
 
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

   
history = model.fit(x_train, y_train, epochs=10, validation_split=0.1)

fig, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].plot(history.history["loss"], label="Training Loss")
axs[0].plot(history.history["val_loss"], label="Validation Loss")
axs[0].legend()
axs[1].plot(history.history["accuracy"], label="Training Accuracy")
axs[1].plot(history.history["val_accuracy"], label="Validation Accuracy")
axs[1].legend()
plt.suptitle("mnist")
plt.show()



Epoch 1/10

   1/1688 [..............................] - ETA: 11:31 - loss: 2.3869 - accuracy: 0.1250

2023-05-05 07:15:07.574813: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - ETA: 0s - loss: 0.8291 - accuracy: 0.7180

2023-05-05 07:15:22.702274: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - 16s 9ms/step - loss: 0.8291 - accuracy: 0.7180 - val_loss: 0.1790 - val_accuracy: 0.9560

Epoch 2/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.4879 - accuracy: 0.8429 - val_loss: 0.1511 - val_accuracy: 0.9603

Epoch 3/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.4101 - accuracy: 0.8740 - val_loss: 0.1274 - val_accuracy: 0.9685

Epoch 4/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3582 - accuracy: 0.8903 - val_loss: 0.1260 - val_accuracy: 0.9688

Epoch 5/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3260 - accuracy: 0.8994 - val_loss: 0.1239 - val_accuracy: 0.9722

Epoch 6/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2943 - accuracy: 0.9096 - val_loss: 0.1184 - val_accuracy: 0.9687

Epoch 7/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2703 - accuracy: 0.9162 - val_loss: 0.1131 - val_accuracy: 0.9718

Epoch 8/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2520 - accuracy: 0.9229 - val_loss: 0.1209 - val_accuracy: 0.9757

Epoch 9/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2427 - accuracy: 0.9257 - val_loss: 0.1394 - val_accuracy: 0.9715

Epoch 10/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2317 - accuracy: 0.9283 - val_loss: 0.1302 - val_accuracy: 0.9727



그래프를 보면 Train Loss보다 Validation Loss가 더 낮은 값을 갖게되었고 Train Accuracy보다 Validation Accuracy가 높은 값을 갖게 되었습니다. 

오버피팅이 해결된 것으로 볼 수 있습니다. 




이제 학습에 사용하지 않은 Test 데이터셋을 사용하여 모델 성능을 평가해 봅니다. 

import tensorflow as tf
import matplotlib.pyplot as plt

# 모델 성능 평가를 위해 추가로 사용되는 모듈들입니다.
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# 넘파이 배열에서 최대값의 인덱스를 찾기 위해 사용되는 모듈입니다. 
import numpy as np

# 혼동 행렬(confusion matrix)을 출력하기 위해 사용됩니다.
import seaborn as sns


(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(64, activation='relu'),
  tf.keras.layers.Dense(32, activation='relu'),
  tf.keras.layers.Dense(16, activation='relu'),
  tf.keras.layers.Dropout(0.5),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

   
history = model.fit(x_train, y_train, epochs=10, validation_split=0.1)


fig, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].plot(history.history["loss"], label="Training Loss")
axs[0].plot(history.history["val_loss"], label="Validation Loss")
axs[0].legend()
axs[1].plot(history.history["accuracy"], label="Training Accuracy")
axs[1].plot(history.history["val_accuracy"], label="Validation Accuracy")
axs[1].legend()
plt.suptitle("mnist")
plt.show()


# 학습이 완료된 모델에 입력으로 x_test 데이터셋을 사용하여 추론된 결과가 pred_y에 저장됩니다.
pred_y = model.predict(x_test)

# pred_y는 추론된 10개의 값을 갖습니다. 10개의 값은 이미지가 0 ~ 9 숫자일 확률로 이중 가장 높은 값을 선택해야 합니다.
# 선택된 가장 높은 값이 이미지로부터 추론된 숫자로 사용됩니다.
# argmax 함수를 사용하여 10개의 값중 가장 높은 값의 인덱스를 얻게 됩니다. 인덱스가 이미지가 의미하는 숫자를 나타냅니다.
pred_y = np.argmax(pred_y, axis=1)

# Test 데이터셋의 라벨인 y_test와 Test 데이터셋의 이미지인 x_test의 추론 결과인 pred_y를 사용하여 정확도(Accuracy)를 계산합니다.
# 정확도는 전체 정답 중 몇개를 맞추었는지를 의미합니다.
accuracy = accuracy_score(y_test, pred_y)
print("Accuracy: {}".format(accuracy))


# 분류관련 측정 지표를 출력해줍니다.
print(classification_report(y_test, pred_y))


# 혼동 행렬을 계산하여 seaborn 모듈을 사용하여 화면에 출력합니다.
confusion_mtx = confusion_matrix(y_test, pred_y)

fig, ax = plt.subplots(figsize=(15,10))
ax = sns.heatmap(confusion_mtx, annot=True, fmt='d', ax=ax, cmap="Purples")
ax.set_xlabel('Predicted Label')
ax.set_ylabel('True Label')
ax.set_title('Confusion Matrix')




Epoch 1/10

   1/1688 [..............................] - ETA: 11:39 - loss: 2.3188 - accuracy: 0.2188

2023-05-05 07:17:46.307056: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - ETA: 0s - loss: 0.8332 - accuracy: 0.7176

2023-05-05 07:18:01.547353: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - 16s 9ms/step - loss: 0.8332 - accuracy: 0.7176 - val_loss: 0.1919 - val_accuracy: 0.9545

Epoch 2/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.4598 - accuracy: 0.8584 - val_loss: 0.1401 - val_accuracy: 0.9638

Epoch 3/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3657 - accuracy: 0.8924 - val_loss: 0.1252 - val_accuracy: 0.9683

Epoch 4/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3040 - accuracy: 0.9139 - val_loss: 0.1240 - val_accuracy: 0.9700

Epoch 5/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2618 - accuracy: 0.9316 - val_loss: 0.1144 - val_accuracy: 0.9728

Epoch 6/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2235 - accuracy: 0.9430 - val_loss: 0.1098 - val_accuracy: 0.9708

Epoch 7/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1951 - accuracy: 0.9515 - val_loss: 0.1210 - val_accuracy: 0.9713

Epoch 8/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1725 - accuracy: 0.9569 - val_loss: 0.1243 - val_accuracy: 0.9705

Epoch 9/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1552 - accuracy: 0.9609 - val_loss: 0.1192 - val_accuracy: 0.9722

Epoch 10/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1437 - accuracy: 0.9632 - val_loss: 0.1571 - val_accuracy: 0.9693




 

2023-05-05 07:20:24.007914: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

Accuracy: 0.9671

              precision    recall  f1-score   support

 

           0       0.98      0.99      0.98       980

           1       0.99      0.99      0.99      1135

           2       0.97      0.97      0.97      1032

           3       0.93      0.98      0.96      1010

           4       0.98      0.96      0.97       982

           5       0.98      0.95      0.96       892

           6       0.98      0.96      0.97       958

           7       0.95      0.98      0.97      1028

           8       0.98      0.93      0.95       974

           9       0.95      0.96      0.95      1009

 

    accuracy                           0.97     10000

   macro avg       0.97      0.97      0.97     10000

weighted avg       0.97      0.97      0.97     10000

 

Text(0.5, 1.0, 'Confusion Matrix')



세로축이 실제 값이며 가로축이 추론된 값입니다. 실제 어떤 값이었는데 어떻게 추론했는지를 보여줍니다. 두 값이 같은 지점이 중앙에 보이는 대각선에 있는 값들입니다. 




케라스 코드를 실행할 때 마다 똑같은 성능 결과를 보여줘야 모델이나 데이터셋 변경시 이전과 비교가 가능합니다.

여기서 부턴 성능 평가 출력 중, Accuracy만 남겨두고 나머진 생략합니다.

import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.python.keras.callbacks import EarlyStopping, ReduceLROnPlateau
from sklearn.metrics import accuracy_score
import numpy as np

import random


# 항상 같은 성능 결과를 얻기위해 재현 가능한 결과(reproducible results)를 얻기위해 추가된 코드입니다.
tf.keras.utils.set_random_seed(1)
tf.config.experimental.enable_op_determinism()
np.random.seed(123)
random.seed(123)
tf.random.set_seed(1234)


(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(64, activation='relu'),
  tf.keras.layers.Dense(32, activation='relu'),
  tf.keras.layers.Dense(16, activation='relu'),
  tf.keras.layers.Dropout(0.5),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

   
history = model.fit(x_train, y_train, epochs=10, validation_split=0.1)


fig, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].plot(history.history["loss"], label="Training Loss")
axs[0].plot(history.history["val_loss"], label="Validation Loss")
axs[0].legend()
axs[1].plot(history.history["accuracy"], label="Training Accuracy")
axs[1].plot(history.history["val_accuracy"], label="Validation Accuracy")
axs[1].legend()
plt.suptitle("mnist")
plt.show()

pred_y = model.predict(x_test)

pred_y = np.argmax(pred_y, axis=1)
accuracy = accuracy_score(y_test, pred_y)
print("Accuracy: {}".format(accuracy))



Epoch 1/10

   1/1688 [..............................] - ETA: 11:35 - loss: 2.3527 - accuracy: 0.0938

2023-05-05 07:20:25.592955: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - ETA: 0s - loss: 0.8300 - accuracy: 0.7259

2023-05-05 07:20:40.729446: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - 16s 9ms/step - loss: 0.8300 - accuracy: 0.7259 - val_loss: 0.1797 - val_accuracy: 0.9497

Epoch 2/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.4655 - accuracy: 0.8641 - val_loss: 0.1341 - val_accuracy: 0.9637

Epoch 3/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3794 - accuracy: 0.8911 - val_loss: 0.1215 - val_accuracy: 0.9672

Epoch 4/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3225 - accuracy: 0.9093 - val_loss: 0.1150 - val_accuracy: 0.9708

Epoch 5/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2804 - accuracy: 0.9211 - val_loss: 0.1178 - val_accuracy: 0.9718

Epoch 6/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2573 - accuracy: 0.9286 - val_loss: 0.1154 - val_accuracy: 0.9708

Epoch 7/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2320 - accuracy: 0.9367 - val_loss: 0.1153 - val_accuracy: 0.9745

Epoch 8/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2111 - accuracy: 0.9424 - val_loss: 0.1257 - val_accuracy: 0.9740

Epoch 9/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1947 - accuracy: 0.9467 - val_loss: 0.1321 - val_accuracy: 0.9723

Epoch 10/10

1688/1688 [==============================] - 16s 9ms/step - loss: 0.1863 - accuracy: 0.9507 - val_loss: 0.1262 - val_accuracy: 0.9748

 



2023-05-05 07:23:02.314244: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

Accuracy: 0.9702




epoch를 100으로 늘리고 콜백함수 사용합니다. ReduceLROnPlateau는 지정한 val_loss가 낮아지지 않으면 학습률을 지정한 비율로  낮춥니다.  EarlyStopping는 지정한 val_loss가 낮아지지 않으면 학습을 중단합니다. 오버퍼팅을 방지하는 효과를 볼 수 있습니다. 

import tensorflow as tf
# 추가된 모듈입니다.
from tensorflow.python.keras.callbacks import EarlyStopping, ReduceLROnPlateau
from sklearn.metrics import accuracy_score
import numpy as np
import random
import matplotlib.pyplot as plt


tf.keras.utils.set_random_seed(1)
tf.config.experimental.enable_op_determinism()
np.random.seed(123)
random.seed(123)
tf.random.set_seed(1234)


(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(64, activation='relu'),
  tf.keras.layers.Dense(32, activation='relu'),
  tf.keras.layers.Dense(16, activation='relu'),
  tf.keras.layers.Dropout(0.5),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])


# 학습률을 조정합니다.val_loss가 0.001만큼 감소하는게 2번이상이면 학습률을 0.5% 작게 조정합니다.
reduce_lr = ReduceLROnPlateau(monitor='val_loss', mode="min", factor=0.5, patience=2, min_delta=0.001

# 조기 종료하여 오버피팅을 방지합니다. val_loss가 0.001만큼 감소하는게 10번 이상이면 학습을 중단하고 가장 좋았던 가중치로 바꿔줍니다.
early_stop= EarlyStopping(monitor = "val_loss", mode="min", min_delta=0.001, restore_best_weights=True,
                            patience=10, verbose=1)
   
history = model.fit(x_train, y_train, epochs=100, validation_split=0.1, callbacks = [early_stop, reduce_lr])


fig, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].plot(history.history["loss"], label="Training Loss")
axs[0].plot(history.history["val_loss"], label="Validation Loss")
axs[0].legend()
axs[1].plot(history.history["accuracy"], label="Training Accuracy")
axs[1].plot(history.history["val_accuracy"], label="Validation Accuracy")
axs[1].legend()
plt.suptitle("mnist")
plt.show()

pred_y = model.predict(x_test)

pred_y = np.argmax(pred_y, axis=1)
accuracy = accuracy_score(y_test, pred_y)
print("Accuracy: {}".format(accuracy))



Epoch 1/100

   1/1688 [..............................] - ETA: 11:31 - loss: 2.3527 - accuracy: 0.0938

2023-05-05 07:23:03.666447: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - ETA: 0s - loss: 0.8299 - accuracy: 0.7260

2023-05-05 07:23:18.994470: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

1688/1688 [==============================] - 16s 10ms/step - loss: 0.8299 - accuracy: 0.7260 - val_loss: 0.1791 - val_accuracy: 0.9502 - lr: 0.0010

Epoch 2/100

1688/1688 [==============================] - 16s 9ms/step - loss: 0.4651 - accuracy: 0.8637 - val_loss: 0.1368 - val_accuracy: 0.9627 - lr: 0.0010

Epoch 3/100

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3777 - accuracy: 0.8916 - val_loss: 0.1251 - val_accuracy: 0.9658 - lr: 0.0010

Epoch 4/100

1688/1688 [==============================] - 16s 9ms/step - loss: 0.3212 - accuracy: 0.9101 - val_loss: 0.1177 - val_accuracy: 0.9695 - lr: 0.0010

Epoch 5/100

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2811 - accuracy: 0.9206 - val_loss: 0.1184 - val_accuracy: 0.9715 - lr: 0.0010

Epoch 6/100

1688/1688 [==============================] - 1008s 598ms/step - loss: 0.2573 - accuracy: 0.9297 - val_loss: 0.1245 - val_accuracy: 0.9700 - lr: 0.0010

Epoch 7/100

1688/1688 [==============================] - 16s 9ms/step - loss: 0.2154 - accuracy: 0.9414 - val_loss: 0.1130 - val_accuracy: 0.9753 - lr: 5.0000e-04

Epoch 8/100

1688/1688 [==============================] - 15s 9ms/step - loss: 0.1944 - accuracy: 0.9466 - val_loss: 0.1134 - val_accuracy: 0.9748 - lr: 5.0000e-04

Epoch 9/100

1688/1688 [==============================] - 163s 97ms/step - loss: 0.1827 - accuracy: 0.9494 - val_loss: 0.1095 - val_accuracy: 0.9767 - lr: 5.0000e-04

Epoch 10/100

1688/1688 [==============================] - 15s 9ms/step - loss: 0.1796 - accuracy: 0.9497 - val_loss: 0.1122 - val_accuracy: 0.9750 - lr: 5.0000e-04

Epoch 11/100

1688/1688 [==============================] - 15s 9ms/step - loss: 0.1706 - accuracy: 0.9522 - val_loss: 0.1101 - val_accuracy: 0.9777 - lr: 5.0000e-04

Epoch 12/100

1688/1688 [==============================] - 894s 530ms/step - loss: 0.1480 - accuracy: 0.9582 - val_loss: 0.1143 - val_accuracy: 0.9782 - lr: 2.5000e-04

Epoch 13/100

1688/1688 [==============================] - 17s 10ms/step - loss: 0.1411 - accuracy: 0.9606 - val_loss: 0.1111 - val_accuracy: 0.9787 - lr: 2.5000e-04

...

Epoch 19/100

1685/1688 [============================>.] - ETA: 0s - loss: 0.1190 - accuracy: 0.9671Restoring model weights from the end of the best epoch.

1688/1688 [==============================] - 16s 10ms/step - loss: 0.1190 - accuracy: 0.9671 - val_loss: 0.1199 - val_accuracy: 0.9793 - lr: 3.1250e-05

Epoch 00019: early stopping

Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

 

이전보다 더 많은 에포크동안 학습이 진행된것을 볼 수 있습니다.



2023-05-05 08:01:47.716604: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.

Accuracy: 0.9721




반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts