ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TensorFlow] 파이썬을 이용한 MNIST 분류 모델 만들기
    Python/딥러닝 2024. 7. 29. 17:43
    반응형

    텐서플로우를 이용한 MNIST 분류 모델 만들기


    파이썬(Python)에서 이용할 수 있는 대표적인 딥러닝 플랫폼인 텐서플로우(TensorFlow)를 활용해, MNIST 데이터를 분류할 수 있는 딥러닝(Deep Learning) 모델을 만들어 보는 실습을 진행해 보겠습니다. 분류에 이용할 데이터는 MNIST 데이터셋인데요, 28*28px 크기의 흑백 이미지에 0에서 9까지의 숫자가 기록되어 있지요. 해당 데이터는 텐서플로우에서 기본 제공을 해 주기 때문에, tensorflow.keras.datasets.mnist.load_data() 함수를 이용해 불러올 수 있습니다.

     

     

    데이터 전처리


    불러온 MNIST 데이터는 x_train, x_test, y_train, y_test로 분류되는데요, 각각의 데이터는 아래와 같은 형태와 특징이 있습니다.

     

    • x_train: numpy array 타입의 이미지 데이터. 6만개의 샘플, 각각의 샘플은 28*28 크기를 가지고 각 값의 범위는 0~255 사이입니다.
    • x_test: numpy array 타입의 이미지 데이터. 1만개의 샘플, 각각의 샘플은 28*28 크기를 가지고 각 값의 범위는 0~255 사이입니다.
    • y_train: numpy array 타입의 1차원 배열. 6만개의 샘플, 각각의 샘플은 0~9 범위의 정수로 표현됩니다.
    • y_test: numpy array 타입의 1차원 배열. 1만개의 샘플, 각각의 샘플은 0~9 범위의 정수로 표현됩니다.

     

    데이터를 불러온 뒤에는, x 데이터를 255로 나누어 줍니다. 이 때, x 데이터는 0~1 사이의 실수로 제한됩니다. 이렇게 범위를 제한하는 이유는, 기울기 소실과 폭주 (Gradient Vanishing & Exploding) 문제를 해결하고, 모델의 훈련 속도를 빠르게 하기 위해서입니다.

     

     

    # Import Package and Data
    import tensorflow as tf
    
    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train, x_test = x_train / 255.0, x_test / 255.0

     

     

    모델 생성


    이제, 저희는 MNIST 데이터를 활용해, 0~9 사이의 숫자가 적힌 이미지를 입력하면 어떤 숫자를 적은 이미지인지 맞출 수 있는 모델을 생성해 보려 합니다. 이 경우, 다중 클래스 분류 모델이 가장 합리적인 선택이지요. 이 모델은 입력층, 은닉층, 출력층을 차례대로 쌓아가는 방식의 tensorflow.keras.models.Sequential 클래스를 활용해 쉽게 생성할 수 있습니다.

     

    이번에 만드는 모델의 경우, 우선 입력층의 구조는 28*28 크기의 데이터를 받을 수 있는 입력층을 만들어 줘야 합니다. 이 때, 입력된 데이터를 1차원으로 변형해 주는 tensorflow.keras.layers.Flatten 클래스를 활용하지요. 이 때, input_shapex_train의 shape와 똑같이 설정해 주어야 합니다.


    다음으로는 은닉층을 생성하는데, 이 때는 tensorflow.keras.layers.Dense 클래스를 활용합니다. Dense 레이어는 입출력 레이어를 연결해 주는 역할을 하며, 입력 크기는 이전 레이어의 출력 크기와 같이, 출력 크기는 다음 레이어의 입력 크기와 같이 설정해 주시면 됩니다. 여기에서는 출력 크기를 128로 만들어 줬습니다. 그리고, 활성함수는 많은 모델에서 범용적으로 이용하는 relu를 선택했습니다.


    그 다음에는 tensorflow.keras.layers.Dropout 클래스를 이용해서 Dropout 레이어를 만들어 줍니다. 이 레이어는 딥러닝 모델을 무작위 일정 비율만큼 비활성화하는 역할을 합니다. 이 때, 정규화(Regularization)와 같은 효과가 일어나기 때문에, 과적합(overfitting) 문제를 손쉽게 해결할 수 있습니다. 드롭아웃 레이어의 설정은, 0~1 사이의 실수를 입력하면 되는데, 비활성화시킬 비율만큼을 입력하면 됩니다. 여기서는 20%에 해당하는 0.2를 입력해 주었습니다.


    마지막으로 추가하는 출력층은 Dense 레이어를 이용합니다. 원하는 분류 클래스의 개수에 따라 출력 형태를 입력해 주는데, 여기서는 0~9의 10개 클래스 분류이기 때문에 10을 입력해 줍니다. 다중 클래스 분류 모델의 경우, 출력층에서는 활성함수를 주로 softmax를 이용하는 편입니다.

     

     

    다음으로는 모델의 학습 과정을 설정하는 컴파일 작업이 진행됩니다. 이 때는 옵티마이저(optimizer), 손실함수(loss function), 평가 지표(metrics)를 설정하는데, 각각 아래와 같은 이유에서 사용하게 됩니다.

     

    • optimizer: 모델의 가중치를 업데이트할 때, 어떻게 손실을 최소화할지에 대해 계산하는 역할을 합니다. adam이 범용적으로 사용되나, 목적에 따라서 다른 함수를 이용하는 경우도 많습니다.
    • loss: 딥러닝 모델의 예측 값과 실제 값 사이의 오차를 측정하는 기준이 되는 함수입니다. 다중 분류의 경우, 주로 sparse_categorical_crossentropy를 이용합니다.
    • metrics: 학습된 모델의 평가 지표를 설정합니다. 분류 작업의 경우, 정확도 지표인 accuracy를 이용합니다.

     

     

    model = tf.keras.models.Sequential([
      tf.keras.layers.Flatten(input_shape=(28, 28)),
      tf.keras.layers.Dense(128, activation='relu'),
      tf.keras.layers.Dropout(0.2),
      tf.keras.layers.Dense(10, activation='softmax')
    ])
    
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

     

    # 값 예측
    predictions = model(x_train[0:1]).numpy()
    predictions
    array([[0.15522064, 0.13845733, 0.03556472, 0.114774  , 0.10561258,
            0.06301416, 0.09854259, 0.15010136, 0.06135726, 0.07735529]],
          dtype=float32)

     

    # 각 클래스별로 정답일 확률을 계산
    tf.nn.softmax(predictions).numpy()
    array([[0.10559919, 0.10384376, 0.09369032, 0.10141329, 0.10048844,
            0.09629769, 0.09978049, 0.10505998, 0.09613826, 0.09768865]],
          dtype=float32)

     

    # 손실값 계산
    # 손실값의 경우, 0 이상의 실수로 표현됨. 0에 가까울수록 좋은 결과
    loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
    loss_fn(y_train[:1], predictions).numpy()
    2.340311

     

     

    모델 학습 및 검증


    모델의 구성이 끝난 뒤에는, model.fit 함수를 이용해 학습을 진행합니다. 이 때, fit 함수에는 x_train, y_train, epochs 값을 입력합니다. epochs는 전체 데이터를 사용한 학습 과정을 몇 번 수행할 것인가를 정수로 입력하게 됩니다. 너무 높을 경우에는 과적합의 위험이, 너무 낮을 경우에는 과소적합(Underfitting)의 위험이 있습니다. 어느 정도의 값이 적당한지는 데이터와 모델의 형태에 따라 다르게 나타나기 때문에, 학습 결과를 확인해서 적절하게 조절해 주어야 합니다. 여기서는 적당히 10으로 설정해 두었습니다.

     

    모델의 검증은 model.evaluate 함수를 이용하며, 여기에는 x_test, y_test를 입력합니다. 학습 과정에서 사용되지 않은 데이터를 입력했을 때, 모델이 얼마나 정확하게 예측, 분류하는지 평가하는 과정이며, 이 함수는 loss와 accuracy를 반환해 줍니다.

     


    만약 미지의 데이터를 입력한 뒤, 이 데이터가 어떤 클래스인지 확인하는 과정을 수행하고 싶다면 model.predict 함수를 이용하면 됩니다. 이번에 만든 모델의 경우, 10개의 클래스를 분류하는 모델이기 때문에 각각의 클래스별로 해당 클래스일 확률(predict proba)를 반환해 줍니다.

     

     

    model.fit(x_train, y_train, epochs=10)
    Epoch 1/10
    1875/1875 [==============================] - 5s 2ms/step - loss: 0.2975 - accuracy: 0.9137
    Epoch 2/10
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.1468 - accuracy: 0.9569
    Epoch 3/10
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.1093 - accuracy: 0.9674
    Epoch 4/10
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.0876 - accuracy: 0.9729
    Epoch 5/10
    1875/1875 [==============================] - 3s 2ms/step - loss: 0.0751 - accuracy: 0.9761
    Epoch 6/10
    1875/1875 [==============================] - 5s 2ms/step - loss: 0.0666 - accuracy: 0.9783
    Epoch 7/10
    1875/1875 [==============================] - 5s 3ms/step - loss: 0.0591 - accuracy: 0.9813
    Epoch 8/10
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.0524 - accuracy: 0.9833
    Epoch 9/10
    1875/1875 [==============================] - 5s 3ms/step - loss: 0.0492 - accuracy: 0.9839
    Epoch 10/10
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.0431 - accuracy: 0.9859
    
    
    
    
    
    <keras.src.callbacks.History at 0x1c989084fd0>

     

    model.evaluate(x_test, y_test)
    313/313 [==============================] - 1s 1ms/step - loss: 0.0731 - accuracy: 0.9803
    
    
    
    
    
    [0.07312066853046417, 0.9803000092506409]

     

    model.predict(x_train[19:20])
    1/1 [==============================] - 0s 71ms/step
    
    
    
    
    
    array([[1.0951435e-08, 6.6231119e-06, 1.3379996e-09, 3.1919670e-04,
            1.9712163e-05, 1.4836489e-05, 8.2480073e-13, 8.1592950e-04,
            5.0377807e-06, 9.9881870e-01]], dtype=float32)
    반응형

    댓글

문의: jwkang3929@naver.com