(7-3) (실습) PyTorch, TensorFlow

Yongjoo Lee·2021년 1월 20일
0
post-thumbnail

(실습) PyTorch

💡 colab 에서 실습을 진행

from __future__ import print_function
import torch

torch.__version__

'1.7.1+cpu'

PyTorch란?

python 기반의 과학 연산 패키지

다음과 같은 경우에 사용

  • Numpy를 대체하면서 GPU를 이용한 연산이 필요한 경우
  • 최대한의 유연성과 속도를 제공하는 딥러닝 연구 플랫폼이 필요한 경우

Torch 에서는 tensor 타입을 사용

📌 tensor : numpy의 ndarray와 유사하며, 추가로 GPU를 사용한 연산 가속도 가능

Tensor 연산

  • 초기화되지 않은 행렬 생성

    • torch.empty()
  • 무작위로 초기화된 행렬 생성

    • torch.randn() : 표준정규분포에서 값을 샘플링
    • torch.rand() : 0~1 사이의 값을 샘플링
  • 0 또는 1로 채워진 행렬 생성 (dtype=torch.float32)

    • torch.zeros() : 0 으로 채워진 행렬 생성
    • torch.ones() : 1 로 채워진 행렬 생성
  • 데이터로부터 직접 tensor 생성

    • torch.tensor(data)

      x = torch.tensor([5.5, 3])
      print(x)
      
      tensor([5.5000, 3.0000])
  • 존재하는 tensor를 바탕으로 tensor 생성. 사용자로부터 제공된 새로운 값이 없으면 입력 tensor의 속성(예: dtype)을 재사용

    • x.new_ones()

    • torch.randn_like(x)

      x = x.new_ones(5, 3, dtype=torch.double)
      print(x)
      x = torch.randn_like(x, dtype=torch.float)
      print(x)
      
      tensor([[1., 1., 1.],
              [1., 1., 1.],
              [1., 1., 1.],
              [1., 1., 1.],
              [1., 1., 1.]], dtype=torch.float64)
      tensor([[-2.0476,  1.1892, -0.9870],
              [-0.4139,  0.3040,  0.5669],
              [ 0.8405, -0.7245, -1.6147],
              [ 0.4094, -0.7145, -1.6480],
              [-1.4789,  2.0897,  1.9627]])
  • 행렬의 크기

    • x.size() or x.shape

      print(x.size())
      print(x.shape)
      
      torch.Size([5, 3])
      torch.Size([5, 3])
  • 덧셈: 문법1 x + y

    y = torch.rand(5, 3)
    print(x)
    print(y)
    print(x + y)
    
    tensor([[-0.8039, -0.0473, -0.2606],
            [-0.6666, -0.2164,  1.5497],
            [-0.0673, -0.6175,  1.4867],
            [ 1.8226, -0.9508,  2.0158],
            [ 1.1701, -1.5394, -0.1466]])
    tensor([[0.5261, 0.0257, 0.2226],
            [0.0479, 0.8267, 0.1479],
            [0.4942, 0.8873, 0.1607],
            [0.3858, 0.2859, 0.7855],
            [0.3595, 0.9427, 0.4000]])
    tensor([[-0.2778, -0.0216, -0.0379],
            [-0.6187,  0.6103,  1.6975],
            [ 0.4269,  0.2698,  1.6474],
            [ 2.2084, -0.6649,  2.8013],
            [ 1.5296, -0.5966,  0.2534]])
  • 덧셈: 문법2 torch.add(x, y)

    print(torch.add(x, y))
    
    tensor([[-0.2778, -0.0216, -0.0379],
            [-0.6187,  0.6103,  1.6975],
            [ 0.4269,  0.2698,  1.6474],
            [ 2.2084, -0.6649,  2.8013],
            [ 1.5296, -0.5966,  0.2534]])
    • 결과를 담을 tensor를 인자로 제공

      result = torch.empty(5, 3)
      print(result)
      
      torch.add(x, y, out=result)
      print(result)
      
      tensor([[ 3.2141e-36,  0.0000e+00,  1.5975e-43],
              [ 1.3873e-43,  1.4574e-43,  6.4460e-44],
              [ 1.4153e-43,  1.5274e-43,  1.5695e-43],
              [ 1.6255e-43,  1.6956e-43,  2.8013e+00],
              [ 1.5296e+00, -5.9664e-01,  2.5340e-01]])
      tensor([[-0.2778, -0.0216, -0.0379],
              [-0.6187,  0.6103,  1.6975],
              [ 0.4269,  0.2698,  1.6474],
              [ 2.2084, -0.6649,  2.8013],
              [ 1.5296, -0.5966,  0.2534]])
  • 덧셈: 바꿔치기(In-place) 방식 y.add_(x)

    # adds x to y
    print(y)
    y.add_(x)
    print(y)
    
    tensor([[0.5261, 0.0257, 0.2226],
            [0.0479, 0.8267, 0.1479],
            [0.4942, 0.8873, 0.1607],
            [0.3858, 0.2859, 0.7855],
            [0.3595, 0.9427, 0.4000]])
    tensor([[-0.2778, -0.0216, -0.0379],
            [-0.6187,  0.6103,  1.6975],
            [ 0.4269,  0.2698,  1.6474],
            [ 2.2084, -0.6649,  2.8013],
            [ 1.5296, -0.5966,  0.2534]])

    📌 바꿔치기(In-place) 방식으로 tensor의 값을 변경하는 연산은 '' 를 접미사로 갖는다. (예: x.copy(y), x.t_())

  • 인덱싱 (Numpy와 동일)

    print(x)
    print(x[:, 1])
    
    tensor([[-0.8039, -0.0473, -0.2606],
            [-0.6666, -0.2164,  1.5497],
            [-0.0673, -0.6175,  1.4867],
            [ 1.8226, -0.9508,  2.0158],
            [ 1.1701, -1.5394, -0.1466]])
    tensor([-0.0473, -0.2164, -0.6175, -0.9508, -1.5394])
  • ⭐ 크기변경 x.view()

    • -1 은 자동으로 계산하여 결정

      x = torch.randn(4, 4)
      print(x)
      
      y = x.view(16)
      z = y.view(-1, 2)
      print(y)
      print(z)
      print(y.size(), z.size())
      
      tensor([[ 1.5496, -0.3506,  1.2708,  0.3292],
              [ 0.0165,  0.3230, -1.3762, -0.3285],
              [ 1.2202,  1.2733,  0.6468, -1.5027],
              [-0.0418,  0.6608,  0.4468, -0.0493]])
      tensor([ 1.5496, -0.3506,  1.2708,  0.3292,  0.0165,  0.3230, -1.3762, -0.3285,
               1.2202,  1.2733,  0.6468, -1.5027, -0.0418,  0.6608,  0.4468, -0.0493])
      tensor([[ 1.5496, -0.3506],
              [ 1.2708,  0.3292],
              [ 0.0165,  0.3230],
              [-1.3762, -0.3285],
              [ 1.2202,  1.2733],
              [ 0.6468, -1.5027],
              [-0.0418,  0.6608],
              [ 0.4468, -0.0493]])
      torch.Size([16]) torch.Size([8, 2])
  • 하나의 값만 존재할 경우 숫자 값 반환 x.item()

    x = torch.randn(1)
    print(x)
    print(type(x), type(x.item()))
    print(x.item())
    
    tensor([1.1069])
    <class 'torch.Tensor'> <class 'float'>
    1.10688054561615

