AI |Computer Vision/Basic Pytorch
[PyTorch] Tensor Manipulation 2
Derrick
2022. 4. 4. 14:00
728x90
반응형
1. PyTorch Tensor의 기본 연산
→ View, Squeeze, Unsqeeze, Type casting, Concatenate 등의 기초적인 텐서 연산하기
1) View - Tensor의 size 조절 ( 매우 중요 ★★★ )
Pytorch View(뷰)는 "Tensor의 shape를 변경"해주는 역할을 수행한다.
→ view는 size 변경 전과 후의 Tensor 안의 원소 개수가 유지되어야 한다.
→ Pytorch의 view는 size가 -1로 설정되면, 해당 차원은 무시하고 다른 차원으로부터 값을 유추
- 3차원 Tensor에서 2차원 Tensor로 변경
import torch
ft = torch.FloatTensor([[[0, 1, 2], # 3차원의 Tensor 생성(ft)
[3, 4, 5]],
[[6, 7, 8],
[9, 10, 11]]])
print(ft.shape) # ft Tensor size
print(ft.view([-1, 4])) # 3차원 Tensor(2,2,3)를 (?, 4)의 size로 변경
print(ft.view([-1,4]).shape)
>>
torch.Size([2, 2, 3])
tensor([[ 0., 1., 2., 3.], # 원소의 개수와 값은 유지
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
torch.Size([3, 4]) # (2, 2, 3) -> (3, 4)
→ view([-1. 4]) : 2번째 차원의 길이는 4로 유지하고, 첫번째 차원에 길이 몰빵
→ view의 size가 ' -1 '로 설정되면, 그 외 차원값은 자동으로 유추됨
- 3차원의 Tensor size 변경
print(ft.view([-1, 1, 3])) # (2 x 2 x 3) -> (? x 1 x 3)로 변경
print(ft.view([-1, 1, 3]).shape)`
>>
tensor([[[ 0., 1., 2.]],
[[ 3., 4., 5.]],
[[ 6., 7., 8.]],
[[ 9., 10., 11.]]])
torch.Size([4, 1, 3]) # (4, 1, 3) 으로 변경된 것 확인
→ 변경 전, Tensor 원소의 수는 (2 x 2 x 3) = 12개
→ 변경 후, Tensor 원소의 수는 (4 x 1 x 3) = 12개 (원소의 수 동일)
2) Squeeze(스퀴즈)
Squeeze( )는 차원이 1인 경우에 해당 차원을 제거합니다.
→ element가 1인 경우와 차원이 1인 경우는 다르다! ( 구분 필요 )
ft = torch.FloatTensor([[1], [2], [3]])
print(ft)
print(ft.shape)
# Squeeze() 적용
print(ft.squeeze()) # 2번째 차원이 1이므로 squeeze 적용하면 제거됨
print(ft.squeeze().shape)
>>
tensor([[1.],
[2.],
[3.]])
torch.Size([3, 1]) # (3, 1) size의 2차원 Tensor 생성
# Squeeze() 적용
tensor([1., 2., 3.]) # 1차원 Vector로 변경됨
torch.Size([3]) # (3, 1) -> (3,)
3) Unsqueeze(언스퀴즈)
→ 특정 위치에 1인 차원을 추가하는 함수
ft = torch.FloatTensor([1, 2, 3])
print(ft.shape)
# Unsqueeze() 적용 - 1
print(ft.unsqueeze(0)) # 첫번째 차원(0)에 1인 차원 추가
print(ft.unsqueeze(0).shape)
# view()로 unsqueeze 효과 구현
print(ft.view(1, -1)) # 1차원을 1로 두고, 2차원을 변경
print(ft.view(1, -1).shape)
# Unsqueeze() 적용 - 2
print(ft.unsqueeze(1)) # 두번째 차원(1)에 1인 차원 추가
print(ft.unsqueeze(1).shape)
>>
torch.Size([3])
# Unsqueeze() 적용 - 1
tensor([[1., 2., 3.]])
torch.Size([1, 3]) # (3,) -> (1, 3)
# view()로 구현
tensor([[1., 2., 3.]])
torch.Size([1, 3]) # (3,) -> (1, 3)
# Unsqueeze() 적용 - 2
tensor([[1.],
[2.],
[3.]])
torch.Size([3, 1]) # (3,) -> (3, 1)
4) Type Casting (타입 캐스팅)
→ Tensor의 자료형 변환 (Float, Long, cuda 등)

lt = torch.LongTensor([0, 1, 2, 3]) # Long 타입의 Tensor 선언(lt)
bt = torch.ByteTensor([True, False, True, False]) # Byte 타입의 Tensor 선언(bt) - Boolean 값 저장
print(lt)
print(lt.float()) # Long -> Float
print(bt.long()) # Byte -> Long
print(bt.float()) # Byte -> float
>>
tensor([0, 1, 2, 3])
tensor([0., 1., 2., 3.])
tensor([1, 0, 1, 0])
tensor([1., 0., 1., 0.])
5) Concatenate (이어붙이기) - cat([ ])
→ 두 개의 Tensor을 연결하는 기법. ( 입력 데이터를 붙일때 자주 활용 )
# (2 x 2) size의 Tensor 선언
a = torch.FloatTensor([[1, 2], [3, 4]])
b = torch.FloatTensor([[5, 6], [7, 8]])
# Concatenate로 연결
t1 = torch.cat([a, b], dim=0) # 첫번째 차원(dim=0) 기준에서 늘리기
print(t1, t1.shape)
t2 = torch.cat([a, b], dim=1) # 두번째 차원(dim=1) 기준에서 늘리기
print(t2, t2.shape)
>>
tensor([[1., 2.],
[3., 4.],
[5., 6.],
[7., 8.]]) torch.Size([4, 2]) # (2, 2) -> (4, 2)
tensor([[1., 2., 5., 6.],
[3., 4., 7., 8.]]) torch.Size([2, 4]) # (2, 2) -> (2, 4)
6) Stacking (스태킹) - stack([ ])
→ 2개 이상의 Tensor를 쌓는 기법
# (2,) size의 1차원 Vector 선언
t1 = torch.FloatTensor([1, 2])
t2 = torch.FloatTensor([3, 4])
t3 = torch.FloatTensor([5, 6])
# stack 적용
print(torch.stack([t1, t2, t3])) # 첫번째 차원(dim=0) 기준으로 쌓기 - default
print(torch.stack([t1, t2, t3]).shape)
print(torch.stack([t1, t2, t3], dim=1)) # 두번째 차원(dim=1) 기준으로 쌓기
print(torch.stack([t1, t2, t3], dim=1).shape)
>>
tensor([[1., 2.],
[3., 4.],
[5., 6.]])
torch.Size([3, 2]) # (2,) -> (3, 2)
tensor([[1., 3., 5.],
[2., 4., 6.]])
torch.Size([2, 3]) # (2,) -> (2, 3)
7) Ones_like & Zeros_like
→ '0' 으로 채워진 Tensor & '1' 로 채워진 Tensor (크기 유지)
# (2 x 3) size의 Tensor 선언
a = torch.FloatTensor([[0, 1, 2], [3, 4, 5]])
print(a)
print(torch.ones_like(a)) # 1로만 채워진 Tensor 생성 (동일한 크기)
print(torch.zeros_like(a)) # 0으로만 채워진 Tensor 생성
>>
tensor([[0., 1., 2.],
[3., 4., 5.]])
tensor([[1., 1., 1.], # ones_like
[1., 1., 1.]])
tensor([[0., 0., 0.], # zeros_like
[0., 0., 0.]])
8) In_place Operation ( 연산 뒤에 ' _ ' 추가 )
→ 연산을 수행하고 기존값에 연산한 결과를 덮어쓸 때 적용
# (2 x 3) Tensor 선언
a = torch.FloatTensor([[1, 2], [3, 4]])
print(a.mul(3.)) # 2를 곱한 결과 출력
print(a)
print(a.mul_(3.)) # 2를 곱한 결과를 'a'에 저장하고 출력
print(a)
>>
tensor([[ 3., 6.],
[ 9., 12.]])
tensor([[1., 2.], # 연산 전의 기존 값 출력
[3., 4.]])
tensor([[ 3., 6.],
[ 9., 12.]])
tensor([[ 3., 6.], # 연산 후의 변경 값 출력
[ 9., 12.]])