본문 바로가기

[PyTorch] Tensor Manipulation 1

Derrick 발행일 : 2022-03-29
728x90
반응형

1. Tensor 이해하기

[ Vector, Matrix and Tensor ]

< 딥러닝의 가장 기본적인 단위 >

  • 1D : Vector (벡터)
  • 2D : Matrix (행렬)
  • 3D : Tensor (텐서) - 주로 3차원 이상을 Tensor로 분류
  • 4D : 3차원의 텐서를 위로 쌓아 올린 형상 - 이후 차원은 옆/뒤로 확장한 모습

2. Pytorch Tensor Shape Convention

 Matrix, Tensor들에 대해 " 크기를 구하는 것 "이 중요하다.
 정확한 크기를 고려해야 제대로 구현할 수 있으며, 수식을 쉽게 이해할 수 있다.

 

[ 2D / 3D Tensor ]

< Tensor Size >

  • 2D Tensor : |t| = ( batch size, dim )
  • 3D Tensor : |t| = ( batch size, width, height )
    → 여기부터는 조금 더 복잡한 형태의 입력과 출력을 다룰 수 있다.
    ex) 이미지의 경우, ('가로 X 세로')의 set이 여러 개가 쌓이면 3D Tensor 구성

3. PyTorch로 Tensor 선언

 → PyTorch는 Numpy 방식과 매우 유사하며, 지금부터 간단한 Tensor 선언

1) 1D Tensor

  • 1차원의 Tensor인 Vector 생성
import torch 
a = torch.FloatTensor([0.1, 1., 2., 3., 4., 5., 6.]) 
print(a) 
print(a.dim())                                     # dimension 
print(a.shape)                                     # Tensor의 size

 

>>
tensor([0.1000, 1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000])
1                                        # 1차원 텐서
torch.Size([7])                          # Tensor 사이즈는 7, 원소는 7개



  • Indexing과 Slicing 연습!
print(a[-1], a[0], a[1])                         # indexing 
print(a[1:5], a[3:-1])                           # Slicing 
print(a[:3], a[3:])                              # Slicing`

 

>>
tensor(6.) tensor(0.1000) tensor(1.)
tensor([1., 2., 3., 4.]) tensor([3., 4., 5.])
tensor([0.1000, 1.0000, 2.0000]) tensor([3., 4., 5., 6.])

 
 → Slicing : 범위 지정(index)으로 원소를 불러오기
 → [시작 번호 : 끝 번호], 끝 번호는 해당하지 않는다!

 

2) 2D Tensor

  • 2차원의 Tensor인 Matrix 생성
b = torch.FloatTensor([[1., 2., 3.,],
                      [4., 5., 6.,],
                      [7., 8., 9.,],
                      [10., 11., 12.]
                      ])
print(b)
print(b.dim())                        # dimension
print(b.size())                       # tensor.size

 

>>
tensor([[ 1.,  2.,  3.],
      [ 4.,  5.,  6.],
      [ 7.,  8.,  9.],
      [10., 11., 12.]])
2                                     # 2차원의 Tensor 
torch.Size([4, 3])                    # (4, 3)

 

  • Slicing
print(b[:, 2])            # 첫번째 차원을 모두 선택하고, 2번째 차원의 2번째 것만 가져온다
print(b[:, 2].size())     # 위의 결과의 size
print(b[:-1,:])           # 두번째 차원을 모두 선택하고, 1차원의 맨 마지막 것을 제외하고 모두 가져온다

 

>>
tensor([ 3.,  6.,  9., 12.])
torch.Size([4])
tensor([[1., 2., 3.],
      [4., 5., 6.],
      [7., 8., 9.]])

 


3. Tensor 연산하기 및 다양한 기능

1) Broadcasting

 덧셈/뺄셈의 연산을 수행할 때의 Tensor의 크기는 동일해야 하지만, 불가피하게 다른 크기의
 Tensor들을 연산하는 상황에서 Pytorch에서는 자동으로 size을 맞춰서 연산 수행한다.

 

  • Vector + Scalar
# vector + scalar
m1 = torch.FloatTensor([[1, 2]])
m2 = torch.FloatTensor([3])            # [3] -> [3, 3] : Broadcasting
print(m1.size(), m2.size())            # m1, m2의 다른 size 확인
print(m1 + m2)

 