📃 추가적인 Tensor 연산

전치, 인덱싱, 슬라이싱, 수학계산, 선형대수, 난수 등과 같은

100가지 이상의 Tensor 연산은 🔗 에 설명되어 있다.

NumPy 변환(Bridge)

Torch의 Tensor를 Numpy 배열(array)로 변환하거나, 그 반대로 하는 것은 매우 쉽다.

CPU 상에서 Torch Tensor와 Numpy 배열은 ⭐저장 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경된다.

  • Torch Tensor를 Numpy 배열로 변환

    a = torch.ones(5)
    print(a)
    
    tensor([1., 1., 1., 1., 1.])
    
    b = a.numpy()
    print(b)
    
    [1. 1. 1. 1. 1.]
    a.add_(1)
    print(a)
    print(b)
    
    tensor([2., 2., 2., 2., 2.])
    [2. 2. 2. 2. 2.]
    • 개별로 선언 a.clone()

      temp = a.clone()
      temp_numpy = temp.numpy()
      
      a.add_(1)
      print(a)
      print(temp_numpy)
      
      tensor([3., 3., 3., 3., 3.])
      [2. 2. 2. 2. 2.]
  • Numpy 배열을 Torch Tensor로 변환

    import numpy as np
    a = np.ones(5)
    print(a)
    
    [1. 1. 1. 1. 1.]
    
    b = torch.from_numpy(a)
    np.add(a, 1, out=a)
    print(a)
    print(b)
    
    [2. 2. 2. 2. 2.]
    tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

    💡 마찬가지로 Numpy(np) 배열을 변경하면 Torch Tensor의 값도 자동 변경된다!

