1. 파이토치(Pytorch)

  • Tensorflow와 함께 머신러닝, 딥러닝에서 가장 널리 사용되는 프레임 워크
  • 초기에는 Torch라는 이름으로 Lua언어 기반으로 만들어졌으나, 파이썬 기반으로 변경한 것이 Pytorch
  • 뉴욕대학교와 페이스북(Meta)가 공동으로 개발하였으며, 현재 가장 대중적인 머신러닝, 딥러닝 프레임워크
# 필요모듈 임포트
import torch
print(torch.__version__)

# 결과값 => 2.1.0+cu121

 

1-1. 스칼라(Scalar)

  • 하나의 상수를 의미함.
var1 = torch.tensor([1])
var1
# 결과값 => tensor([1])

#------------------------------------------------------#

type(var1)
# 결과값 => torch.Tensor

#------------------------------------------------------#

var2 = torch.tensor([10.4])
var2
# 결과값 => tensor([10.4000])

#------------------------------------------------------#

# 두 스칼라의 사칙 연산
print(var1 + var2)
print(var1 - var2)
print(var1 * var2)
print(var1 / var2)

# 결과값 => 
# tensor([11.4000])
# tensor([-9.4000])
# tensor([10.4000])
# tensor([0.0962])

 

1-2. 벡터(Vector)

  • 상수가 두 개 이상 나열된 경우
vec1 = torch.tensor([1, 2, 3])
vec1
# 결과값 => tensor([1, 2, 3])

#------------------------------------------------------#

vec2 = torch.tensor([1.5, 2.4, 3.4])
vec2
# 결과값 => tensor([1.5000, 2.4000, 3.4000])

#------------------------------------------------------#

# 두 백터의 사칙 연산
print(vec1 + vec2)
print(vec1 - vec2)
print(vec1 * vec2)
print(vec1 / vec2)

# 결과값 => 
# tensor([2.5000, 4.4000, 6.4000])
# tensor([-0.5000, -0.4000, -0.4000])
# tensor([ 1.5000,  4.8000, 10.2000])
# tensor([0.6667, 0.8333, 0.8824])

#------------------------------------------------------#

vec3 = torch.tensor([5, 10, 20, 30])
vec3
# 결과값 => tensor([ 5, 10, 20, 30])

 

1-3. 행렬(Matrix)

  • 2개 이상의 벡터 값을 가지고 만들어진 값으로 행과 열의 개념을 가진 숫자의 나열을 뜻함.
mat1 = torch.tensor([[1, 2], [3, 4]])
print(mat1)

# 결과값 => 
# tensor([[1, 2],
#         [3, 4]])

#------------------------------------------------------#

mat2 = torch.tensor([[7, 8], [9, 10]])
print(mat2)

# 결과값 => 
# tensor([[ 7,  8],
#         [ 9, 10]])

#------------------------------------------------------#

# 두 행렬의 사칙 연산
print(mat1 + mat2)
print(mat1 - mat2)
print(mat1 * mat2)
print(mat1 / mat2)

# 결과값 => 
# tensor([[ 8, 10],
#         [12, 14]])
# tensor([[-6, -6],
#         [-6, -6]])
# tensor([[ 7, 16],
#         [27, 40]])
# tensor([[0.1429, 0.2500],
#         [0.3333, 0.4000]])

 

1-4. 텐서(Tensor)

  • 다수의 행렬이 모이면 텐서
  • 배열이나 행렬과 매우 유사한 특수 자료구조(파이토치만 사용가능)
  • 파이토치는 텐서를 사용하여 모델의 입력과 출력, 모델의 매개변수들을 처리함.

tensor1 = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(tensor1)

# 결과값 => 
# tensor([[[1, 2],
#          [3, 4]],
# 
#         [[5, 6],
#          [7, 8]]])

#------------------------------------------------------#

tensor2 = torch.tensor([[[9, 10], [11, 12]], [[13, 14], [15, 16]]])
print(tensor2)

# 결과값 => 
# tensor([[[ 9, 10],
#          [11, 12]],
# 
#         [[13, 14],
#          [15, 16]]])

#------------------------------------------------------#

