[실습] PyTorch 기초 - Transforms

  • Transforms

    • Torchvision에서는 Computer Vision에서 사용되는 다양한 모델, 데이터셋들을 제공
    • 여기서 torchvision의 transforms 모듈은 이미지 전처리에 관련된 유용한 기능들을 제공
    • 예를 들어,
      • ToTensor : image를 tensor로 변환하고 0~1 사이 값으로 normalize
      • Data augmentation (데이터 증강)
        • Gaussian Blur
        • Random Affine, 등
  • PreProcessing(전처리)

    • Deep Learning Pipeline(process)

      • Raw Input -> Deep Learning Pipeline -> Cat! (Output)
    • MLOps에서의 pipeline의미는 조금 다름

    • 여기서는 raw input에 대해서 output으로 mapping하는 일련의 과정을 의미한다.

    • CV case.

      • 전처리 -> 딥러닝모델 -> 후처리

      • [전처리]

        • 이미지를 H' W'로 resize한다.
        • 왜냐하면 NN의 input으로 mini-batch를 구성하는 데이터들은 동일한 dimension (shape)을 가져야 한다.
        • 그래야 mini-batch을 Matrix 혹은 Tensor로 표현할 수 있다!
        • resized 된 이미지를 numpy 배열로 변환
        • 0~1사이 값으로 normalize 한다
          • Torchvision의 Transforms은 CV와 관련된 전처리 함수, 기능들을 포함!
      • [딥러닝 모델]

        • NN Model은 전처리 값을 입력받아서 또 다른 Tensor값을 출력한다.

          model(img)
          tensor([0.9900, 0.100])
          # 고양이일 확률 예측 0.999
          # 강아지일 확률 예측 0.100
      • [후처리]

        • Cat!
        • 비록 해당 예제에서는 간단하지만 더 복잡한 전처리의 task도 많이 있다.
        • e.g. Object Detection, Segmentation, NLP ...
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch 기초 - Dataset과 DataLoader

  • Dataset과 Data Loader
    • Dataset과 Data Loader은 PyTorch에서 제공하는 추상 클래스
    • Dataset (torch.utils.data.Dataset)
      • Mini-batch를 구성할 각 data sample을 하나씩 불러오는 기능을 수행한다.
    • Dataloader (torch.utils.data.DataLoader)
      • Dataset에서 불러온 각 data sample들을 모아서 mini-batch로 구성하는 기능을 수행한다.
    • 그리고 Data Loader를 통해서 Data sample들을 병렬적으로 불러오고, 데이터 셔플 등의 작업을 간단하게 수행할 수 있다.
  • Dataset의 뼈대대
    • init function
    • len function
    • getitem function
    • 예:
from torch.utils.data import Dataset
class CustomDataset(Dataset):
    def __init__(self):
        # 데이터셋의 전처리를 수행하는 부분
    def __len__(self):
        # 데이터셋의 길이 (즉, 총 샘플의 갯수를 명시하는 부분)
    def __getitem__(self, item):
        # 데이터셋에서 특정 1개의 샘플을 가져오는 부분
        # 참고로 item은 index
  • Data Loader의 Input:
    • dataset
    • batch_size: mini-batch의 크기
    • shuffle (binary): 무작위 순서로 데이터를 샘플링 할 것인지
    • num_workers: 데이터 로딩에 사룡할 subprocess 개수 (병렬 처리)
    • pin_memory (binary): GPU memory에 pin 할 것인지
    • drop_last (binary): 마지막 mini-batch을 drop할 것인지
  • 참고로
    • num_workers 수가 많을수록 데이터 로딩이 더 빠르지만, 그만큼 CPU core 갯수도 충분해야한다. (CPU core 갯수보다 num_workers가 더 많으면 오히려 느려지는 경우 발생)
    • pin_memory=True로 했을 시, GPU (cuda) memory를 미리 할당, 확보시켜서 조금 더 빠르게 데이터를 GPU에 올릴 수 있다.
  • 다음 내용을 Jupyter Notebook에서 살펴보자:
    • CIFAR10 (torchvision.datasets.CIFAR10)을 활용
    • torch.utils.Dataset으로 Custom Dataset 구현
    • torch.utils.DataLoader 활용
  • 출처: 인프런 | 딥러닝 이론 + PyTorch 실무 완전 정복

