티스토리 뷰

학습 데이터를 점차 늘려가며 트랜스포머 모델을 학습하고 있었다.

특정 시점에서 아래와 같은 오류가 났고 혹시 GPU메모리 부족인가 싶어 학습 중 메모리를 확인하는 코드를 추가해보았다. 하지만 메모리는 충분했고 텐서 크기가 너무 커서 버티지 못한 것으로 생각했다.

RuntimeError: CUDA error: invalid configuration argument
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1
Compile with TORCH_USE_CUDA_DSA to enable device-side assertions.

 

배치 사이즈나 look back 파라미터를 조절하는 것으로는 되지 않았다. 

GPU 커널을 호출할 때 grid·block 크기가 한계치를 초과해서 생깁니다.
지금 코드에서 그 원인은 “검증·테스트 텐서를 한꺼번에 GPU에 올려서” 배치 크기가 수십-만~수백-만으로 커지기 때문입니다.
Conv 1D·Attention 커널은 gridDim.x ≤ 65535 같은 제약이 있는데, 한 번에 수십만 시퀀스를 넘기면 바로 이 오류가 납니다(OOM 대신). 라고 한다. 

바꾼 부분은 다음과 같다.

best_loss, patience_cnt = float('inf'), 0
for ep in range(1, EPOCHS+1):
    model.train()
    for xb, yb in train_loader:
        xb, yb = xb.to(device), yb.to(device)
        loss = crit(model(xb), yb)
        optim.zero_grad(); loss.backward(); optim.step()

    model.eval()
    with torch.no_grad():
        val_loss = crit(model(test_X_t), test_y_t).item()

    print(f'Epoch {ep:03d} | val MSE {val_loss:.6f}')
    if val_loss < best_loss:          # improvement
        best_loss, patience_cnt = val_loss, 0
        best_state = model.state_dict()
    else:
        patience_cnt += 1
        if patience_cnt >= PATIENCE:
            print(f'⏹ Early stop at epoch {ep}')
            break

model.load_state_dict(best_state)

# ──────────────────── 6. 예측 & 역정규화 ────────────────────
model.eval()
with torch.no_grad():
    pred = model(test_X_t).cpu().numpy()
true = test_y_t.cpu().numpy()

y_pred = y_scaler.inverse_transform(pred)
y_true = y_scaler.inverse_transform(true)

print('MAE :', mean_absolute_error(y_true, y_pred))
print('R^2 :',  r2_score(y_true,  y_pred))
# 1️⃣ 테스트 DataLoader
test_loader = DataLoader(test_ds, batch_size=BATCH_SIZE, shuffle=False)

# 2️⃣ 학습 루프 안의 검증 손실 계산 (메모리 safe)
def eval_mse(loader):
    mse, n = 0.0, 0
    with torch.no_grad():
        for xb, yb in loader:
            xb, yb = xb.to(device), yb.to(device)
            mse += crit(model(xb), yb).item() * len(xb)
            n   += len(xb)
    return mse / n              # 평균 MSE

best_loss, patience_cnt = float('inf'), 0
for ep in range(1, EPOCHS+1):
    model.train()
    for xb, yb in train_loader:
        xb, yb = xb.to(device), yb.to(device)
        loss = crit(model(xb), yb)
        optim.zero_grad(); loss.backward(); optim.step()

    val_loss = eval_mse(test_loader)
    print(f'Epoch {ep:03d} | val MSE {val_loss:.6f}')

    if val_loss < best_loss:
        best_loss, patience_cnt = val_loss, 0
        best_state = model.state_dict()
    else:
        patience_cnt += 1
        if patience_cnt >= PATIENCE:
            print(f'⏹ Early stop at epoch {ep}')
            break

model.load_state_dict(best_state)

# 3️⃣ 예측도 배치로 모아서 → 역정규화
pred_list, true_list = [], []
model.eval()
with torch.no_grad():
    for xb, yb in test_loader:
        pred_list.append(model(xb.to(device)).cpu())
        true_list.append(yb)

y_pred = y_scaler.inverse_transform(torch.cat(pred_list).numpy())
y_true = y_scaler.inverse_transform(torch.cat(true_list).numpy())
print('MAE :', mean_absolute_error(y_true, y_pred))
print('R²  :', r2_score(y_true,  y_pred))

 

변경 전 변경 후 차이

test_X_t = torch.stack([...]) → 한 번에 수백 MB~GB 전송 DataLoader로 64개씩 스트리밍
검증 손실 계산을 model(test_X_t) 한 방에 eval_mse() 함수로 배치별 accumulate
예측 시 model(test_X_t) for xb in test_loader: 반복

 

이것만으로 해결되다니 o3는 천재야

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함