포스트

PyTorch 기초 (5) - 학습 실무: GPU, train/eval 모드, 체크포인트, 재현성

모델을 실제로 돌릴 때 필요한 실무 감각 — device로 GPU 쓰기, model.train()과 eval()의 차이, state_dict로 체크포인트 저장·로드, 시드 고정으로 재현성 확보, 그리고 흔한 실수들 — 을 정리하며 PyTorch 기초 시리즈를 마무리하는 (5)편입니다.

PyTorch 기초 (5) - 학습 실무: GPU, train/eval 모드, 체크포인트, 재현성

PyTorch 기초 시리즈(6편)의 마지막, 5편입니다. 전체 목차는 0편에 있습니다. 모델·학습·데이터를 갖췄으니, 이 편은 그것을 실제로 안정적으로 돌리는 실무를 정리합니다.

GPU 쓰기: device 패턴

1편에서 텐서가 device를 가진다고 했습니다. GPU 학습의 규칙은 단순합니다. 모델과 그 모델에 들어가는 데이터가 같은 device에 있어야 합니다. 실무에서는 device를 한 번 정해두고, 모델과 배치를 거기로 옮기는 패턴을 씁니다.

1
2
3
4
5
6
7
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)                       # 모델 파라미터를 GPU로

for xb, yb in loader:
    xb, yb = xb.to(device), yb.to(device)   # 배치도 같은 곳으로
    pred = model(xb)
    ...

CPU 텐서와 GPU 텐서를 섞어 연산하면 에러가 나므로, to(device)를 빠뜨리지 않는 것이 핵심입니다. GPU가 없으면 자동으로 CPU가 되어 같은 코드가 그대로 돕니다.

train 모드와 eval 모드

모델에는 학습 모드와 평가 모드가 있고, model.train() / model.eval()로 전환합니다. 이 구분이 중요한 이유는 드롭아웃(8편)과 배치 정규화(7편)가 두 모드에서 다르게 동작하기 때문입니다.

  • 드롭아웃 — 학습 때는 뉴런을 무작위로 끄지만, 평가 때는 전부 켜야 합니다.
  • 배치 정규화 — 학습 때는 배치 통계를, 평가 때는 학습 중 누적한 이동평균을 씁니다.

평가·추론할 때는 모드 전환과 함께 torch.no_grad()로 기울기 추적도 꺼서 메모리와 시간을 아낍니다.

1
2
3
4
5
6
7
8
9
model.train()                     # 학습 루프 전
for xb, yb in train_loader:
    ...

model.eval()                      # 평가 전
with torch.no_grad():
    for xb, yb in valid_loader:
        pred = model(xb)
        ...

eval()로 바꾸는 것을 잊으면, 평가 중에도 드롭아웃이 켜져 있어 성능이 실제보다 낮게, 그리고 매번 다르게 나옵니다. 조용히 틀리는 대표적인 실수입니다.

체크포인트: state_dict 저장과 로드

학습한 모델을 저장할 때는 모델 객체 전체가 아니라 state_dict — 파라미터를 이름과 값으로 담은 딕셔너리 — 를 저장하는 것이 권장 방식입니다.

1
2
3
4
5
torch.save(model.state_dict(), "model.pt")     # 저장

model = Net()                                   # 같은 구조를 먼저 만들고
model.load_state_dict(torch.load("model.pt"))   # 파라미터를 채운다
model.eval()

학습을 중간부터 이어가려면(재개) 모델뿐 아니라 옵티마이저의 state_dict와 에폭 번호도 함께 저장해야 합니다. 옵티마이저(예: Adam)가 모멘텀 같은 내부 상태를 들고 있기 때문입니다.

재현성: 시드 고정

같은 코드를 돌릴 때마다 결과가 달라지면 실험을 비교할 수 없습니다. 난수 시드를 고정하면 재현성이 생깁니다. PyTorch·NumPy·(GPU를 쓰면) CUDA의 시드를 함께 잡아야 합니다.

1
2
3
4
5
6
import torch, numpy as np

def set_seed(seed=42):
    torch.manual_seed(seed)
    np.random.seed(seed)
    torch.cuda.manual_seed_all(seed)

완전한 결정성이 필요하면 추가 설정이 더 있지만, 대개는 이 정도로 실험 간 비교가 가능해집니다.

흔한 실수 모음

마지막으로, 처음에 반드시 한 번씩 겪는 실수들입니다.

실수증상해결
zero_grad() 누락기울기가 누적돼 학습이 이상매 스텝 optimizer.zero_grad()
eval() 전환 안 함평가 성능이 낮고 매번 다름평가 전 model.eval() + no_grad()
device 불일치“expected same device” 에러모델·데이터 모두 to(device)
손실을 텐서째 보관메모리 누수(그래프가 안 풀림)기록용은 loss.item()으로 값만

시리즈를 마치며

(1) 텐서에서 시작해 (2) autograd로 미분을, (3) nn.Module과 옵티마이저로 모델과 학습 루프를, (4) Dataset·DataLoader로 데이터 공급을, 그리고 이 편에서 실무 감각까지 정리했습니다. 이제 딥러닝 기초에서 원리로 익힌 신경망을, PyTorch라는 도구로 직접 만들고 학습시킬 수 있습니다. 다음은 이 도구로 실제 데이터에 아키텍처를 붙여보는 실습입니다 — 개념(딥러닝 기초)과 도구(이 시리즈)가 만나는 자리입니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.