TensorFlow / Keras — 딥러닝 모델 만들기

Sequential API로 신경망을 설계하고 MNIST 손글씨 인식 모델을 직접 학습하며 Dropout, EarlyStopping으로 과적합을 막는 법까지 정리

2026.04.10

TensorFlowKerasdeep learningSequentialDenseDropoutEarlyStoppingMNISTneural network

0. 시리즈

제목역할
1편NumPy 완벽 정리 — 숫자 배열 다루기데이터 기초
2편Pandas 완벽 정리 — 데이터 불러오고 정리하기데이터 전처리
3편Matplotlib / Seaborn — 데이터 시각화시각화
4편Scikit-learn — 머신러닝 실습 입문ML 실습
5편⬅️TensorFlow / Keras — 딥러닝 모델 만들기DL 실습
6편PyTorch 입문 — Keras와 무엇이 다를까?DL 심화

1. TensorFlow와 Keras란?

1-1. TensorFlow란?

TensorFlow(텐서플로우) 는 구글이 2015년에 공개한 딥러닝 연산 엔진입니다. 이름의 Tensor 는 다차원 배열(1편에서 배운 NumPy 배열과 같은 개념), Flow 는 데이터가 연산 그래프를 따라 흘러간다는 뜻입니다.

쉽게 말해 "딥러닝 모델 안에서 일어나는 수백만 번의 수학 계산을 빠르게 처리해주는 엔진" 입니다.

1-2. Keras란?

Keras(케라스) 는 TensorFlow 위에서 동작하는 고수준 인터페이스 입니다. TensorFlow 2.0부터는 tf.keras로 TensorFlow 안에 완전히 통합되었습니다.

TensorFlow로 모델을 직접 구현하면 수십 줄이 필요한 코드를, Keras는 몇 줄로 줄여줍니다.

1-3. TensorFlow vs Keras 관계

TensorFlow  =  자동차 엔진  (강력하지만 직접 다루기 복잡함)
Keras       =  핸들과 페달  (누구나 쉽게 조작할 수 있는 인터페이스)

우리는 핸들(Keras)을 잡고 운전하면 됩니다. 엔진(TensorFlow)은 내부에서 알아서 돌아갑니다.

1-4. PyTorch와 무엇이 다른가?

비교 항목TensorFlow/KerasPyTorch
개발사GoogleMeta(Facebook)
난이도쉬움 (입문자 추천)비교적 어려움
주요 사용처산업·서비스 배포연구·논문 구현
사용자층실무 개발자AI 연구자

PyTorch는 다음 편(6편)에서 다룹니다.

1-5. 설치 및 임포트

bashpip install tensorflow
pythonimport tensorflow as tf
print(tf.__version__)  # 예: 2.15.0

from tensorflow import keras
from tensorflow.keras import layers

Google Colab은 이미 설치되어 있어 별도 설치 불필요합니다.


2. 딥러닝 기본 개념 복습

2-1. 뉴런과 레이어 한 줄 요약

입력층 (Input Layer)   → 데이터를 받아들이는 문
은닉층 (Hidden Layer)  → 패턴을 찾아내는 중간 처리 단계
출력층 (Output Layer)  → 최종 결과를 내보내는 문

각 층은 뉴런(노드) 들로 구성되고, 뉴런끼리 가중치(weight) 로 연결됩니다. 학습이란 이 가중치를 조금씩 조정해 정답에 가까워지는 과정입니다.

2-2. Scikit-learn(4편)과 무엇이 다른가?

비교 항목Scikit-learnTensorFlow/Keras
방식전통 머신러닝딥러닝 (신경망)
데이터 크기소~중형대형
특징 추출사람이 직접모델이 자동으로
학습 시간빠름느림 (GPU 권장)
주요 용도정형 데이터이미지, 텍스트, 음성

2-3. 딥러닝이 유리한 상황

  • 이미지, 텍스트, 음성처럼 비정형 데이터 를 다룰 때
  • 데이터가 수만 건 이상 으로 충분히 많을 때
  • 정확도가 최우선이고 학습 시간을 감수할 수 있을 때

반대로 데이터가 적거나 표 형태의 정형 데이터라면 Scikit-learn이 더 빠르고 효율적입니다.


3. Keras로 모델 만드는 방법

3-1. Sequential API

레이어를 순서대로 쌓아 모델을 만드는 방식입니다. 가장 기본적이고 직관적인 방법입니다.

pythonfrom tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Dropout