>>
torch.Size([1, 2]) torch.Size([1])
tensor([[4., 5.]])

 

  • 2x1 Vector + 1x2 Vector
# 2x1 Vector + 1x2 Vector
m1 = torch.FloatTensor([[1, 2]])              # (1, 2) -> (2, 2)
m2 = torch.FloatTensor([[3], [4]])            # (2, 1) -> (2, 2)
print(m1.size(), m2.size())
print(m1 + m2)
print((m1+m2).size())

 

>>
torch.Size([1, 2]) torch.Size([2, 1])
tensor([[4., 5.],
      [5., 6.]])
torch.Size([2, 2])

 

2) Matrix Multiplication(행렬곱) vs Multiplication(일반곱)

  • Matrix Multiplication ( Tensor의 행렬곱셈 - matmul() )
m1 = torch.FloatTensor([[1, 2], [3, 4]])
m2 = torch.FloatTensor([[1], [2]])
print(m1.shape)               # m1의 size : (2, 2)
print(m2.shape)               # m2의 size : (2, 1)
print(m1.matmul(m2))          # (2, 1)로 size 변경됨

 

>>
torch.Size([2, 2])
torch.Size([2, 1])
tensor([[ 5.],
      [11.]])

 

  • Multiplication ( Tensor 내 각 element의 곱셈 - mul() )
print(m1 * m2)                    # 2 x 2 
print(m1.mul(m2))    
print((m1.mul(m2)).size())

 

>>
tensor([[1., 2.],
        [6., 8.]])
tensor([[1., 2.],
        [6., 8.]])
torch.Size([2, 2])                # m2의 size : (2, 1) -> (2, 2)

 
 → 일반 곱셈(mul)을 수행하면, 두 행렬의 크기는 broadcasting된 후에 곱셈 수행

3) 평균 (Mean) - .mean()

a = torch.FloatTensor([1, 2])
b = torch.FloatTensor([[1, 2], [3, 4]])
print(a.mean())               # a의 평균값 = (1+2)/2

print(b.mean(dim=0))          # 첫번째 차원(행)을 제거하고 평균 - [ (1+3)/2 , (2+4)/2 ]
print(b.mean(dim=1))          # 두번째 차원(열)을 제거하고 평균
print(b.mean(dim=-1))         # 마지막 차원(= 열)을 제거하고 평균

 

>>
tensor(1.5000)
tensor([2., 3.])
tensor([1.5000, 3.5000])
tensor([1.5000, 3.5000])

 
 → 인자로 dim 값을 준다면, 해당 차원을 제거한다는 의미
 → 2x2 Matrix에서 행(dim = 1)을 제거하면, (1, 2) = (2,)의 Vector가 됨.

4) 합계(Sum)과 최대값(Max, ArgMax)

  • 합계(Sum)
a = torch.FloatTensor([[1, 2], [3, 4]])
print(a.sum())

print(a.sum(dim=0))         # 행 제거   
print(a.sum(dim=1))         # 열 제거
print(a.sum(dim=-1))        # 마지막 차원(= 열) 제거

 

>>
tensor(10.)
tensor([4., 6.])
tensor([3., 7.])
tensor([3., 7.])

 

  • Max, ArgMax
a = torch.FloatTensor([[1, 2], [3, 4]])
print(a)

print(a.max())              # 전체 element 중, 최대값 하나 출력
print(a.max(dim=0))         # max, argmax 두 값을 출력 (행 차원 제거)

 

>>
tensor([[1., 2.],
        [3., 4.]])
tensor(4.)
torch.return_types.max(
values=tensor([3., 4.]),           # dim = 0을 배제 후, 얻은 최대값
indices=tensor([1, 1]))            # 최대값의 해당 index값

 
 → Max는 원소들 중 최대값을 return하고, ArgMax는 최대값을 가진 index를 return 한다.
 → max와 argmax만 따로 return 받고 싶다면 인덱스를 별도 부여하면 된다.

 

print('Max :',a.max(dim=0)[0])            # 0번 인덱스 : max 값만 
print('ArgMax :',a.max(dim=0)[1])         # 1번 인덱스 : argmax 값만

 

>>
Max : tensor([3., 4.])
ArgMax : tensor([1, 1])

댓글