← 보드Tensor · 6/11
모양 바꾸기 — reshape와 view ★★
reshape는 값(원소 수)은 그대로 두고 모양만 바꿔요. 원소가 12개면 (12,), (3, 4), (2, 6), (2, 2, 3) 모두 가능해요. 하지만 원소 수가 달라지는 모양은 안 돼요. 곱이 12가 안 되면 에러예요.
x = torch.arange(12)
print(x.reshape(3, 4))
print(x.reshape(-1, 4).shape)
print(x.reshape(2, 2, 3).shape)
y = torch.arange(24)
print(y.reshape(4, -1).shape)
print(y.reshape(2, 3, -1).shape)
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
torch.Size([3, 4])
torch.Size([2, 2, 3])
torch.Size([4, 6])
torch.Size([2, 3, 4])
| 코드 줄 | 무슨 뜻 |
|---|---|
x.reshape(3, 4) | 0~11을 순서대로 3행 4열 표에 채워요 |
x.reshape(-1, 4) | -1은 "이 자리는 알아서 계산해 줘"예요. 12 ÷ 4 = 3이라 (3, 4) |
y.reshape(4, -1) | 24 ÷ 4 = 6이라 (4, 6) |
y.reshape(2, 3, -1) | 24 ÷ (2×3) = 4이라 (2, 3, 4) |
-1은 한 자리에만 쓸 수 있어요. 나머지 숫자를 곱해서 전체 원소 수를 나누면 그 값이에요. reshape(5, 3)처럼 원소 수가 안 맞으면 "shape이 입력 크기 12에 맞지 않다"는 RuntimeError가 나요.
view도 모양을 바꾸는 함수인데, 차이는 아래 표와 같아요.
| 함수 | 메모리 공유 보장 | 메모리가 연속(contiguous)이 아닐 때 |
|---|---|---|
reshape() | 보장 안 함 (필요하면 복사본을 만들어요) | 사용 가능 (더 유연해서 안전해요) |
view() | 공유함 | 사용 불가 (에러) |
"연속"은 값이 메모리에 순서대로 붙어 있다는 뜻이에요. transpose(행과 열 바꾸기)를 하면 읽는 순서만 바뀌고 메모리 배치는 그대로라서 연속이 아니게 돼요. 이때 view(-1)은 에러, reshape(-1)은 성공이에요.
x = torch.arange(12).reshape(3, 4)
y = x.transpose(0, 1)
print(y.is_contiguous())
print(y.reshape(-1))
False
tensor([ 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11])
| 코드 줄 | 무슨 뜻 |
|---|---|
x.transpose(0, 1) | 0번 차원과 1번 차원을 맞바꿔요. (3, 4)가 (4, 3)이 돼요 |
y.is_contiguous() | 연속인지 묻는 질문. 바꾼 뒤라서 False |
y.reshape(-1) | -1 하나이니 전부 한 줄로 펴요. y를 위에서 아래로(열 순서로) 읽은 0, 4, 8, 1, 5, 9, …가 나와요 |
시험엔 이렇게 써요 — 이렇게 고르세요
reshape()와 view()는 원소 수를 유지하면서 shape을 바꾸며, -1을 쓰면 해당 차원의 크기가 자동 계산된다. view()는 메모리가 연속이어야만 동작하고 reshape()는 필요하면 복사하므로 더 유연하다. 계산 문제는 "나머지 숫자를 곱해서 전체 개수를 나눈 값"이 -1 자리예요.
잠깐 확인 — 원소 30개짜리 Tensor를 reshape(5, -1)하면 shape은?
(5, 6)이에요. 30 ÷ 5 = 6이에요.
다음 카드 → 크기 1인 차원 다루기 — squeeze, unsqueeze, cat, stack ★★
자료: 2주차 · Week02_Tensor_and_GPU(pdf, 풀이포함 ipynb) · 빅분02(2주차) 녹취