검색
← 모듈 로드맵

신경망 학습 디버깅과 실험 관리 레시피

강의 · 준전문가 · KAITABASE 정리

초기 손실 ln C · 한 배치 과적합 · 0 입력 기준선 · 학습률 훑기 · 시드와 체크포인트로 하는 학습 디버깅

먼저 알아야 할 것

역전파옵티마이저 · 학습률초기화 · 정규화 · 드롭아웃학습 · 검증 데이터 나누기

다루는 내용

Karpathy의 신경망 학습 레시피 여섯 단계를 뼈대로, 학습이 조용히 실패하는 버그를 잡는 점검을 정리합니다. 손글씨 숫자 데이터로 초기 손실이 ln C 근처인지, 한 배치를 외우는지, 입력을 지운 기준선과 차이가 나는지, 학습률을 몇 배 간격으로 훑었을 때 어떻게 달라지는지를 직접 돌린 결과로 보여 줍니다. 시드 고정 · 설정 저장 · 기록 · 체크포인트 같은 실험 관리 습관과 증상별 진단표도 담았습니다.

해설

신경망 학습 디버깅과 실험 관리 레시피

신경망은 버그가 있어도 에러 없이 "그럭저럭" 학습되는 일이 많아서, 무엇이 잘못됐는지 알아채기 어렵습니다. 이 수업은 Andrej Karpathy의 글 A Recipe for Training Neural Networks(2019)의 순서를 뼈대로, 초기 손실 확인 · 한 배치 과적합 · 학습률 훑기 · 입력을 지운 기준선 같은 점검을 손글씨 숫자 데이터로 직접 돌려 본 결과와 함께 정리하고, 시드 · 기록 · 체크포인트로 실험을 다시 만들 수 있게 관리하는 법을 다룹니다.

항목내용
참고 자료Andrej Karpathy, A Recipe for Training Neural Networks · karpathy.github.io/2019/04/25/recipe, PyTorch 재현성 문서
트랙 · 수준딥러닝 기초 · 중급
이 수업의 범위데이터 들여다보기, 끝까지 도는 뼈대와 단순 기준선, 초기 손실 ln⁡C\ln C 확인, 한 배치 과적합, 입력을 0으로 지운 기준선, 학습률 훑기, 기울기 점검, 과적합 → 규제 → 조정 순서, 시드 · 기록 · 체크포인트
먼저 알면 좋은 것역전파, 옵티마이저, 초기화 · 정규화 · 드롭아웃, 학습 · 검증 데이터 나누기

들어가기 전에

한눈에 보기

  • 신경망 버그가 "조용히" 성능만 깎는 이유와, 그래서 작은 점검을 순서대로 쌓아야 하는 이유를 압니다.
  • 학습 전 손실이 ln⁡C\ln C 근처인지 확인하는 법을 직접 돌린 숫자로 봅니다.
  • 한 배치를 거의 0 손실까지 외우게 하는 "한 배치 과적합"으로 모델 · 손실 · 옵티마이저 연결을 점검합니다.
  • 학습률을 몇 배 간격으로 훑어 쓸 만한 범위를 찾는 법을 실제 결과 표로 익힙니다.
  • 실험을 다시 만들 수 있도록 시드 · 설정 · 기록 · 체크포인트를 남기는 습관을 정리합니다.

1. 왜 레시피가 필요한가

직관(해설용 비유): 요리에서 소금을 빼먹어도 음식은 나옵니다. 맛이 조금 없을 뿐입니다. 신경망도 데이터 전처리 한 줄이 틀리거나, 정답 라벨이 섞이거나, 드롭아웃을 평가 때 켜 둬도 학습은 "돌아갑니다". 성능만 몇 퍼센트 떨어집니다. Karpathy는 이 점을 들어 신경망 학습이 "조용히 실패한다"고 표현하고, 빠르고 화려하게 시작하기보다 작은 단계를 하나씩 검증하며 나아가라고 권합니다.

그 글이 제시하는 순서는 다음 여섯 단계입니다(제목은 원문, 설명은 요약).

단계원문 제목하는 일
1Become one with the data모델 코드 전에 데이터를 오래 들여다보기 — 중복, 깨진 라벨, 불균형, 이상값
2Set up the end-to-end training/evaluation skeleton + get dumb baselines단순한 모델로 학습 · 평가가 끝까지 도는 뼈대를 만들고 바보 같은 기준선 확보
3Overfit학습 데이터를 충분히 맞출 만큼 큰 모델부터 맞추기
4Regularize그다음 검증 성능을 위해 규제
5Tune하이퍼파라미터 탐색
6Squeeze out the juice앙상블, 더 오래 학습 등 마지막 짜내기
mermaid
flowchart LR
  A[데이터 들여다보기] --> B[끝까지 도는 뼈대 + 단순 기준선]
  B --> C{점검 통과?<br/>초기 손실 · 한 배치 과적합 · 0 입력 기준선}
  C -- 아니오 --> B
  C -- 예 --> D[과적합할 만큼 키우기]
  D --> E[규제: 데이터 · 증강 · 감쇠 · 조기 종료]
  E --> F[조정: 무작위 탐색]
  F --> G[짜내기: 앙상블 · 오래 학습]