# 두 텐서의 사칙 연산
print(tensor1 + tensor2)
print(tensor1 - tensor2)
print(tensor1 * tensor2)
print(tensor1 / tensor2)

# 결과값 => 
# tensor([[[10, 12],
#          [14, 16]],
# 
#         [[18, 20],
#          [22, 24]]])
# tensor([[[-8, -8],
#          [-8, -8]],
# 
#         [[-8, -8],
#          [-8, -8]]])
# tensor([[[  9,  20],
#          [ 33,  48]],
# 
#         [[ 65,  84],
#          [105, 128]]])
# tensor([[[0.1111, 0.2000],
#          [0.2727, 0.3333]],
# 
#         [[0.3846, 0.4286],
#          [0.4667, 0.5000]]])
print(torch.add(tensor1, tensor2)) # 덧셈
print(torch.subtract(tensor1, tensor2)) # 뺄셈
print(torch.multiply(tensor1, tensor2)) # 곱셈
print(torch.divide(tensor1, tensor2)) # 나눗셈
print(torch.matmul(tensor1, tensor2)) # 행렬곱

# 결과값 => 
# tensor([[[10, 12],
#          [14, 16]],
# 
#         [[18, 20],
#          [22, 24]]])
# tensor([[[-8, -8],
#          [-8, -8]],
# 
#         [[-8, -8],
#          [-8, -8]]])
# tensor([[[  9,  20],
#          [ 33,  48]],
# 
#         [[ 65,  84],
#          [105, 128]]])
# tensor([[[0.1111, 0.2000],
#          [0.2727, 0.3333]],
# 
#         [[0.3846, 0.4286],
#          [0.4667, 0.5000]]])
# tensor([[[ 31,  34],
#          [ 71,  78]],
# 
#         [[155, 166],
#          [211, 226]]])

# tensor1에 결과를 다시 저장. 모든 사칙연산자에 _를 붙이면 inplace가 됨
print(tensor1.add_(tensor2)) # inplace가 되는 연산. 즉 덧셈을 한후 적용됨

# 결과값 =>
# tensor([[[10, 12],
#          [14, 16]],
# 
#         [[18, 20],
#          [22, 24]]])

 

2. 텐서의 변환

data = [[1, 2], [3, 4]]
print(data)

# 결과값 => [[1, 2], [3, 4]]

x_data = torch.tensor(data)
print(x_data)

# 결과값 => 
# tensor([[1, 2],
#         [3, 4]])

 

import numpy as np

# tensor -> array로 변경
np_array = np.array(x_data)
np_array

# 결과값 => 
# array([[1, 2],
#        [3, 4]])

#------------------------------------------------------#

# array -> tensor로 변경
x_np_1 = torch.tensor(np_array)
x_np_1

# 결과값 => 
# tensor([[1, 2],
#         [3, 4]])

#------------------------------------------------------#

x_np_1[0, 0] = 100
print(x_np_1)
print(np_array)

# 결과값 => 
# tensor([[100,   2],
#        [  3,   4]])
# [[1 2]
#  [3 4]]

#------------------------------------------------------#

# as_tensor : ndarray와 동일한 메모리 주소를 가리키는 뷰를 만듦
x_np_2 = torch.as_tensor(np_array)
print(x_np_2)
x_np_2[0, 0] = 200
print(x_np_2)
print(np_array)

# 결과값 => 
# tensor([[1, 2],
#         [3, 4]])
# tensor([[200,   2],
#         [  3,   4]])
# [[200   2]
#  [  3   4]]

#------------------------------------------------------#

# from_numpy : ndarray와 동일한 메모리 주소를 가리키는 뷰를 만듬
# from_numpy는 무조건 ndarray만 들어갈 수 있음
# as_tensor는 list나 다른 데이터형식이 들어갈 수 있음, 그냥 자료구조 자체이름이 tensor라고 변환이 됨
x_np_3 = torch.from_numpy(np_array)
print(x_np_3)
x_np_3[0, 0] = 300
print(x_np_3)
print(np_array)

# 결과값 => 
# tensor([[200,   2],
#         [  3,   4]])
# tensor([[300,   2],
#         [  3,   4]])
# [[300   2]
#  [  3   4]]

#------------------------------------------------------#

