실제 프로젝트에서 딥러닝 모델을 개발할 때 필요한 실전 지식

1. 하이퍼파라미터 튜닝

하이퍼파라미터 중요도 순서

1순위 (가장 중요):

  • 🥇 학습률 (Learning Rate)
  • 🥈 배치 크기 (Batch Size)

2순위:

  • 은닉층 개수
  • 은닉층 뉴런 수
  • Dropout 비율

3순위:

  • 옵티마이저 선택
  • 활성화 함수
  • 가중치 감쇠

1.1 학습률 찾기

방법: Learning Rate Finder

# 작은 학습률부터 시작하여 지수적으로 증가시키며 손실 관찰
lrs = []
losses = []
 
for lr in [1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1]:
    model = create_model()
    optimizer = keras.optimizers.Adam(learning_rate=lr)
    # 몇 에포크 학습
    history = model.fit(X_train, y_train, epochs=3, verbose=0)
    lrs.append(lr)
    losses.append(history.history['loss'][-1])
 
# 시각화
import matplotlib.pyplot as plt
plt.plot(lrs, losses)
plt.xscale('log')
plt.xlabel('Learning Rate')
plt.ylabel('Loss')
plt.show()
 
# 손실이 가장 빠르게 감소하는 학습률 선택

경험적 값:

  • Adam: 0.001 (기본값)
  • SGD: 0.01 ~ 0.1
  • AdamW: 0.0001 ~ 0.001

1.2 배치 크기 선택

배치 크기장점단점사용 시기
작음 (16-32)일반화 성능 좋음
메모리 적음
느림
불안정
데이터 적음
메모리 제약
중간 (64-128)균형 잡힘-일반적인 경우
큼 (256-512+)빠름
안정적
일반화 성능 저하
메모리 많이 필요
대규모 데이터
강력한 GPU

추천: 32 or 64로 시작


1.3 은닉층 구조

경험 법칙:

  • 입력층 → 점점 감소 → 출력층
  • 예: 784 → 512 → 256 → 128 → 10

깊이 vs 너비:

깊은 모델넓은 모델
층 수많음 (5+)적음 (2-3)
뉴런 수적음-중간많음
표현력복잡한 패턴단순한 패턴
과적합 위험높음중간
학습 속도느림빠름

시작점:

  • 2-3개 은닉층
  • 128-512 뉴런
  • 과소적합이면 층/뉴런 추가
  • 과적합이면 층/뉴런 감소 또는 정규화

1.4 Dropout 비율

위치추천 비율
입력층0.1 ~ 0.2
은닉층 (FC)0.3 ~ 0.5
CNN0.1 ~ 0.2
RNN0.2 ~ 0.5

조정 방법:

  • 과적합 심하면 → 증가 (0.5 → 0.6)
  • 과소적합이면 → 감소 (0.5 → 0.3)

2. 일반적인 문제와 해결책

문제 1: 과적합 (Overfitting) 🔥

증상:

  • 훈련 손실 < 검증 손실
  • 훈련 정확도 >> 검증 정확도
  • 학습 곡선이 갈라짐

시각화:

Loss
  |
  | Train ----___
  |            \___
  | Val   ________/----
  |      /
  +------------------- Epoch

해결책 (우선순위):

  1. 🥇 더 많은 데이터 수집 (가장 효과적)
  2. 🥈 Dropout 추가/증가 (0.3 → 0.5)
  3. 🥉 L2 정규화 추가 (weight_decay=0.0001)
  4. 모델 단순화 (층/뉴런 감소)
  5. 조기 종료 (Early Stopping)
  6. 데이터 증강 (이미지/텍스트)
  7. Batch Normalization 추가

코드 예시:

# 과적합 방지 조합
model = keras.Sequential([
    Dense(256, kernel_regularizer=l2(0.001)),  # L2 정규화
    BatchNormalization(),
    Activation('relu'),
    Dropout(0.5),  # Dropout 증가
 
    Dense(128, kernel_regularizer=l2(0.001)),
    BatchNormalization(),
    Activation('relu'),
    Dropout(0.4),
 
    Dense(10, activation='softmax')
])
 
# Early Stopping
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
model.fit(X, y, validation_split=0.2, callbacks=[early_stop])

문제 2: 과소적합 (Underfitting)

증상:

  • 훈련 손실도 높음
  • 훈련 정확도도 낮음
  • 검증 성능도 낮음

시각화:

Loss
  |
  | Train --------
  |       \______
  | Val   --------
  |       \______
  +------------------- Epoch

해결책:

  1. 🥇 모델 복잡도 증가 (층/뉴런 추가)
  2. 🥈 더 오래 학습 (에포크 증가)
  3. 🥉 정규화 감소 (Dropout 낮춤)
  4. 더 나은 특징 엔지니어링
  5. 다른 모델 아키텍처 시도
  6. 학습률 조정 (너무 낮거나 높음)

코드 예시:

# 모델 복잡도 증가
model = keras.Sequential([
    Dense(512, activation='relu'),  # 뉴런 수 증가
    Dense(256, activation='relu'),  # 층 추가
    Dense(128, activation='relu'),
    Dense(10, activation='softmax')
])
 
# 더 오래 학습
model.fit(X, y, epochs=100)  # 에포크 증가

문제 3: 학습이 안 됨

증상:

  • 손실이 감소하지 않음
  • 정확도가 랜덤 수준
  • 손실이 NaN

원인과 해결책:

원인해결책
학습률이 너무 큼학습률 감소 (0.001 → 0.0001)
학습률이 너무 작음학습률 증가 (0.0001 → 0.001)
잘못된 가중치 초기화He/Xavier 초기화 사용
데이터 전처리 안 함정규화/표준화 적용
기울기 소실/폭발Batch Norm, ReLU 사용
잘못된 손실 함수문제 유형에 맞는 손실 선택

체크리스트:

# 1. 데이터 정규화 확인
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)
 
# 2. 가중치 초기화 확인
Dense(128, kernel_initializer='he_normal')
 
# 3. 학습률 조정
optimizer = Adam(learning_rate=0.001)
 
# 4. Batch Normalization 추가
model.add(BatchNormalization())
 
# 5. 작은 모델로 시작
model = keras.Sequential([
    Dense(64, activation='relu'),
    Dense(32, activation='relu'),
    Dense(10, activation='softmax')
])

문제 4: 기울기 소실/폭발

증상:

  • 초기 층의 가중치가 거의 업데이트 안 됨
  • NaN 손실 발생
  • 학습이 매우 느림

해결책:

기울기 소실:

# 1. ReLU 활성화 함수 사용
Dense(128, activation='relu')
 
# 2. Batch Normalization
model.add(BatchNormalization())
 
# 3. He 초기화
Dense(128, kernel_initializer='he_normal', activation='relu')
 
# 4. 잔차 연결 (ResNet)
# 고급 주제 - 별도 학습 필요

기울기 폭발:

# 1. 기울기 클리핑
optimizer = Adam(clipnorm=1.0)
 
# 또는 PyTorch
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
 
# 2. 낮은 학습률
optimizer = Adam(learning_rate=0.0001)
 
# 3. Batch Normalization
model.add(BatchNormalization())

문제 5: 학습이 너무 느림

해결책:

  1. 배치 크기 증가

    model.fit(X, y, batch_size=128)  # 32 → 128
  2. GPU 사용

    # PyTorch
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = model.to(device)
  3. 더 빠른 옵티마이저

    optimizer = Adam(learning_rate=0.001)  # SGD보다 빠름
  4. 학습률 증가

    optimizer = Adam(learning_rate=0.01)  # 0.001 → 0.01
  5. 모델 단순화

    # 층이나 뉴런 수 감소

3. 딥러닝 워크플로우

3.1 데이터 준비

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
 
# 1. 데이터 분할 (60% 훈련, 20% 검증, 20% 테스트)
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
 
# 2. 정규화 (훈련 데이터 기준으로 fit)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)
X_test = scaler.transform(X_test)
 
print(f"Train: {X_train.shape}, Val: {X_val.shape}, Test: {X_test.shape}")

3.2 모델 구축

from tensorflow import keras
from tensorflow.keras import layers
 
model = keras.Sequential([
    layers.Input(shape=(input_dim,)),
 
    # 첫 번째 블록
    layers.Dense(256, kernel_initializer='he_normal'),
    layers.BatchNormalization(),
    layers.Activation('relu'),
    layers.Dropout(0.3),
 
    # 두 번째 블록
    layers.Dense(128, kernel_initializer='he_normal'),
    layers.BatchNormalization(),
    layers.Activation('relu'),
    layers.Dropout(0.3),
 
    # 세 번째 블록
    layers.Dense(64, kernel_initializer='he_normal'),
    layers.BatchNormalization(),
    layers.Activation('relu'),
    layers.Dropout(0.2),
 
    # 출력층
    layers.Dense(num_classes, activation='softmax')
])
 
model.summary()

3.3 모델 컴파일

model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.001),
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

3.4 콜백 설정

callbacks = [
    # 조기 종료
    keras.callbacks.EarlyStopping(
        monitor='val_loss',
        patience=10,
        restore_best_weights=True,
        verbose=1
    ),
 
    # 학습률 감소
    keras.callbacks.ReduceLROnPlateau(
        monitor='val_loss',
        factor=0.5,
        patience=5,
        min_lr=1e-7,
        verbose=1
    ),
 
    # 모델 저장
    keras.callbacks.ModelCheckpoint(
        'best_model.keras',
        monitor='val_accuracy',
        save_best_only=True,
        verbose=1
    )
]

3.5 모델 학습

history = model.fit(
    X_train, y_train,
    batch_size=32,
    epochs=100,
    validation_data=(X_val, y_val),
    callbacks=callbacks,
    verbose=1
)

3.6 학습 곡선 시각화

import matplotlib.pyplot as plt
 