2. 뼈대 단계의 점검 다섯 가지

아래 숫자는 scikit-learn 내장 손글씨 숫자 데이터(8×8 이미지 1,797장, 10개 클래스)를 학습 1,437 · 검증 360으로 나누고, 64→64→10 MLP(ReLU)를 PyTorch로 학습해 얻은 실제 실행 결과입니다(해설용 실험, 시드 0, CPU 한 번 실행).

점검 1: 시작 손실이 ln C 근처인가

직관: 아무것도 배우지 않은 분류기는 CC개 클래스에 거의 같은 확률 1/C1/C를 줍니다. 그러면 교차 엔트로피는

L시작≈−ln⁡1C=ln⁡CL_{\text{시작}} \approx -\ln\frac{1}{C} = \ln C

입니다. Karpathy도 소프트맥스 분류기의 초기 손실이 −log⁡(1/nclasses)-\log(1/n_{\text{classes}}) 근처인지 확인하라고 권합니다.

숫자로 해 보기: 10개 클래스이므로 ln⁡10≈2.3026\ln 10 \approx 2.3026. 실제 초기 손실은 2.3136으로 거의 같습니다. 만약 초기 손실이 10이나 50처럼 크면 출력층 가중치가 너무 크거나(초기화 문제) 라벨 · 손실 함수 연결이 잘못된 것입니다.

관련 팁 — 마지막 층 편향 초기화: 회귀라면 목표값의 평균으로, 클래스가 불균형하면 그 비율을 반영해 마지막 층 편향을 잡아 주면 초반 몇 걸음을 편향 맞추는 데 낭비하지 않습니다(원문의 "init well").

점검 2: 한 배치를 외울 수 있는가

직관: 예제 32개짜리 배치 하나만 반복해 학습시키면, 충분한 크기의 모델은 이것을 거의 완벽하게 외워야 합니다. 못 외우면 모델 · 손실 · 옵티마이저 중 어딘가 끊겨 있습니다.

숫자로 해 보기(Adam, 학습률 0.01):

걸음050100200
배치 손실2.34830.00460.00150.0007

200걸음 뒤 그 배치의 정확도는 1.0이었습니다. 이 점검은 1분 안에 끝나므로, 모델 구조를 바꿀 때마다 먼저 돌려 볼 만합니다.

점검 3: 입력을 지워도 성능이 같은가(입력 무관 기준선)

직관: 입력을 모두 0으로 바꿔 학습해 봅니다. 모델이 입력에서 정보를 뽑고 있다면, 진짜 입력으로 학습한 모델이 훨씬 좋아야 합니다.

숫자로 해 보기: 입력을 0으로 바꾸고 같은 설정(Adam 1e-3, 20에포크)으로 학습하면 검증 손실 2.3025 · 정확도 0.10, 즉 찍기와 같습니다. 진짜 입력에서는 손실 0.2414 · 정확도 0.9472였습니다. 만약 두 결과가 비슷하다면 입력이 모델에 제대로 들어가지 않는 버그를 의심합니다.

점검 4: 모델 직전의 텐서를 눈으로 보기

데이터 증강 · 정규화 · 자르기 등 전처리를 거친 뒤 모델에 들어가기 직전의 배치를 이미지 · 숫자로 직접 확인합니다. 원문은 이것을 "visualize just before the net"이라 부르며 전처리 버그를 잡는 가장 확실한 방법이라고 합니다. 픽셀 값 범위(0~1인지 0~255인지), 라벨이 이미지와 맞는지, 배치 차원 순서가 맞는지를 봅니다.

점검 5: 기울기로 의존 관계 확인하기

예제 ii의 손실만 역전파했을 때 다른 예제 jj의 입력에 기울기가 생기면, 배치 안 예제끼리 섞이는 버그(예: 차원을 잘못 잡은 view나 정규화)가 있다는 뜻입니다. 자기회귀 모델이라면 tt번째 출력의 기울기가 tt 이후 입력에 생기지 않는지도 같은 방법으로 봅니다. 역전파 구현 자체를 직접 짰다면 수치 기울기 점검을 합니다.

3. 학습률 훑기: 몇 배 간격으로 먼저 찾기