model = Sequential([
    Dense(128, activation="relu", input_shape=(4,)),  # 입력층 + 첫 번째 은닉층
    Dense(64, activation="relu"),                      # 두 번째 은닉층
    Dense(3, activation="softmax")                     # 출력층 (클래스 3개)
])

3-2. 주요 레이어 종류

레이어역할주로 쓰는 곳
Dense완전 연결층 — 모든 뉴런이 연결기본 분류·회귀
Dropout뉴런 일부를 랜덤으로 꺼서 과적합 방지모든 모델
Flatten다차원 배열을 1차원으로 펼침이미지 → Dense 연결 시
Conv2D이미지의 특징을 추출하는 합성곱층이미지 분류
LSTM순서가 있는 데이터 처리텍스트, 시계열

3-3. 활성화 함수

뉴런의 출력 값을 어떻게 변환할지 결정합니다.

python# ReLU — 은닉층에서 가장 많이 쓰임
Dense(128, activation="relu")

# Sigmoid — 이진 분류 출력층 (0~1 사이 확률)
Dense(1, activation="sigmoid")

# Softmax — 다중 분류 출력층 (확률의 합 = 1)
Dense(10, activation="softmax")  # 10개 클래스

3-4. 모델 구조 확인

pythonmodel.summary()

# 출력 예시:
# Layer (type)          Output Shape    Param #
# ─────────────────────────────────────────────
# dense (Dense)         (None, 128)     640
# dense_1 (Dense)       (None, 64)      8256
# dense_2 (Dense)       (None, 3)       195
# ─────────────────────────────────────────────
# Total params: 9,091

Param #은 이 레이어가 학습해야 할 가중치의 수입니다. 숫자가 클수록 복잡한 모델입니다.


4. 모델 컴파일 & 학습

4-1. 컴파일 설정

모델을 학습하기 전에 "어떻게 학습할지" 를 설정합니다.

pythonmodel.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"]
)

4-2. 옵티마이저란?

모델이 오답을 냈을 때 가중치를 어느 방향으로, 얼마나 수정할지 결정합니다.

옵티마이저특징
adam가장 많이 쓰임. 학습률 자동 조정. 입문자 기본값
sgd가장 기본. 안정적이지만 느림
rmspropRNN/LSTM에 자주 사용

4-3. 손실 함수란?

모델의 예측이 정답과 얼마나 틀렸는지 측정합니다. 이 값을 최소화하는 방향으로 학습합니다.

문제 유형손실 함수
이진 분류 (0 or 1)binary_crossentropy
다중 분류 (정수 라벨)sparse_categorical_crossentropy
다중 분류 (원핫 라벨)categorical_crossentropy
회귀 (숫자 예측)mse (평균 제곱 오차)

4-4. 모델 학습

pythonhistory = model.fit(
    X_train, y_train,
    epochs=50,
    batch_size=32,
    validation_split=0.2,
    verbose=1
)
  • epoch — 전체 데이터를 한 번 다 보는 것. 50 epochs = 50번 반복
  • batch_size — 한 번에 처리하는 데이터 수. 32 또는 64가 일반적
  • validation_split — 과적합 여부를 실시간으로 확인하기 위해 검증 데이터 분리

4-5. 학습 곡선 시각화

pythonimport matplotlib.pyplot as plt

plt.plot(history.history["accuracy"],     label="훈련 정확도")
plt.plot(history.history["val_accuracy"], label="검증 정확도", linestyle="--")
plt.title("정확도 변화")
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.legend()
plt.grid(True)
plt.show()

plt.plot(history.history["loss"],     label="훈련 손실")
plt.plot(history.history["val_loss"], label="검증 손실", linestyle="--")
plt.title("손실 변화")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
plt.grid(True)
plt.show()

💡 검증 손실이 다시 올라가기 시작하는 지점 = 과적합 시작. 이 지점에서 학습을 멈추는 것이 이상적입니다.


5. 분류 실습 — 손글씨 숫자 인식 (MNIST)

5-1. MNIST 데이터셋이란?

MNIST 는 0~9까지의 손글씨 숫자 이미지 70,000장으로 구성된 데이터셋입니다. AI 분야에서 "Hello, World!"와 같은 입문 데이터셋으로, 딥러닝 학습에 가장 많이 쓰입니다.

- 훈련 데이터: 60,000장
- 테스트 데이터: 10,000장
- 이미지 크기: 28 × 28 픽셀 (흑백)
- 클래스: 0~9 (총 10개)

5-2. 데이터 전처리

pythonfrom tensorflow.keras.datasets import mnist

(X_train, y_train), (X_test, y_test) = mnist.load_data()

print(X_train.shape)  # (60000, 28, 28)
print(y_train.shape)  # (60000,)

