파이토치에서 사용하는 텐서는 여러가지 형태로 차원을 변환할 수 있다. 차원의 추가, 삭제도 포함이다.
여기서는 squeeze, unsqueeze, view, reshape, traspose, permute를 알아본다.
1. unsqueeze
지정된 위치에 크기가 1일 차원을 추가
import torch
x = torch.tensor([[1, 2, 3],
[4, 5, 6]])
x.shape
>> torch.Size([2, 3])
y = x.unsqueeze(0)
y, y.shape
>> (tensor([[[1, 2, 3],
[4, 5, 6]]]),
torch.Size([1, 2, 3]))
y = x.unsqueeze(1)
y, y.shape
>>(tensor([[[1, 2, 3]],
[[4, 5, 6]]]),
torch.Size([2, 1, 3]))
y = x.unsqueeze(2)
y, y.shape
>> (tensor([[[1],
[2],
[3]],
[[4],
[5],
[6]]]),
torch.Size([2, 3, 1]))
2. squeeze
크기가 1인 차원을 제거. 디폴트는 모든 차원의 제거다.
특정 차원의 제거만 지정할 수 있다.
크기가 1인 차원이 없으면 아무 변화도 없다.
x = torch.tensor([[1, 2, 3],
[4, 5, 6]])
y = x.squeeze(0)
y, y.shape
# 크기가 1인 차원이 없어서 변화 없음
>> (tensor([[1, 2, 3],
[4, 5, 6]]),
torch.Size([2, 3]))
y = x.unsqueeze(2)
y = y.squeeze()
y, y.shape
# 2차원 추가 후 제거
>> (tensor([[1, 2, 3],
[4, 5, 6]]),
torch.Size([2, 3]))
y = x.unsqueeze(2)
y = y.squeeze(0)
y, y.shape
# 2차원 추가 후 0차원 제거
# 변화 없음
>>(tensor([[[1],
[2],
[3]],
[[4],
[5],
[6]]]),
torch.Size([2, 3, 1]))
x = torch.tensor([[1, 2, 3],
[4, 5, 6]])
y = x.unsqueeze(2)
y = x.unsqueeze(0)
y = y.squeeze()
y, y.shape
# 0번째와 2번째에 차원 추가 후 제거
# 1인 차원을 모두 제거해서 원래와 동일하다
>> (tensor([[1, 2, 3],
[4, 5, 6]]),
torch.Size([2, 3]))
3. reshape
텐서의 모양을 변경한다.
내부적으로 텐서를 복사하기 때문에 view 보다 오버헤드가 발생할 수 있다.
x = torch.tensor([[1, 2, 3],
[4, 5, 6]])
# 2 x 3 -> 3 x 2
x.reshape(3, 2)
>> tensor([[1, 2],
[3, 4],
[5, 6]])
4. view
텐서의 모양을 변경한다는 목적은 reshape와 같다.
하지만 텐서의 데이터를 변경하지 않으며 메모리 상에서 데이터가 연속적으로 저장되어 있어야 한다.
이를 위해서 contiguous() 메소드의 호출이 반쯤 필수다.
pytorch나 huggingface의 여러 모델들의 소스 코드를 뜯어 보면 나오는 contiguous()의 적용 이유기도 하다.
x.contiguous().view(3, 2)
>> tensor([[1, 2],
[3, 4],
[5, 6]])
5. transpose
지정된 두 차원을 서로 교환한다.
x.transpose(0, 1)
>> tensor([[1, 4],
[2, 5],
[3, 6]])
# 3차원 텐서 (크기: [2, 3, 4])
z = torch.randn(2, 3, 4)
print("Shape of z:", z.shape)
>> Shape of z: torch.Size([2, 3, 4])
# 차원 1과 차원 2를 서로 바꿈 (크기: [2, 4, 3])
w = z.transpose(1, 2)
print("Shape of w:", w.shape)
>> Shape of w: torch.Size([2, 4, 3])
6. permute
텐서의 모든 차원을 원하는 순서대로 변경한다.
# 3차원 텐서 (크기: [2, 3, 4])
x = torch.randn(2, 3, 4)
print("Shape of x:", x.shape)
>> Shape of x: torch.Size([2, 3, 4])
# 차원의 순서를 (1, 0, 2)로 변경 (크기: [3, 2, 4])
y = x.permute(1, 0, 2)
print("Shape of y:", y.shape)
>> Shape of y: torch.Size([3, 2, 4])
# 차원의 순서를 (2, 0, 1)로 변경 (크기: [4, 2, 3])
z = x.permute(2, 0, 1)
print("Shape of z:", z.shape)
>> Shape of z: torch.Size([4, 2, 3])
3차원 이상의 텐서는 점차 복잡해지기 때문에 einops나 einsum을 활용하면 기호로 나타내어 permute나 tensor 곱을 편하게 할 수 있다. 이는 나중에 다루고자 한다.
References:
https://pytorch.org/docs/stable/generated/torch.reshape.html
'AI Codes > PyTorch' 카테고리의 다른 글
nanoGPT, PyTorch DDP, LLM 시각화 (0) | 2025.04.18 |
---|---|
PyTorch pre-trained Models (0) | 2025.04.17 |
ML와 DL에서의 seed 고정 (0) | 2025.01.02 |
PyTorch repeat, repeat_interleave, expand 차이 (0) | 2024.11.01 |
ResNet (2016) PyTorch Implementation (0) | 2024.04.24 |