직관: 학습률은 결과를 가장 크게 바꾸는 손잡이입니다. 처음에는 정밀하게 고르기보다 10배 간격으로 넓게 훑어 "쓸 만한 구간"을 찾습니다.

숫자로 해 보기(같은 MLP, Adam, 20에포크, 배치 64):

학습률검증 손실검증 정확도읽을 것
1e-52.28240.1222너무 작아 거의 안 배움
1e-41.84870.8056배우지만 느림
1e-30.24140.9472좋음
1e-20.13830.9583이 실험에서 가장 좋음
1e-10.20910.9417아직 괜찮지만 나빠지기 시작
1.02.35680.1000너무 커서 학습 실패

결과는 문제와 모델마다 다르므로 이 표의 최적값을 다른 문제에 옮기면 안 됩니다. 방법만 가져갑니다. Karpathy는 출발점으로 학습률 3e-4의 Adam을 권하고, 학습률 감소 스케줄은 처음에는 끄고(상수 학습률) 마지막에 조정하라고 조언합니다 — 에포크 기준 기본 스케줄이 예상보다 빨리 학습률을 0으로 만들어 버릴 수 있기 때문입니다.

4. 과적합 → 규제 → 조정의 순서

  1. 먼저 과적합시키기: 학습 손실이 충분히 내려가는 모델을 만듭니다. 원문은 처음부터 새 구조를 발명하지 말고("Don't be a hero") 가장 관련 있는 논문의 단순하고 검증된 구조를 가져오라고 권합니다. 복잡도는 하나씩만 올리며 매번 기대한 만큼 좋아지는지 확인합니다.
  2. 그다음 규제하기: 효과가 큰 순서로 — 데이터 더 모으기, 데이터 증강, 사전학습 모델 쓰기, 입력 · 모델 크기 줄이기, 드롭아웃, 가중치 감쇠, 조기 종료(초기화 · 정규화 · 규제).
  3. 조정하기: 하이퍼파라미터는 격자 탐색보다 무작위 탐색을 권합니다. 몇몇 하이퍼파라미터만 결과에 크게 영향을 줄 때, 무작위 탐색이 중요한 축의 값을 더 다양하게 시험하기 때문입니다.
  4. 짜내기: 여러 모델의 앙상블은 대개 정확도를 조금 더 올립니다. 그리고 신경망은 생각보다 오래 학습해도 계속 좋아지는 경우가 많습니다.

5. 실험 관리: 다시 만들 수 있게

직관: 한 달 뒤 "그때 그 좋은 결과"를 다시 못 만들면, 그 결과는 없는 것과 같습니다.

최소 습관 체크리스트

  • 시드 고정: torch.manual_seed(0), random.seed(0), np.random.seed(0). 더 엄격하게는 torch.use_deterministic_algorithms(True)와 torch.backends.cudnn.benchmark = False. 다만 PyTorch 문서는 릴리스 · 커밋 · 플랫폼이 다르면 완전히 같은 결과를 보장하지 않는다고 밝힙니다. 그래서 중요한 비교는 시드를 여러 개 돌려 평균과 흔들림을 함께 봅니다.
  • 설정 저장: 학습률 · 배치 크기 · 에포크 · 모델 크기 · 데이터 버전 · 코드 커밋을 실험마다 파일 하나(예: YAML · JSON)로 남깁니다.
  • 기록: 학습 · 검증 손실과 지표, 학습률, 기울기 노름을 걸음마다 기록하고 그래프로 봅니다. 지표는 배치 평균을 매끄럽게 한 값보다 검증 데이터 전체로 계산합니다(원문의 "add significant digits to your eval").
  • 체크포인트: 모델과 옵티마이저 상태(Adam의 mm, vv 포함), 스케줄러 상태, 현재 걸음 수를 함께 저장해야 중단된 학습을 똑같이 이어 갈 수 있습니다. 가장 좋은 검증 점수의 체크포인트는 따로 보관합니다.
python
torch.save({"model": model.state_dict(),
            "optimizer": optimizer.state_dict(),
            "scheduler": scheduler.state_dict(),
            "step": step, "config": config}, "ckpt.pt")

6. 증상별 빠른 진단표

증상먼저 의심할 것
시작 손실이 ln⁡C\ln C보다 훨씬 큼출력층 초기화, 로짓에 소프트맥스를 두 번 적용, 라벨 형식
손실이 전혀 안 줄어듦학습률이 너무 작음, optimizer.step() 누락, 파라미터가 옵티마이저에 안 들어감, requires_grad 꺼짐
손실이 NaN · 폭발학습률이 너무 큼, log(0), 기울기 폭발 → 학습률 낮추기 · 웜업 · 클리핑
학습은 좋은데 검증이 나쁨과적합, 학습 · 검증 분포 차이, 데이터 누수
학습할 때와 평가할 때 결과가 다름model.eval() 누락(드롭아웃 · 배치 정규화), 전처리 불일치
매번 결과가 크게 다름시드 미고정, 너무 작은 검증 데이터, 학습률이 경계값 근처