CUDA Tensors

  • Tensor를 다른 장치로 옮기기 x.to()

    import torch
    
    # 이 코드는 CUDA가 사용 가능한 환경에서만 실행합니다.
    # ``torch.device`` 를 사용하여 tensor를 GPU 안팎으로 이동해보겠습니다.
    
    x = torch.rand(4,4)
    if torch.cuda.is_available():
        device = "cuda:0" # torch.device("cuda:0")          # CUDA 장치 객체(device object)로
        y = torch.ones_like(x, device=device)  # GPU 상에 직접적으로 tensor를 생성하거나
        print(y)
    
        x = x.to(device)                       # ``.to("cuda")`` 를 사용하면 됩니다.
        z = x + y
        print(z)
        print(z.to("cpu", torch.double))       # ``.to`` 는 dtype도 함께 변경합니다!
    
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0')
    tensor([[1.2859, 1.9080, 1.2066, 1.6184],
            [1.7055, 1.7199, 1.2572, 1.0787],
            [1.7547, 1.6160, 1.1335, 1.0379],
            [1.0367, 1.5918, 1.3650, 1.8609]], device='cuda:0')
    tensor([[1.2859, 1.9080, 1.2066, 1.6184],
            [1.7055, 1.7199, 1.2572, 1.0787],
            [1.7547, 1.6160, 1.1335, 1.0379],
            [1.0367, 1.5918, 1.3650, 1.8609]], dtype=torch.float64)
  • Tensor를 다른 장치로 옮기기(간단하게) x.cuda()

    x = x.cuda()
    print(x)
    
    tensor([[0.2859, 0.9080, 0.2066, 0.6184],
            [0.7055, 0.7199, 0.2572, 0.0787],
            [0.7547, 0.6160, 0.1335, 0.0379],
            [0.0367, 0.5918, 0.3650, 0.8609]], device='cuda:0')

(실습) Tensorflow

import tensorflow as tf
print(tf.__version__)

2.4.0

Tensorflow 문법

  • 변수 생성 tf.Variable()

    my_variable = tf.Variable(tf.zeros([1, 2, 3]))
    my_variable
    
    <tf.Variable 'Variable:0' shape=(1, 2, 3) dtype=float32, numpy=
    array([[[0., 0., 0.],
            [0., 0., 0.]]], dtype=float32)>

    👉 모양이 [1, 2, 3]이고 값은 0으로 채워진 3차원 텐서가 변수로 생성

  • 변수 사용

    • 텐서플로 그래프에서 tf.Variable의 값을 사용하려면
      이를 단순히 tf.Tensor로 취급하면 됨

      v = tf.Variable(0.0)
      print(v)
      
      <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.0>
      
      w = v + 1  # w는 v값 기준으로 계산되는 tf.Tensor 입니다.
                 # 변수가 수식에 사용될 때, 변수는 자동적으로
                 # tf.Tensor로 변환되어 값을 표현합니다.
      print(w)
      
      tf.Tensor(1.0, shape=(), dtype=float32)
  • 변수에 값 할당

    • 값을 변수에 할당하려면 assign, assign_add 메소드와 tf.Variable 클래스에 있는 친구들(friends)을 사용

      a = tf.Variable(0.0)
      a.assign_add(1)
      a.read_value()  # 1.0
      
      <tf.Tensor: shape=(), dtype=float32, numpy=1.0>

📌 tf.Tensor 객체의 랭크는 그 차원의 수

  • 랭크 0 (스칼라)

    mammal = tf.Variable("코끼리", tf.string)
    ignition = tf.Variable(451, tf.int16)
    floating = tf.Variable(3.14159265359, tf.float64)
    its_complicated = tf.Variable(12.3 - 4.85j, tf.complex64)
    
    print(mammal)
    print(ignition)
    print(floating)
    print(its_complicated)
    
    <tf.Variable 'Variable:0' shape=() dtype=string, numpy=b'\xec\xbd\x94\xeb\x81\xbc\xeb\xa6\xac'>
    <tf.Variable 'Variable:0' shape=() dtype=int32, numpy=451>
    <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=3.1415927>
    <tf.Variable 'Variable:0' shape=() dtype=complex128, numpy=(12.3-4.85j)>
  • 랭크 1 (벡터)

    mystr = tf.Variable(["안녕하세요"], tf.string)
    cool_numbers  = tf.Variable([3.14159, 2.71828], tf.float32)
    first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32)
    its_very_complicated = tf.Variable([12.3 - 4.85j, 7.5 - 6.23j], tf.complex64)
    
    print(mystr)
    print(cool_numbers)
    print(first_primes)
    print(its_very_complicated)
    
    <tf.Variable 'Variable:0' shape=(1,) dtype=string, numpy=
    array([b'\xec\x95\x88\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94'],
          dtype=object)>
    <tf.Variable 'Variable:0' shape=(2,) dtype=float32, numpy=array([3.14159, 2.71828], dtype=float32)>
    <tf.Variable 'Variable:0' shape=(5,) dtype=int32, numpy=array([ 2,  3,  5,  7, 11], dtype=int32)>
    <tf.Variable 'Variable:0' shape=(2,) dtype=complex128, numpy=array([12.3-4.85j,  7.5-6.23j])>
    
    tf.rank(mystr)
    
    <tf.Tensor: shape=(), dtype=int32, numpy=1>
  • 랭크 2 (행렬)

    mymat = tf.Variable([[7],[11]], tf.int16)
    myxor = tf.Variable([[False, True],[True, False]], tf.bool)
    linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32)
    squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32)
    
    #tf.rank : 객체의 랭크 구하기 
    rank_of_squares = tf.rank(squarish_squares)
    mymatC = tf.Variable([[7],[11]], tf.int32)
    
    print(mymat)
    print(rank_of_squares)
    
    <tf.Variable 'Variable:0' shape=(2, 1) dtype=int32, numpy=
    array([[ 7],
           [11]], dtype=int32)>
    tf.Tensor(2, shape=(), dtype=int32)