import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 5, figsize=(12, 5))
for i, ax in enumerate(axes.flat):
    ax.imshow(X_train[i], cmap="gray")
    ax.set_title(f"정답: {y_train[i]}")
    ax.axis("off")
plt.show()

# 정규화
X_train = X_train / 255.0
X_test  = X_test  / 255.0

# Flatten
X_train = X_train.reshape(-1, 784)
X_test  = X_test.reshape(-1, 784)

print(X_train.shape)  # (60000, 784)

5-3. 모델 설계 및 학습

pythonfrom tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Dropout

model = Sequential([
    Dense(256, activation="relu", input_shape=(784,)),
    Dropout(0.3),
    Dense(128, activation="relu"),
    Dropout(0.3),
    Dense(10, activation="softmax")
])

model.summary()

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

history = model.fit(
    X_train, y_train,
    epochs=20,
    batch_size=64,
    validation_split=0.2
)

5-4. 예측 결과 시각화

pythonimport numpy as np

y_pred_proba = model.predict(X_test)
y_pred       = np.argmax(y_pred_proba, axis=1)

fig, axes = plt.subplots(2, 5, figsize=(14, 6))
for i, ax in enumerate(axes.flat):
    ax.imshow(X_test[i].reshape(28, 28), cmap="gray")
    color = "blue" if y_pred[i] == y_test[i] else "red"
    ax.set_title(f"예측:{y_pred[i]} / 정답:{y_test[i]}", color=color)
    ax.axis("off")

plt.suptitle("파란색: 정답, 빨간색: 오답")
plt.show()

5-5. 정확도 확인

pythontest_loss, test_acc = model.evaluate(X_test, y_test)
print(f"테스트 정확도: {test_acc:.4f}")  # 예: 0.9789 (97.89%)

6. 과적합 방지 기법

6-1. 과적합(Overfitting)이란?

모델이 훈련 데이터만 너무 잘 외워서 새로운 데이터에는 성능이 떨어지는 현상 입니다.

훈련 정확도: 99%
테스트 정확도: 72%  ← 과적합 발생

6-2. Dropout

학습할 때마다 뉴런의 일부를 랜덤으로 꺼서, 모델이 특정 패턴에만 의존하지 않도록 합니다.

pythonfrom tensorflow.keras.layers import Dropout

Dropout(0.3)  # 30%의 뉴런을 랜덤으로 비활성화
# 예측할 때는 모든 뉴런이 다시 켜집니다

6-3. EarlyStopping

검증 손실이 더 이상 개선되지 않으면 학습을 자동으로 멈춥니다.

pythonfrom tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(
    monitor="val_loss",
    patience=5,
    restore_best_weights=True
)

history = model.fit(
    X_train, y_train,
    epochs=100,
    validation_split=0.2,
    callbacks=[early_stop]
)

print(f"실제 학습된 에폭 수: {len(history.history['loss'])}")

6-4. Dropout + EarlyStopping 적용 전/후 비교

python# 적용 전 — 과적합 발생
# 훈련 정확도: 99.5%  검증 정확도: 82.3%

# 적용 후 — 과적합 억제
# 훈련 정확도: 96.1%  검증 정확도: 95.7%
# → 훈련-검증 격차가 줄어들수록 일반화 성능이 좋아진 것

7. 모델 저장 & 불러오기

7-1. 모델 저장

학습을 마친 모델을 저장해두면 다시 학습할 필요 없이 바로 사용할 수 있습니다.

pythonmodel.save("mnist_model.keras")

7-2. 모델 불러오기

pythonfrom tensorflow.keras.models import load_model

loaded_model = load_model("mnist_model.keras")

y_pred = loaded_model.predict(X_test)
print(f"정확도: {loaded_model.evaluate(X_test, y_test)[1]:.4f}")

7-3. 실무에서 저장이 중요한 이유

  • GPU가 있는 서버에서 학습하고, CPU 환경에서 예측만 실행
  • 학습에 몇 시간~며칠이 걸리는 모델을 매번 다시 학습할 수 없음
  • 여러 버전의 모델을 저장해두고 성능 비교

8. 마무리

8-1. 오늘 배운 것 한눈에 정리

개념핵심 내용
KerasTensorFlow 위에서 모델을 쉽게 설계하는 인터페이스
Sequential API레이어를 순서대로 쌓아 모델 구성
compile옵티마이저 + 손실 함수 + 평가 지표 설정
fitepoch, batch_size로 학습 제어
과적합 방지Dropout + EarlyStopping
저장/불러오기model.save / load_model