Skip to main content
Summary

오류는 문제의 위치를 알려 준다

PyTorch를 배우다 보면 긴 오류 메시지를 자주 만납니다. 처음에는 무섭게 보이지만, 대부분은 몇 가지 원인으로 반복됩니다. 특히 초보자가 자주 만나는 오류는 shape, dtype, device, memory 문제입니다.

오류를 빨리 고치려면 감으로 코드를 바꾸기보다 텐서의 상태를 먼저 확인해야 합니다.

print(x.shape, x.dtype, x.device)
print(y.shape, y.dtype, y.device)

이 세 줄은 디버깅의 기본 도구입니다. 모델에 들어가기 전, 손실 함수를 계산하기 전, 오류가 난 줄 바로 앞에서 확인하면 원인을 찾기 쉽습니다.

초보자가 자주 만나는 오류 해결하기

shape mismatch: 모양이 맞지 않는 경우

shape mismatch, mat1 and mat2 shapes cannot be multiplied, size mismatch 같은 메시지는 텐서의 모양이 연산에 맞지 않는다는 뜻입니다.

대표적인 상황은 이미지 데이터를 펼치지 않고 Linear 계층에 넣는 경우입니다. 예를 들어 FashionMNIST 이미지는 보통 [batch, 1, 28, 28] 모양입니다. 하지만 nn.Linear(784, 128)은 [batch, 784] 모양을 기대합니다. 이때는 모델 안에서 펼쳐야 합니다.

x = x.view(x.size(0), -1)

오류를 고칠 때는 각 단계마다 모양을 출력해 보세요.

print(x.shape)
x = self.flatten(x)
print(x.shape)
logits = self.classifier(x)
print(logits.shape)

좋은 습관은 "데이터셋에서 나온 모양 → 모델 입력 모양 → 모델 출력 모양 → 라벨 모양"을 순서대로 확인하는 것입니다. 분류 문제라면 보통 모델 출력은 [batch, class_count], 라벨은 [batch] 형태가 됩니다.

device 오류: 모델과 데이터가 다른 장치에 있는 경우

Expected all tensors to be on the same device라는 오류는 모델은 GPU에 있고 데이터는 CPU에 있거나, 그 반대일 때 발생합니다. PyTorch에서는 같은 연산에 참여하는 텐서들이 같은 장치에 있어야 합니다.

해결 방법은 모델과 배치를 같은 device로 보내는 것입니다.

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)

for inputs, labels in train_loader:
    inputs = inputs.to(device)
    labels = labels.to(device)
    outputs = model(inputs)

오류가 계속 나면 다음을 확인합니다.

print(next(model.parameters()).device)
print(inputs.device, labels.device)

모델의 일부 텐서를 직접 만들 때도 주의해야 합니다. 예를 들어 학습 중 새 텐서를 만들면 기본적으로 CPU에 만들어질 수 있습니다. 이때는 device=inputs.device를 지정하거나, 만든 뒤 .to(device)를 적용합니다.

dtype 오류: 손실 함수가 원하는 자료형 확인하기

dtype은 텐서 안의 숫자 자료형입니다. 손실 함수마다 기대하는 입력 조건이 다릅니다. 특히 CrossEntropyLoss에서 자주 실수합니다.

다중 분류에서 nn.CrossEntropyLoss()를 사용할 때 모델 출력은 정규화하지 않은 점수인 logits여야 하고, 라벨은 클래스 번호여야 합니다. 라벨의 dtype은 반드시 torch.long이어야 합니다.

labels = labels.long()
loss = criterion(outputs, labels)

예를 들어 10개 클래스를 분류한다면 outputs.shape은 [batch, 10], labels.shape은 [batch]가 자연스럽습니다. 라벨을 원-핫 벡터처럼 [batch, 10]으로 만들면 초보 단계에서는 오히려 오류가 나기 쉽습니다.

반대로 회귀 문제에서 MSELoss를 쓴다면 예측값과 정답값이 보통 실수형이어야 합니다.

targets = targets.float()

오류 메시지에 Long, Float, expected scalar type 같은 단어가 보이면 dtype 문제를 먼저 의심하세요.

GPU memory 오류: 한 번에 너무 많이 올린 경우

CUDA out of memory는 GPU 메모리가 부족하다는 뜻입니다. 가장 효과적인 해결책은 batch_size를 줄이는 것입니다. 배치 크기를 절반으로 줄이면 한 번에 처리하는 데이터가 줄어 메모리 사용량도 줄어듭니다.

그다음 확인할 것은 불필요한 텐서를 계속 보관하고 있지 않은지입니다. 학습 중 매번 loss나 outputs를 리스트에 그대로 저장하면 계산 그래프까지 함께 남아 메모리를 많이 사용할 수 있습니다. 기록용 값은 .item()으로 숫자만 저장하는 편이 안전합니다.

loss_values.append(loss.item())

평가나 추론에서는 기울기 계산이 필요 없으므로 torch.no_grad()를 사용합니다.

with torch.no_grad():
    outputs = model(inputs)

torch.cuda.empty_cache()는 PyTorch가 잡아 두고 있는 사용하지 않는 캐시 메모리를 비우는 함수입니다. 하지만 현재 필요한 텐서의 메모리를 줄여 주지는 않습니다. 따라서 근본 해결책은 배치 크기 줄이기, 모델 크기 줄이기, 불필요한 텐서 참조 제거입니다.

in-place 연산은 조심해서 사용하기

x += 1, relu_(), add_()처럼 기존 텐서 값을 직접 바꾸는 연산을 in-place 연산이라고 합니다. 메모리를 조금 아낄 수 있지만, autograd가 역전파에 필요한 중간 값을 추적하는 과정과 충돌할 수 있습니다.

오류 메시지에 inplace operation이나 modified by an inplace operation이 보이면 최근에 사용한 밑줄(_)이 붙은 함수나 += 연산을 확인하세요.

초보 단계에서는 꼭 필요한 경우가 아니라면 in-place 연산을 피하는 편이 좋습니다.

# 조심해야 하는 형태
x += 1
x = torch.relu_(x)

# 더 안전한 형태
x = x + 1
x = torch.relu(x)

오류를 고치는 순서

오류가 났을 때는 다음 순서로 확인하면 됩니다.

  1. 오류가 난 줄 바로 앞에서 shape, dtype, device를 출력한다.

  2. 모델 입력과 출력의 shape가 의도와 맞는지 본다.

  3. 라벨의 dtype이 손실 함수 조건과 맞는지 본다.

  4. 모델과 데이터가 같은 device에 있는지 확인한다.

  5. GPU 메모리 오류라면 batch size부터 줄인다.

  6. autograd 오류라면 in-place 연산을 의심한다.

PyTorch 실력은 오류를 한 번도 만나지 않는 데서 생기지 않습니다. 오류 메시지를 읽고, 텐서의 상태를 확인하고, 원인을 좁혀 가는 과정에서 실력이 쌓입니다. 막혔을 때는 먼저 출력해 보세요. 대부분의 답은 텐서의 모양, 자료형, 장치 안에 있습니다.

책 목록

초보자를 위한 PyTorch 사용법: 텐서부터 이미지 분류 프로젝트까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기