본문 바로가기

[PyTorch] Tensor Manipulation 2

Derrick 발행일 : 2022-04-04
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.]])

댓글