np_again = x_np_1.numpy()
print(np_again, type(np_again))

# 결과값 => 
# [[100   2]
#  [  3   4]] <class 'numpy.ndarray'>

 

3. 파이토치 주요 함수

# 예시 1은 흰색
a = torch.ones(2, 3)
print(a)

# 결과값 => 
# tensor([[1., 1., 1.],
#         [1., 1., 1.]])

#------------------------------------------------------#

# 검정색 0
b = torch.zeros(2, 3)
print(b)

# 결과값 => 
# tensor([[0., 0., 0.],
#         [0., 0., 0.]])

#------------------------------------------------------#

# 10으로 채우기
c = torch.full((2, 3), 10)
print(c)

# 결과값 => 
# tensor([[10, 10, 10],
#         [10, 10, 10]])

#------------------------------------------------------#

# 자동으로 쓰레기 값을 채워 넣음
d = torch.empty(2, 3)
print(d)

# 결과값 => 
# tensor([[5.0954e+18, 4.5081e-41, 5.0954e+18],
#         [4.5081e-41, 6.3376e-10, 2.1707e-18]])

#------------------------------------------------------#

e = torch.eye(5)
print(e)

# 결과값 => 
# tensor([[1., 0., 0., 0., 0.],
#         [0., 1., 0., 0., 0.],
#         [0., 0., 1., 0., 0.],
#         [0., 0., 0., 1., 0.],
#         [0., 0., 0., 0., 1.]])

#------------------------------------------------------#

f = torch.arange(10)
print(f)

# 결과값 => tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

#------------------------------------------------------#

# 랜덤값을 넣어줌
g = torch.rand(2, 3)
print(g)

# 결과값 => 
# tensor([[0.4533, 0.6650, 0.0121],
#         [0.1306, 0.3642, 0.5025]])

#------------------------------------------------------#

# 랜덤값 난수를 포함하여 생성해줌
h = torch.randn(2, 3)
print(h)

# 결과값 => 
# tensor([[-0.3783, -2.2212, -1.1986],
#         [-2.2711, -2.1616,  1.9712]])

#------------------------------------------------------#

# 차원을 바꿔줌 중요함
# reshape(2 <- 메트릭스, 2 <- 2행, 4 <- 4열)
i = torch.arange(16).reshape(2, 2, 4)
print(i, i.shape)

# 결과값 => 
# tensor([[[ 0,  1,  2,  3],
#          [ 4,  5,  6,  7]],
# 
#         [[ 8,  9, 10, 11],
#          [12, 13, 14, 15]]]) torch.Size([2, 2, 4])

#------------------------------------------------------#

# permute : 차원을 지정한 인덱스로 변환
# i가 가지고 있던 차원은 2, 2, 4 => 4, 2, 1 이렇게 변경이 되어서 나온다.
# 값의 방향이 세로(열)로 간다.
# 순서대로 하고 싶으면 j = i.permute((2, 0, 1)).T를 하면 된다.
j = i.permute((2, 0, 1))
print(j, j.shape)

# 결과값 => 
# tensor([[[ 0,  4],
#          [ 8, 12]],
# 
#         [[ 1,  5],
#          [ 9, 13]],
# 
#         [[ 2,  6],
#          [10, 14]],
# 
#         [[ 3,  7],
#          [11, 15]]]) torch.Size([4, 2, 2])

 

4. 텐서의 인덱싱과 슬라이싱

a = torch.arange(1, 13).reshape(3, 4)
print(a)

# 결과값 => 
# tensor([[ 1,  2,  3,  4],
#         [ 5,  6,  7,  8],
#         [ 9, 10, 11, 12]])
        
# ------------------------------------------------#

# 인덱싱을 하면 한 차원 낮아진다. 중요함
print(a[1])

# 결과값 => tensor([5, 6, 7, 8])

# ------------------------------------------------#

print(a[0, -1])

# 결과값 => tensor(4)

# ------------------------------------------------#

# 슬라이싱은 차원이 유지된다.
print(a[1:-1])

# 결과값 => tensor([[5, 6, 7, 8]])

# ------------------------------------------------#

print(a[:2, 2:])

# 결과값 => 
# tensor([[3, 4],
#         [7, 8]])