연습 문제

1. 클래스가 100개인 분류 문제의 시작 손실은 대략 얼마여야 하나요?

풀이: ln⁡100≈4.605\ln 100 \approx 4.605입니다.

2. 이진 분류(양성 10%)에서 마지막 시그모이드 층의 편향을 무엇으로 초기화하면 시작 확률이 0.1이 되나요?

풀이: σ(b)=0.1\sigma(b) = 0.1이 되려면 b=ln⁡0.10.9≈−2.197b = \ln\frac{0.1}{0.9} \approx -2.197입니다.

3. 한 배치 과적합 점검에서 손실이 2.3에서 내려가지 않습니다. 의심할 곳 두 가지는?

풀이: optimizer.step()이나 loss.backward()를 부르지 않는 경우, 옵티마이저에 모델 파라미터가 전달되지 않은 경우, 학습률이 0에 가까운 경우 등입니다.

4. 학습률 훑기에서 1e-2가 가장 좋았습니다. 다음에는 어떤 값들을 시험할까요?

풀이: 그 주변을 더 촘촘히, 예를 들어 3e-3, 5e-3, 1e-2, 2e-2, 3e-2처럼 시험하고 시드도 여러 개 돌려 차이가 흔들림보다 큰지 확인합니다.

스스로 점검

  1. 입력을 0으로 바꾼 기준선은 무엇을 확인하나요?
    • 답: 모델이 실제로 입력에서 정보를 뽑고 있는지입니다. 진짜 입력과 결과가 비슷하면 입력이 제대로 전달되지 않는 버그를 의심합니다.
  2. 왜 규제보다 과적합을 먼저 하나요?
    • 답: 학습 데이터조차 못 맞추는 모델은 규제로 좋아지지 않습니다. 충분한 표현력이 있음을 먼저 확인한 뒤, 검증 성능을 위해 규제를 더합니다.
  3. 체크포인트에 옵티마이저 상태까지 저장해야 하는 이유는?
    • 답: Adam의 이동 평균, 모멘텀 버퍼, 스케줄러의 현재 학습률이 없으면 이어 학습할 때 처음과 다른 궤적을 밟기 때문입니다.

용어 정리

용어쉬운 뜻
기준선(baseline)비교를 위해 먼저 만드는 단순한 모델 · 결과
입력 무관 기준선(input-independent baseline)입력을 지우고 학습해 본 결과, 모델이 입력을 쓰는지 확인용
한 배치 과적합(overfit one batch)작은 배치 하나를 외우게 해 학습 경로가 연결됐는지 보는 점검
학습률 훑기(learning-rate sweep)학습률을 몇 배 간격으로 바꿔 쓸 만한 범위를 찾기
무작위 탐색(random search)하이퍼파라미터를 무작위로 뽑아 시험하는 방법
체크포인트(checkpoint)학습 중간 상태(모델 · 옵티마이저 · 걸음 수)를 저장한 파일
재현성(reproducibility)같은 설정으로 같은 결과를 다시 얻을 수 있는 성질
앙상블(ensemble)여러 모델의 예측을 합쳐 쓰는 방법

더 깊이 보려면

Karpathy의 원문은 각 단계마다 더 많은 구체적 팁(사람 기준 성능과 비교, 고정된 배치의 예측 변화를 학습 내내 지켜보기, 특수한 경우부터 일반화하기 등)을 담고 있어 한 번 통독할 가치가 있습니다. 재현성 설정은 PyTorch의 'Reproducibility' 문서를 참고하세요.

다음에 볼 것

라이선스

이 글은 원문 번역이 아니라 KAITABASE가 직접 쓴 해설입니다. Karpathy 글의 단계 제목은 짧게 인용했고 내용은 요약 · 재구성했습니다. 표의 숫자는 scikit-learn 1.9 내장 데이터와 PyTorch 2.14(CPU)로 직접 실행한 해설용 실험 결과입니다.

출처

AI 원리부터 이해하기 · 딥러닝 기초 모듈

딥러닝 기초 모듈 학습

이 글은 딥러닝 기초 모듈의 학습 자료입니다. 전체 29개 자료 중 12번째입니다.

AI 기초 과정은 현재 진도 저장을 지원하지 않습니다.

출처·원문

원문 보기

요약만

본문 자체 작성 · 참고 자료 Andrej Karpathy 블로그 글