카테고리 없음

텐서플로우를 활용한 모델 구성 및 컴파일 과정

Solbi Lee 2025. 7. 10. 17:56

1. 코드 목적 및 역할 분석

TensorFlow의 Keras API를 사용해 손글씨 숫자 데이터셋(MNIST)에 대한 간단한 신경망 모델을 구성·학습·평가

최종적으로 테스트 결과를 시각화 

데이터 로드정규화모델 정의(Sequential)컴파일학습(fit)평가(evaluate)예측(predict)시각화(show predictions) 의 전 과정을 학습

 

2. 필수 라이브러리 

import tensorflow as tf              # 딥러닝 프레임워크
import matplotlib.pyplot as plt      # 결과 시각화

- TensorFlow: tf.keras API를 통해 모델 구성, 학습, 평가, 예측을 수행

- Matplotlib: 학습 결과(이미지 + 예측값)를 한눈에 볼 수 있도록 배열 형태로 출력

 

3. 주요 기능 개요 

1. MNIST 데이터 로드: tf.keras.datasets.mnist.load_data()

2. 픽셀 정규화: 0–255 범위를 0–1 실수로 스케일링

3. Sequential 모델 구성

- Flatten → Dense(128, relu) → Dense(10, softmax)

4. 모델 컴파일 

- optimizer=adam

- loss=sparse_categorical_crossentropy

- metrics=['accuracy']

5. 모델 학습 : model.fit(..., epochs=5)

6. 모델 평가: model.evaluate(...) → 테스트 정확도 출력

7. 예측: model.predict(X_test) → 각 클래스 확률 벡터 생성

8. 결과 시각화:

- 160개 테스트 이미지를 16×10 그리드로 출력

- 예측이 정답과 일치하면 파란색, 아니면 빨간색 레이블 표시

 

4. 코드 뜯기 

* 데이터 로드 & 정규화 

# 데이터셋
mnist = tf.keras.datasets.mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# 데이터 정규화 (0 ~ 1)
X_train = X_train / 255.0
X_test = X_test / 255.0

- MNIST 데이터셋을 (훈련_이미지, 훈련_레이블), (테스트_이미지, 테스트_레이블) 형태로 불러오기 

- X_train.shape == (60000, 28, 28), y_train.shape == (60000,).

- 픽셀 값(255)을 실수(01)로 스케일링 하여 학습 안정성, 수렴 속도 향상 

 

* 모델 구성 

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

- Flatten: 2D(28×28) → 1D(784)로 변환

- 첫 번째 Dense(128, relu): 완전연결 은닉층, 뉴런 128개, ReLU 활성화

- 두 번째 Dense(10, softmax): 10개 클래스 확률 출력, 합이 1인 분포

 

* 컴파일 

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

- Adam 옵티마이저: 학습률 자동 조정, 모멘텀 적용

- 손실 함수: 정수 레이블(y_train)을 받을 때 sparse_categorical_crossentropy

- 평가지표: accuracy

 

* 학습 

model.fit(X_train, y_train, epochs=5)

# 에포크 5회 반복 학습, 각 에포크마다 훈련 손실(loss)과 정확도(acc) 로그 출력)

Epoch 1/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.8766 - loss: 0.4316
Epoch 2/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9630 - loss: 0.1258
Epoch 3/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9753 - loss: 0.0800
Epoch 4/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9828 - loss: 0.0581
Epoch 5/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9865 - loss: 0.0448
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9673 - loss: 0.1019

 

<학습 결과 해석>

1. 초기 기울기 (1 -> 2Epoch)

- 1회차에서 정확도 88% 손실 0.43 -> 2회차에서 정확도 93% 손실 0.12로 급격히 개선 

- 모델이 MNIST 기본 패턴 (굵기 형태) 학습에 매우 빠르게 적응했음을 의미 

 

2. 수렴 (2 -> 5Epoch)

- 2->3회차 : 정확도 +1.2% 손실 -0.04

- 3-> 5회차 : 정확도 +0.7% 손실 -0.03

에포크가 진행될 수록 기울기가 완만해지는 전형적인 수렴 곡선

 

3. 일반화 성능 

- 훈련 최종 정확도 98.7% 테스트 정확도는 97.2%

- 훈련 대비 테스트 정확도 차이 약 1.5% 과적합 위험 낮음. 일반화 잘 됨. 

 

* 평가 

test_loss, test_acc = model.evaluate(X_test, y_test)
print(f'테스트 정확도 : {test_acc:.4f}') 

--

테스트 정확도 : 0.9723
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step

- 테스트 세트에서 최종 손실과 정확도 계산 

 

* 예측 

predictions = model.predict(X_test)

#predictions.shape == (10000, 10)
# 각 샘플마다 10개 클래스 확률 벡터 반환

 

* 시각화 함수 정의 

def plot_image(i, predictions_array, true_label, img):
    plt.grid(False); plt.xticks([]); plt.yticks([])
    plt.imshow(img, cmap=plt.cm.binary)
    predicted_label = tf.argmax(predictions_array)
    true = true_label[i]
    color = 'blue' if predicted_label==true else 'red'
    plt.xlabel(f'예측:{predicted_label.numpy()}, 정답:{true}', color=color)

- 그리드 눈금 제거 

- tf.argmax로 가장 높은 확률 인덱스(예측 클래스) 추출

- 정답과 비교해 레이블 색상 결정 

 

* 결과 출력 

plt.rc('font', family='Malgun Gothic')
plt.figure(figsize=(16, 12))
for i in range(160):
    plt.subplot(16, 10, i+1)
    plot_image(i, predictions[i], y_test, X_test[i])
plt.tight_layout()
plt.show()