[실습] PyTorch 기초 - Tensor

  • PyTorch의 Tensor
    • Tensor (torch.Tensor)
      • Numpy의 배열 (array)와 행렬 (matrix)와 매우 유사한 자료구조
      • PyTorch에서 scalar, vector, matrix, tensor등을 표현하는데 사용
      • 예:
        • Scalar : 1
          • 1
        • Vector : (2)
          • [1]
            [2]
        • Matrix : (2, 3)
          • [[1 3 5]]
            [[2 4 6]]
        • Tensor : (2, 3, 2)
          • [[[1 2] [3 4] [5 6]]]
            [[[7 8] [9 10] [11 12]]]
      • GPU나 TPU와 같은 연산 가속을 위한 특수한 하드웨어에서 실행할 수 있다.
      • Backward pass에서 계산된 Gradient (.grad)을 저장한다.
      • 기본적으로 torch.Tensor에 어떤 operation (더하기, 곱셈 등)을 취하면 해당 operation이 Computational Graph에 기록된다.
        • 해당 Tensor와 다른 배열들과 Parameter 간의 경사를 구하는 것.
        • Auto Differentation
          • Backward Propagation의 핵심개념이자 작동원리
          • 모두 Reverse Differentiation을 활용해서 Gradient Descent에 필요한 Gradient을 계산하는 것임
          • 즉, w = (w0, w1, ... ,wN)인 어떤 임의의 합성함수 L(w)에 대해서 우리는 dL/dwi을 구할 수 있는 것임.
# Import related library
import numpy as np
import torch

# Initializing a tensor
# 초기화 방법 1: 지정된 값으로 Tensor 초기화
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)

print(x_data)
print(x_data.dtype)

# 초기화 방법 2: 랜덤한 값으로 Tensor 초기화
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")

# 초기화 방법 3: Numpy 배열로부터 Tensor 초기화
data = [[1, 2],[3, 4]]
np_array = np.array(data)
x_np = torch.from_numpy(np_array)

print(x_np)
print(x_np.dtype)

# Tensor 데이터의 형식 지정
# Tensor의 데이터 형식은 어떤 것들이 있을까요?
# 1. 정수 int (integer) \
#     1-1. torch.int8, torch.int16, torch.int32, torch.int64 (torch.long) \
#     1-2. torch.uint8: unsigned integer로 양의 정수 0 ~ 255 숫자만 포함, 주로 이미지 데이터를 다룰 때 사용.
# 2. float \
#     2-1. torch.float16, torch.float32, torch.float64
# 3. boolean: torch.bool
# 4. etc.

# torch.float32 형식으로 초기화
data = [[1,2], [3,4]]
x_data = torch.tensor(data, dtype=torch.float32)
print(x_data)
print(x_data.dtype)

# torch.uint8 형식으로 초기화
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data, dtype=torch.uint8)
print(x_data)
print(x_data.dtype)

# 다른 dtype으로 변환
x_data = x_data.to(torch.float16)
print(x_data.dtype)

# 다른 Device로 Tensor 옮기기

# 1. GPU가 사용가능한지 확인하기
# 2. 다른 Device로 Tensor 옮기기
# 3. 어떤 Device상에 Tensor가 있는지 확인하기

# GPU가 사용가능한지 확인하기
print(torch.cuda.is_available())

# GPU로 Tensor 옮기기
# We move our tensor to the GPU if available
if torch.cuda.is_available():
    tensor = tensor.to("cuda")

# CPU로 Tensor 옮기기
x_data = x_data.cpu()
# x_data = x_data.to("cpu")

# 어떤 Device상에 Tensor가 있는지 확인하기
print(x_data.device)

# Tensor을 활용한 연산
# 1. Indexing and slicing
# 2. Concatenation
# 3. Arithmetric
# 4. Inplace-operation

# Indexing
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0 # 모든 행에대한 index 1에 해당하는 값을 0으로 바꿈
print(tensor)

# Concatenation
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)

# Arithmetric
y1 = tensor @ tensor.T # 행렬의 곱
y2 = tensor.matmul(tensor.T) # Matrix Multiple
print(y1)
print(y2)

# Element-wise 곱셈
z1 = tensor * tensor
z2 = tensor.mul(tensor)
print(z1)
print(z2)

# Inplace operation
print(f"{tensor} \n")
tensor.add_(5) # 각 원소에 5씩 더해주고 override(=Inplace) 해줌
print(tensor)

+ Recent posts