10개의 배치, 299개의 높이와 너비, 3개의 색상으로 생성

# 배치 x 높이 x 너비 x 색상
my_image = tf.zeros([10, 299, 299, 3])  
# H*W = 299 * 299
  • tf.Tensor 객체의 랭크 구하기 tf.rank(x)

    r = tf.rank(my_image)
    print(r)
    
    tf.Tensor(4, shape=(), dtype=int32)
  • tf.Tensor 원소 참조하기

    my_vector = tf.Variable([1, 2, 3, 4], tf.int32)
    print(tf.rank(my_vector))
    my_scalar = my_vector[2]
    print(my_scalar)
    
    tf.Tensor(1, shape=(), dtype=int32)
    tf.Tensor(3, shape=(), dtype=int32)
    print(squarish_squares)
    
    <tf.Variable 'Variable:0' shape=(2, 2) dtype=int32, numpy=
    array([[ 4,  9],
           [16, 25]], dtype=int32)>
    
    my_scalar = squarish_squares[1, 0] # 2행 1열의 값 
    print(my_scalar)
    
    tf.Tensor(16, shape=(), dtype=int32)
    
    my_row_vector = squarish_squares[1]
    print(my_row_vector)
    
    tf.Tensor([16 25], shape=(2,), dtype=int32)
    
    my_column_vector = squarish_squares[:, 1]
    print(my_column_vector)
    
    tf.Tensor([ 9 25], shape=(2,), dtype=int32)
  • tf.Tensor 객체 형태 얻기

    zeros = tf.zeros(squarish_squares.shape) # squarish_squares.shape으로 새로운 텐서 생성 
    zeros
    
    <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
    array([[0., 0.],
           [0., 0.]], dtype=float32)>
  • tf.Tensor 형태 변경

    # 총 60개의 데이터 (3*4*5=60)
    rank_three_tensor = tf.ones([3, 4, 5])
    print(rank_three_tensor.shape)
    print(rank_three_tensor)
    
    print('=== matrix ===')
    matrix = tf.reshape(rank_three_tensor, [6, 10])  # 기존 내용을 6x10 행렬로 형태 변경
    print(matrix.shape)
    print(matrix)
    
    print('=== matrixB ===') 
    matrixB = tf.reshape(matrix, [3, -1])  # 기존 내용을 3x20 행렬로 형태 변경
    print(matrixB.shape)
    print(matrixB)
    
    print('=== matrixAlt ===') 
    matrixAlt = tf.reshape(matrixB, [4, 3, -1])  # 기존 내용을 4x3x5 텐서로 형태 변경
    print(matrixAlt.shape)
    (3, 4, 5)
    tf.Tensor(
    [[[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]
    
     [[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]
    
     [[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]], shape=(3, 4, 5), dtype=float32)
    === matrix ===
    (6, 10)
    tf.Tensor(
    [[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]], shape=(6, 10), dtype=float32)
    === matrixB ===
    (3, 20)
    tf.Tensor(
    [[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]], shape=(3, 20), dtype=float32)
    === matrixAlt ===
    (4, 3, 5)
    tf.Tensor(
    [[[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]
    
     [[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]
    
     [[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]
    
     [[1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]
      [1. 1. 1. 1. 1.]]], shape=(4, 3, 5), dtype=float32)
profile
하나씩 정리하는 개발공부로그입니다.

0개의 댓글