똑같이 보이는데 안 같은 두 가지
NumPy 에서 이 둘은 다른 객체:
np.array(5) # 0-D 배열 — shape ()
np.array([5]) # 1-D 배열 — shape (1,)
둘 다 5 로 출력. 둘 다 값 하나. 같은 게 아니야. 0-D 는 배열 옷 입은 스칼라. 1-D 는 list-of-one. AI 라이브러리는 다르게 다뤄 — 그리고 대부분 1-D 를 선호.
둘을 구분해주는 에러
- 0-D 인덱싱:
scalar_in_array[0]→IndexError. 인덱스할 축 없음. - 0-D 순회:
for x in scalar_in_array→TypeError. 순회할 게 없음. - 대부분의 행렬 연산:
scalar_in_array @ matrix→ 모양 에러. 최소 1축 필요.
1-D 버전은 셋 다 깔끔히 처리. 이거 먼저 설명 안 하는 AI 튜토리얼이 너를 broadcasting 에러로 피흘리게 두는 이유.
universal 해결책
스칼라 있는데 모델/라이브러리/배치 연산에 먹여야 할 때: 먼저 1-D 로 업그레이드. PyTorch 는 scalar.unsqueeze(0). NumPy 는 np.array([scalar]) 또는 np.expand_dims(scalar, 0). 반대 (출력/비교용으로 1-D → 0-D) 는 tensor.squeeze().
피파의 war story
loss.backward() 에 직접 넘겼어. PyTorch 가 받아. 다음 epoch 에서 list 로 로깅하려는데 — "0-d tensor has no len()". 20분 동안 옵티마이저 탓했어. 해결은 .unsqueeze(0) 한 번. 이젠 모든 스칼라가 본능적으로 unsqueeze 돼, 사소해 보여도.
import torch# STEP 1: 0-D 텐서 생성t = torch.tensor(3.14)print(t)print(t.shape)print(t.ndim)# STEP 2: t[0] 인덱싱 시도 - 에러 발생try:print(t[0])# IndexError: invalid index of a 0-dim tensor# 스칼라값은 차원이 없다. 위치를 담을 수 없으니 인덱싱 오류except IndexError as e:print(f"IndexError: {e}")# STEP 3: unsqueeze로 1-D 업그레이드t_1d = t.unsqueeze(0)print(t_1d)print(t_1d.shape)print(t_1d.ndim)# STEP 4: 인덱싱 작동print(t_1d[0])