plt.figure(figsize=(12, 4))
 
# 손실 곡선
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.title('Loss Curves')
plt.grid(True)
 
# 정확도 곡선
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Acc')
plt.plot(history.history['val_accuracy'], label='Val Acc')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Accuracy Curves')
plt.grid(True)
 
plt.tight_layout()
plt.show()

3.7 모델 평가

# 테스트 세트 평가
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
print(f'Test Loss: {test_loss:.4f}')
print(f'Test Accuracy: {test_acc:.4f}')
 
# 예측
y_pred = model.predict(X_test)
y_pred_classes = y_pred.argmax(axis=1)
 
# 혼동 행렬
from sklearn.metrics import confusion_matrix, classification_report
 
print("Confusion Matrix:")
print(confusion_matrix(y_test, y_pred_classes))
 
print("\nClassification Report:")
print(classification_report(y_test, y_pred_classes))

4. 체크리스트

데이터 전처리

  • 데이터 정규화/표준화
  • Train/Val/Test 분할 (60/20/20)
  • 클래스 불균형 확인
  • 결측치 처리
  • 데이터 증강 (필요시)

모델 설계

  • 적절한 활성화 함수 (은닉층: ReLU)
  • 출력층 활성화 (분류: Softmax/Sigmoid, 회귀: None)
  • 적절한 손실 함수
  • He/Xavier 초기화

정규화

  • Dropout 추가 (0.2-0.5)
  • L2 정규화 (weight_decay=0.0001)
  • Batch Normalization (선택)

학습 설정

  • Adam 옵티마이저 (lr=0.001)
  • 적절한 배치 크기 (32-128)
  • Early Stopping 설정
  • ReduceLROnPlateau (선택)

평가

  • 검증 세트로 성능 모니터링
  • 학습 곡선 시각화
  • 테스트 세트로 최종 평가
  • 혼동 행렬 확인

5. 디버깅 플로우차트

학습이 잘 안 되나요?
    |
    ├─ 손실이 감소 안 함?
    |   ├─ 데이터 정규화 확인
    |   ├─ 학습률 조정
    |   └─ Batch Norm 추가
    |
    ├─ 과적합?
    |   ├─ Dropout 증가
    |   ├─ Weight Decay 추가
    |   ├─ 더 많은 데이터
    |   └─ Early Stopping
    |
    ├─ 과소적합?
    |   ├─ 모델 복잡도 증가
    |   ├─ 정규화 감소
    |   └─ 더 오래 학습
    |
    └─ 학습이 느림?
        ├─ 배치 크기 증가
        ├─ GPU 사용
        └─ Adam 옵티마이저

6. 모범 사례 (Best Practices)

시작하기

  1. 간단한 모델로 시작

    • 2-3층, 64-128 뉴런
    • 과소적합이면 복잡도 증가
  2. 기본 설정 사용

    • Adam 옵티마이저 (lr=0.001)
    • Batch size = 32
    • ReLU 활성화
  3. 반드시 검증 세트 사용

    • 과적합 모니터링
    • Early Stopping
  4. 학습 곡선 시각화

    • 문제 진단
    • 하이퍼파라미터 조정 방향 결정

개선하기

  1. 과적합이면:

    • Dropout 추가/증가
    • Weight Decay
    • 데이터 증강
  2. 과소적합이면:

    • 층/뉴런 추가
    • 정규화 감소
    • 더 오래 학습
  3. 학습률 튜닝

    • Learning Rate Finder 사용
    • ReduceLROnPlateau 사용

7. 자주 하는 실수

❌ 하지 말아야 할 것

  1. 테스트 세트로 하이퍼파라미터 튜닝

    • → 검증 세트 사용
  2. 데이터 정규화 안 함

    • → StandardScaler 사용
  3. 모든 가중치를 0으로 초기화

    • → He/Xavier 초기화
  4. 검증 세트 없이 학습

    • → Train/Val/Test 분할
  5. 과적합을 무시하고 계속 학습

    • → Early Stopping
  6. 학습 곡선을 안 봄

    • → 반드시 시각화

핵심 요약

기본 설정

  • 🎯 Adam(lr=0.001) + Batch=32
  • 🎯 ReLU + He 초기화
  • 🎯 Dropout(0.3-0.5) + Weight Decay(0.0001)
  • 🎯 Early Stopping + ReduceLROnPlateau

문제 해결

  • 🔥 과적합 → Dropout↑, 데이터↑
  • 🔥 과소적합 → 모델 복잡도↑
  • 🔥 학습 안 됨 → 학습률, 데이터 정규화
  • 🔥 느림 → 배치 크기↑, GPU

기억할 것

  • ✅ 항상 검증 세트 사용
  • ✅ 학습 곡선 시각화
  • ✅ 간단한 모델부터 시작
  • ✅ 체계적으로 디버깅

다음 학습

  1. 딥러닝_코드_실습 - 실제 프로젝트로 실습
  2. 컴퓨터 비전 (CNN) - 이미지 처리 학습

딥러닝 기초