3. 이미지 분류 · 02 mnist keras
mnist keras

손글씨 숫자(0~9)를 가장 기본 신경망으로 분류해보기

무엇을 배울까요?

  • MNIST 데이터를 불러오고(이미지/정답), 학습 가능한 모양으로 바꾸기
  • 가장 기본적인 분류 모델(Dense)을 만들고 학습시키기
  • 학습이 잘 되는지 loss/accuracy 그래프로 확인하기

이해하기 쉬운 예시

  • 손글씨 숫자 사진(0~9)을 보고, 모델이 각 숫자에 점수를 준다고 생각해볼게요. 이 점수들을 softmax로 확률처럼 바꿔서, 결국 '0~9 중 뭐야?'를 고르는 게 분류예요. 이번 단원은 그 분류를 MNIST로 직접 해보는 첫 실습이에요.
01

데이터 준비(MNIST 불러오기 + 라벨 원-핫)

이 섹션에서 하는 일

이 섹션에서는 학습에 쓸 MNIST 데이터를 가져오고, 정답 라벨을 모델이 이해하기 쉬운 모양(원-핫)으로 바꿔요.

코드
from tensorflow.keras import datasets# MNIST 같은 기본 데이터셋을 쉽게 불러오게 해줘요
from tensorflow.keras.utils import to_categorical# 정답(0~9)을 원-핫 벡터로 바꿔줘요
(X_train, y_train), (X_test, y_test) = datasets.mnist.load_data()# 학습/테스트 데이터를 한 번에 받아요
print(y_train[:5])# 정답 라벨이 어떻게 생겼는지 먼저 확인해요
y_train = to_categorical(y_train)# 0~9 숫자를 [0,0,1,0,...] 같은 벡터로 바꿔요
print(y_train[:5])# 바뀐 모양을 확인해요
y_test = to_categorical(y_test)# 테스트 라벨도 똑같이 바꿔줘요
예상 출력
예상 출력(예시)
[5 0 4 1 9]
[[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 ...]
02

이미지 모양 바꾸기(펼치기) + 정규화

이 섹션에서 하는 일

MNIST 이미지는 28x28(2차원)이에요. 여기서는 가장 단순한 신경망(Dense)을 쓸 거라서 784(1차원)로 펼쳐요. 그리고 픽셀값(0~255)을 0~1로 줄여서 학습이 편하게 만들어줘요.

코드
L, W, H = X_train.shape# (데이터개수, 가로, 세로)를 받아요
X_train = X_train.reshape(-1, W * H)# 28x28을 784로 펼쳐서 넣기 쉽게 만들어요
X_test = X_test.reshape(-1, W * H)# 테스트도 똑같이 바꿔줘요
X_train = X_train / 255.0# 픽셀값을 0~1로 줄여서(정규화) 학습을 안정적으로 해줘요
X_test = X_test / 255.0# 테스트도 동일하게 정규화해요
예상 출력
(출력 없음)
03

모델 만들기(Dense 신경망)

이 섹션에서 하는 일

여기서는 가장 기본 형태의 분류 모델을 만들어요.

- 입력: 784개 숫자(픽셀)
- 중간: ReLU 층 3개
- 출력: 10개(0~9) 확률(softmax)

코드
from tensorflow.keras.layers import Input, Dense, Dropout# 신경망 층(레이어) 부품들을 가져와요
from tensorflow.keras.models import Sequential# 층을 차례대로 쌓는 방식이에요
def make_model(input_number, layers, output_number):# 모델 만드는 과정을 함수로 묶어두면 재사용이 쉬워요
model = Sequential()# 빈 모델을 하나 만들어요
model.add(Input(shape=(input_number,)))# 입력 크기(784)를 지정해요
model.add(Dense(layers[0], activation='relu'))# 1번째 은닉층(예: 128개)
model.add(Dense(layers[1], activation='relu'))# 2번째 은닉층(예: 64개)
model.add(Dense(layers[2], activation='relu'))# 3번째 은닉층(예: 32개)
model.add(Dropout(0.2))# 일부를 랜덤으로 꺼서 과적합을 줄여줘요
model.add(Dense(output_number, activation='softmax', name='output'))
# 0~9 확률로 바꾸는 출력층이에요
model.compile(loss='categorical_crossentropy',# 분류 문제에서 자주 쓰는 손실함수예요
optimizer='adam',# 학습을 자동으로 잘 해주는 대표 옵티마이저
metrics=['accuracy'])# 정확도도 같이 보고 싶어서 넣어요
return model# 완성된 모델을 돌려줘요
예상 출력
(출력 없음)
04

학습(fit) + 평가(evaluate) + 그래프

이 섹션에서 하는 일

이 섹션은 실제로 학습을 돌리고 결과를 확인하는 부분이에요.

- fit: 학습(몇 번 반복할지 epochs, 한 번에 몇 개씩 batch_size)
- evaluate: 테스트 데이터로 점수 확인
- plot: 학습이 잘 됐는지 그래프로 보기

코드
input_number = 784# 28x28을 펼치면 784예요
hidden_layers = [128, 64, 32]# 중간층 크기를 정해요
print(hidden_layers)# 설정이 맞는지 한 번 확인해요
number_of_class = 10# 0~9라서 10개 클래스예요
output_number = number_of_class# 출력도 10개로 맞춰요
model = make_model(input_number, hidden_layers, output_number)# 위에서 만든 함수로 모델을 만들어요
hist = model.fit(X_train, y_train, epochs=5, batch_size=128, validation_split=0.2)
# 학습 + 검증을 같이 해요
model.evaluate(X_test, y_test, batch_size=128)# 테스트로 최종 성능을 봐요
import matplotlib.pyplot as plt# 학습 곡선을 그려볼게요
plt.plot(hist.history['loss'])# 학습 loss
plt.plot(hist.history['accuracy'])# 학습 accuracy
plt.plot(hist.history['val_loss'])# 검증 loss
plt.plot(hist.history['val_accuracy'])# 검증 accuracy
plt.legend(['loss', 'accuracy', 'val_loss', 'val_accuracy'])# 라벨 붙이기
plt.show()# 화면에 그래프 보여주기
예상 출력
예상 출력(예시)
[128, 64, 32]
Epoch 1/5 ... (학습 로그가 쭉 출력됨)
... 
테스트 평가 결과가 (loss, accuracy) 형태로 출력됨
plot

핵심 한 줄