Python

Pytorch의 tensor 다루기

qlsenddl 2020. 11. 7. 16:33
728x90

 PyTorch는 Deep Learning Framework 중 하나로 주로 research 분야에서 많이 사용되는 것으로 알려져있다. PyTorch에서는 tensor를 사용하는데 이 tensor는 PyTorch의 기본적인 data structure라고 생각하면 된다.

 tensor는 numpy와 비슷하게 n 차원 배열을 다룬다. 하지만 Deep Learning의 특성 상 계산량이 많아 보통 GPU에서 계산해야 하는데, numpy와 다르게 PyTorch의 tensor는 GPU에서 계산할 수 있기 때문에 Deep Learning Model을 사용할 때, 이 tensor를 사용한다.


 PyTorch를 사용하기 위해서는 자신의 GPU driver 버전에 맞는 CUDA 및 CuDNN을 설치해야 하고, PyTorch의 설치는 https://qlsenddl-lab.tistory.com/12 에서 확인할 수 있다. CUDA 및 CuDNN 설치는 여기서 다루지 않고, PyTorch가 이미 설치됐다고 가정하고 작성한다.


import torch 를 입력해서 PyTorch의 tensor를 사용할 수 있다.

설치된 PyTorch는 torch.__version__를 통해 확인할 수 있다.


1. tensor 선언하기

torch.tensor(a): a에 대한 tensor를 선언한다.

ex>

a = torch.tensor([[1, 2, 3, 4], [4, 3, 2, 1]])

print (a)

>> tensor([[1, 2, 3, 4],

              [4, 3, 2, 1]])


2. tensor 크기 확인하기 -> numpy와 비교(https://qlsenddl-lab.tistory.com/23 참고)

ndim: tensor의 차원 확인

shape: tensor가 어떤 구조인지 확인(행 수, 열 수 등등)

size(): shape과 동일 -> 주의: '()'해야 shape과 같은 결과

ex> 

a = torch.tensor([[1, 2, 3, 4], [4, 3, 2, 1]])

print(a.ndim)

>> 2

print(a.shape)

>> torch.Size([2, 4])

print(a.size())

>> torch.Size([2, 4])

print(a.size)

>> <built-in method size of Tensor object at 0x0000014E9CDFFA98>


3. 특정 조건의 tensor 선언

zeros(a): 모든 원소가 0인 1*a vector tensor 생성

zeros((a, b)): 모든 원소가 0인 a*b matrix tensor 생성

zeros((a, b, c)): 모든 원소가 0인 a*b*c tensor 생성

ex>

print(torch.zeros(3))

>> tensor([0., 0., 0.])

print(torch.zeros((2, 4)))

>> tensor([[0., 0., 0., 0.],

               [0., 0., 0., 0.]])

print(torch.zeros((2, 3, 2)))

>> tensor([[[0., 0.],

                [0., 0.],
                [0., 0.]],

               [[0., 0.],
                [0., 0.],
                [0., 0.]]])


ones(a): 모든 원소가 1인 1*a vector tensor 생성

ones((a, b)): 모든 원소가 1인 a*b matrix tensor 생성

ones((a, b, c)): 모든 원소가 1인 a*b*c tensor 생성

ex>

print(torch.ones(3))

>> tensor([1., 1., 1.])

print(torch.ones((2, 4)))

>> tensor([[1., 1., 1., 1.],

               [1., 1., 1., 1.]])

print(torch.ones((2, 3, 2)))

>> tensor([[[1., 1.],

                [1., 1.],
                [1., 1.]],

               [[1., 1.],
                [1., 1.],
                [1., 1.]]])


arange(x): 0부터 x-1까지 정수를 원소로 갖는 1*x vector tensor 생성

arange(x).view(a,b): 0부터 x-1까지 정수를 원소로 갖는 a*b 텐서 생성 -> arange는 tuple 형태의 변수를 받지 못하므로 이 방법으로 tensor화 가능

ex>

print(torch.arange(4))

>> tensor([0, 1, 2, 3])

print(torch.arange(12).view(3, 4))

>> tensor([[ 0, 1, 2, 3],

               [ 4,  5,  6,  7],
               [ 8,  9, 10, 11]])


rand(a): 0과 1 사이의 uniform distribution을 따르도록 난수를 발생시켜 1*a vector tensor 생성

rand((a, b)): 0과 1 사이의 uniform distribution을 따르도록 난수를 발생시켜 a*b tensor 생성

randn(a): 표준 정규분포를 따르도록 난수를 발생시켜 1*a vector tensor 생성

randn((a, b)): 표준 정규분포를 따르도록 난수를 발생시켜 a*b tensor 생성

ex>

print(torch.rand(3))

>> tensor([0.8238, 0.8747, 0.5713])

print(torch.rand((2, 3)))

>> tensor([[0.1475, 0.9589, 0.3826],

               [0.3067, 0.8539, 0.3442]])

print(torch.randn(4))

>> tensor([-1.8344, 0.4576, 0.1689, -0.4205])

print(torch.randn((2, 2)))

>> tensor([[-0.6856, 1.9324],

               [ 0.4486, -3.0588]])


3. indexing과 slicing / conditional indexing / operation -> numpy와 거의 유사하므로 https://qlsenddl-lab.tistory.com/24 참고

* 다른 점

1) 음수 step이 불가능하다.

-> numpy에서는 a[i:j:-k]인 경우 k간격마다 역순으로 indexing할 수 있지만 torch tensor에서는 불가능 (vector인 경우)

2) mean(), a@b, matmul(a, b)을 쓰는 경우 숫자의 자료형이 int가 아닌 float여야 한다. 정수 뒤에 .을 붙임으로서 float로 입력 가능하다.

ex> torch.tensor([[1., 2., 3., 4.], [4., 3., 2., 1.]])

3) dot(a, b)의 경우 1D tensor만 가능하다.


4. shape manipulation

view((x, y, z)), view(x, y, z): (x, y, z) shape이 되도록 변경, 이 때 기존 tensor의 전체 요소 개수와 x*y*z의 값이 같아야 한다.(같지 않으면 오류 메시지 출력)

view((x, y, -1), view(x, y, -1): -1에 해당하는 부분에서는 자동으로 차원을 채워서 tensor shape 변경

a[:, None]: 한 차원을 추가, 기존의 shape이 (x, y, z)라면 (x, 1, y, z)로 변경

ex>

a = torch.rand((2, 3, 4))

print(a.view(4, 3, 2).shape)

>> torch.Size([4, 3, 2])

print(a.view(4, 2, -1).shape)

>> torch.Size([4, 2, 3])

print(a[:, None].shape)

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


torch.cat([a, b], dim = i): a와 b의 tensor를 i축에 해당하는 방향으로 쌓음 -> i에 해당하는 축을 제외하고 나머지 a와 b의 shape은 동일해야 한다.

ex>

a = torch.rand((2, 3, 2))

b = torch.rand((2, 3, 3))

print(torch.cat([a, b], dim = 2).shape)

>> torch.Size([2, 3, 5])

728x90