앎을 경계하기

Machine Learning

DEEP LEARNING WITH PYTORCH: A 60 MINUTE BLITZ - TENSORS

양갱맨 2021. 3. 4. 15:09

What is PyTorch?

PyTorch는 파이썬 기반 패키지로 GPU나 다른 가속장치를 사용하기 위해 NumPy를 대체할 수 있고, neural networks 구현을 위한 자동 미분 라이브러리를 제공한다.

Goal of this tutorial

  • PyTorch의 텐서 라이브러리와 neural network를 이해한다.
  • 이미지를 분류하기 위해 작은 neural network를 학습시켜본다.

Requirements

https://pytorch.org/get-started/locally/

자신의 OS, 쿠다 버전 등 컴퓨터 사양에 맞는 파이토치 설치

conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch

Tensors

Tensor는 데이터 구조로 배열이나 행렬과 매우 유사하다.

PyTorch에서 model의 파라미터나 inputs, outputs를 인코딩 할 때 텐서를 사용한다.

Tensor는 NumPy에서의 ndarrays와 유사하며 GPU에서 동작시킬 수 있다.

import torch import numpy as np

Tensor 초기화

텐서를 만드는 방법은 여러가지가 있다.

  1. 데이터로부터 직접 만들기
    data = [[1, 2],[3, 4]] x_data = torch.tensor(data)

    2 by 2 텐서를 data라는 변수에 할당한다.

    torch.tensor를 사용하여 array를 PyTorch의 Tensor로 변환한다. type은 자동적으로 결정된다.

  1. NumPy array로부터 만들기
    np_array = np.array(data) #python list -> numpy array x_np = torch.from_numpy(np_array) #numpy array -> pytorch tensor 
  1. 텐서의 형태만 사용하기

    기존에 만들어 놓은 텐서 값을 사용하는 것이 아니라 shape만 적용하고 요소 값은 다른 값으로 채워서 텐서를 생성할 수 있다.

    x_ones = torch.ones_like(x_data) x_rand = torch.rand_like(x_data, dtype=torch.float)

    torch.ones_like()는 인자로 전달된 값의 shape를 유지한 채로 elements를 1로 채운다.

    torch.rand_like()는 인자로 전달된 값의 shape를 유지한 채로 elements를 랜덤한 값으로 채운다. 값의 범위는 [0, 1)이다.

  1. 랜덤 또는 상수 값 사용하기

    shape를 직접 지정하여 텐서를 생성할 수 있다. 텐서 요소들은 함수에 따라 랜덤, 1, 0으로 채울 수 있다.

    shape = (2,3,) #2 by 3 rand_tensor = torch.rand(shape) ones_tensor = torch.ones(shape) zeros_tensor = torch.zeros(shape)

    torch.rand()랜덤 값으로 채움. 범위는 [0,1)

    torch.ones()요소를 1로 채움.

    torch.zeros()요소를 0으로 채움.

Tensor Attributes

텐서는 텐서의 형태, 데이터 타입, 저장된 디바이스(CPU/GPU) 와 같은 속성을 갖는다.

tensor = torch.rand(3,4) # 랜덤하게 채워진 3 by 4 텐서 생성 print(f"Shape of tensor: {tensor.shape}") print(f"Datatype of tensor: {tensor.dtype}") print(f"Device tensor is stored on: {tensor.device}")
Shape of tensor: torch.Size([3, 4]) Datatype of tensor: torch.float32 Device tensor is stored on: cpu

Tensor Operations

변환, 인덱싱, 슬라이싱, 수학적 연산, 선형대수, 랜덤 샘플링 등 100가지 이상의 텐서 연산들을 제공한다. 연산들은 전부 GPU에서 실행할 수 있고, 이를 위해 텐서를 GPU에 저장해야한다.

#GPU에서 실행하길 원할 때, if torch.cuda.is_available(): # CUDA를 사용할 수 있는 경우 tensor = tensor.to('cuda') # 텐서를 GPU에 올림
  • NumPy처럼 indexing, slicing 하기
    tensor = torch.ones(4,4) # 1로 채워진 4 by 4 tensor tensor[:,1] = 0 # 1번째 column vector 값을 0으로 바꿈 print(tensor)
    tensor([[1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.]])
  • Tensor 붙이기(Concatenate)
    t1 = torch.cat([tensor, tensor, tensor], dim=1) # dim이 0이면 세로(vertical)로 붙이고, 1이면 가로(horizontal)로 붙임 print(t1)
    tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.], [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])
  • 텐서의 곱셈

    *연산자를 쓰거나 PyTorch의 tensor의 mul 메소드를 사용하면 element-wise 연산이 수행된다.

    만약 행렬 곱셈을 하고 싶다면, matmul() 또는 @를 사용해야 한다.

    # Element-wise print(f"tensor.mul(tensor) \n {tensor.mul(tensor)}\n") # tensor의 mul함수 print(f"tensor * tensor \n {tensor * tensor}") # 연산자로 곱하기
    tensor.mul(tensor) tensor([[1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.]]) tensor * tensor tensor([[1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.]])
    # Matix multiplication print(f"tensor.matmul(tensor.T) \n {tensor.matmul(tensor.T)} \n") print(f"tensor @ tensor.T \n {tensor @ tensor.T} \n")
    tensor.matmul(tensor.T) tensor([[3., 3., 3., 3.], [3., 3., 3., 3.], [3., 3., 3., 3.], [3., 3., 3., 3.]]) tensor @ tensor.T tensor([[3., 3., 3., 3.], [3., 3., 3., 3.], [3., 3., 3., 3.], [3., 3., 3., 3.]])
  • In-place 연산 (+=, *= 같은 연산)
    print(tensor) tensor.add_(5) # tensor *= 5 또는 tensor = tensor * 5 결과 값이 바로 요소 값으로 적용됨 print(tensor)
    tensor([[1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.], [1., 0., 1., 1.]]) tensor([[6., 5., 6., 6.], [6., 5., 6., 6.], [6., 5., 6., 6.], [6., 5., 6., 6.]])

Bridge with NumPy

CPU에 있는 tensor와 NumPy arrays는 기본 메모리 위치를 공유할 수 있고, 하나를 변경하는 경우 다른 하나도 함께 변경된다.

  • PyTorch의 Tensor를 NumPy array로 변환
t = torch.ones(5) # 1 by 5 의 1로 채워진 행렬 print(f"t: {t}") n = t.numpy() # NumPy array로 변환 print(f"n: {n}")
t: tensor([1., 1., 1., 1., 1.]) n: [1. 1. 1. 1. 1.]
  • NumPy array를 PyTorch tensor로 변환
n = np.ones(5) t = torch.from_numpy(n) np.add(n, 1, out = n) # numpy array 값을 변환시키면 t에도 적용이 된다. print(f"t: {t}") print(f"n: {n}")
t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64) n: [2. 2. 2. 2. 2.]