Python

pytorch 기본 문법 I

해파리냉채무침 2024. 2. 24. 17:21

강의 출처: https://www.youtube.com/watch?v=k60oT_8lyFw&list=LL&index=1&t=4103s

 

파이토치 구성요소

torch.autograd: 자동 미분 기능 

torch.nn: 신경망 구축을 위한 데이터 구조나 레이어 등의 라이브러리

torch.multiprocessing:  병렬처리 기능

torch.optim:  SGD(Stochastic Gradient Descent)를 중심으로 한 파라미터 최적화 알고리즘 

torch.utils: 데이터 조작 등 유틸리티 기능

torch.onnx: ONNX(Open Neural Network Exchange), 서로 다른 프레임워크 간의 모델을 공유

 

Tensor 텐서

0D tensor : 스칼라, rank 0, shape: ( ) -> 차원이 없음(축이 없음)

1D tensor: vector, rank 1 shape: (3,) -> 축이 하나

2D tensor: matrix, rank 2 shape: (3,3) -> 축이 2개

3D tensor: rank 3 shape: (3,3,3)

4D tensor: rank 4 shape: (3,3,3,3)

5D tensor: rank 5 shape: (3,3,3,3,3)

6D tensor: rank 6 shape: (3,3,3,3,3,3)

 

 

pytorch 버전 확인

import torch
torch.__version__

텐서 초기화와 데이터 타입

초기화 되지 않은 텐서

x = torch.empty(4,2) #4*2의 랜덤한 텐서가 나옴, 숫자가 이상함
print(x)

 

tensor([[2.6112e+28, 4.4023e-41],

[2.6105e+28, 4.4023e-41],

[2.6821e+28, 4.4023e-41],

[2.6822e+28, 4.4023e-41]])

 

무작위로 초기화 된 텐서 

x = torch.rand(4,2)
print(x) #초기화가 random을 기준으로 됨

tensor([[0.5089, 0.5816],

[0.5231, 0.4934],

[0.8437, 0.6886],

[0.4581, 0.1669]])

 

데이터 타입(dtype)이 long이고, 0으로 채워진 텐서

x = torch.zeros(4,2,dtype=torch.long) #long type -> 소수점이 없고 정수형으로 초기화
print(x)

tensor([[0, 0],

[0, 0],

[0, 0],

[0, 0]])

 

사용자가 입력한 값으로 텐서 초기화

x = torch.tensor([3,2.3])
print(x) #기본적으로 실수형 type 데이터

tensor([3.0000, 2.3000])

 

2x4 크기, double 타입, 1로 채워진 텐서

x = x.new_ones(2,4,dtype= torch.double) #torch.double은 소수점
print(x)

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

[1., 1., 1., 1.]], dtype=torch.float64)

 

x와 같은 크기, float 타입, 무작위로 채워진 텐서

x  = torch.randn_like(x,dtype = torch.float) #위의 2*4 형상과 똑같이 해주는것, 데이터 형식 float 실수형으로 바꿔줘
print(x)
 
tensor([[-0.4821, 0.7120, -0.0676, 1.5889],
[ 1.2754, -0.4262, -0.5425, -0.2298]])

 

텐서의 크기 계산

print(x.size())

torch.Size([2, 4])

 

데이터 타입

Data type                                                   dtype                                 CPU tensor                   GPU tensor

32-bit floating point torch.float32 or torch.float torch.FloatTensor torch.cuda.FloatTensor
64-bit floating point torch.float64 or torch.double torch.DoubleTensor torch.cuda.DoubleTensor
16-bit floating point torch.float16 or torch.half torch.HalfTensor torch.cuda.HalfTensor
8-bit integer(unsinged) torch.uint8 torch.ByteTensor torch.cuda.ByteTensor
8-bit integer(singed) torch.int8 torch.CharTensor torch.cuda.CharTensor
16-bit integer(signed) torch.int16 or torch.short torch.ShortTensor torch.cuda.ShortTensor
32-bit integer(signed) torch.int32 or torch.int torch.IntTensor torch.cuda.IntTensor
64-bit integer(signed) torch.int64 or torch.long torch.LongTensor torch.cuda.LongTensor

 

ft = torch.FloatTensor([1,2,3])
print(ft)
print(ft.dtype) #float tensor 기본 32

tensor([1., 2., 3.])

torch.float32

print(ft.short())
print(ft.int())
print(ft.long())#long은 64비트

tensor([1, 2, 3], dtype=torch.int16)

tensor([1, 2, 3], dtype=torch.int32)

tensor([1, 2, 3])

it = torch.IntTensor([1,2,3])
print(it)
print(it.dtype)

tensor([1, 2, 3], dtype=torch.int32)

torch.int32

print(it.double())
print(it.half())

tensor([1., 2., 3.], dtype=torch.float64)

tensor([1., 2., 3.], dtype=torch.float16)

 

CUDA Tensor

.to 메소드를 사용하여 텐서를 어떠한 장치(cpu, gpu)로도 옮길 수 있음

x = torch.randn(1)
print(x)
print(x.item())#실제값
print(x.dtype)

tensor([1.0434])

1.0433578491210938

torch.float32

device = torch.device('cuda' if torch.cuda.is_available()  else 'cpu')
print(device)
y = torch.ones_like(x,device=device) #cuda 디바이스로 들어감
print(y)
x = x.to(device) #device 옮기기
print(x)
z = x+y #1더하기
print(z)
print(z.to('cpu',torch.double)) #계산된 값 cpu로 옮기기

cuda

tensor([1.], device='cuda:0')

tensor([1.0434], device='cuda:0')

tensor([2.0434], device='cuda:0')

tensor([2.0434], dtype=torch.float64)

다차원 텐서 표현

0D Tensor(Scalar)

  • 하나의 숫자를 담고 있는 텐서(tensor)
  • 축과 형상이 없음
t0 = torch.tensor(0)
print(t0.ndim)
print(t0.shape)
print(t0) #치원이 없는 단순한 텐서

0

torch.Size([])

tensor(0)

 

1D Tensor(Vector)

  • 값들을 저장한 리스트와 유사한 텐서
  • 하나의 축이 존재
t1 = torch.tensor([1,2,3])
print(t1.ndim)
print(t1.shape)
print(t1)

1

torch.Size([3])

tensor([1, 2, 3])

 

2D Tensor(Matrix)

  • 행렬과 같은 모양으로 두개의 축이 존재
  • 일반적인 수치, 통계 데이터셋이 해당
  • 주로 샘플(samples)과 특성(features)을 가진 구조로 사용
t2 = torch.tensor([[1,2,3],
                  [4,5,6],
                   [7,8,9]])
print(t2.ndim)
print(t2.shape)
print(t2)

2

torch.Size([3, 3])

tensor([[1, 2, 3],

[4, 5, 6],

[7, 8, 9]])

 

3D Tensor

  • 큐브(cube)와 같은 모양으로 세개의 축이 존재
  • 데이터가 연속된 시퀀스 데이터나 시간 축이 포함된 시계열 데이터에 해당
  • 주식 가격 데이터셋, 시간에 따른 질병 발병 데이터 등이 존재
  • 주로 샘플(samples), 타임스텝(timesteps), 특성(features)을 가진 구조로 사용
t3 = torch.tensor([[[1,2,3],
                  [4,5,6],
                   [7,8,9]],
                    [[1,2,3],
                  [4,5,6],
                   [7,8,9]],
                    [[1,2,3],
                  [4,5,6],
                   [7,8,9]]])
print(t3.ndim)
print(t3.shape)
print(t3)

3

torch.Size([3, 3, 3])

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

[4, 5, 6],

[7, 8, 9]],

 

[[1, 2, 3],

[4, 5, 6],

[7, 8, 9]],

 

[[1, 2, 3],

[4, 5, 6],

[7, 8, 9]]])

 

4D Tensor

  • 4개의 축 rank 4개
  • 컬러 이미지 데이터가 대표적인 사례 (흑백 이미지 데이터는 3D Tensor로 가능)
  • 주로 샘플(samples), 높이(height), 너비(width), 컬러 채널(channel)을 가진 구조로 사용

5D Tensor

  • 5개의 축 rank가 5개
  • 비디오 데이터가 대표적인 사례
  • 주로 샘플(samples), 프레임(frames), 높이(height), 너비(width), 컬러 채널(channel)을 가진 구조로 사용

텐서의 연산(operations)

텐서에 대한 수학 연산, 삼각함수, 비트 연산, 비교 연산, 집계 등 제공

import math
a = torch.rand(1,2) * 2 -1
print(a)
print(torch.abs(a)) #절댓값
print(torch.ceil(a))#올림
print(torch.floor(a))#버림
print(torch.clamp(a,-0.5,0.5))# -0.5, 0.5 사이 값이 있도록

tensor([[-0.3085, -0.9677]])

tensor([[0.3085, 0.9677]])

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

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

tensor([[-0.3085, -0.5000]])

 

print(a)
print(torch.min(a))
print(torch.max(a))
print(torch.mean(a))
print(torch.std(a))
print(torch.prod(a))
print(torch.unique(torch.tensor([1,2,3,1,2,2]))) #중복제거하고 출력

tensor([[-0.3085, -0.9677]])

tensor(-0.9677)

tensor(-0.3085)

tensor(-0.6381)

tensor(0.4661)

tensor(0.2986)

tensor([1, 2, 3])

 

max와 min은 dim 인자를 줄 경우 argmax와 argmin도 함께 리턴

  • argmax: 최대값을 가진 인덱스
  • argmin: 최소값을 가진 인덱스
x = torch.rand(2,2)
print(x)
print(x.max(dim=0))
print(x.max(dim=1))

tensor([[0.9169, 0.0324],

[0.5905, 0.2895]])

torch.return_types.max( values=tensor([0.9169, 0.2895]),

indices=tensor([0, 1]))

torch.return_types.max( values=tensor([0.9169, 0.5905]), indices=tensor([0, 0]))

x = torch.rand(2,2)
print(x)
y = torch.rand(2,2)
print(y)

tensor([[0.3240, 0.5966],

[0.6831, 0.8738]])

tensor([[0.0522, 0.2589],

[0.7465, 0.1907]])

 

torch.add 덧셈

print(x+y)
print(torch.add(x,y))

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

 

결과 텐서를 인자로 제공

result = torch.empty(2,4) #빈 텐서 생성
torch.add(x,y,out=result) #result와 x,y는 같은 크기의 텐서여야함
print(result)
tensor([[0.3763, 0.8556],
        [1.4296, 1.0646]])
<ipython-input-29-fa27375dc8ba>:2: UserWarning: An output with one or more elements was resized since it had shape [2, 4], which does not match the required output shape [2, 2]. This behavior is deprecated, and in a future PyTorch release outputs will not be resized unless they have zero elements. You can explicitly reuse an out tensor t by resizing it, inplace, to zero elements with t.resize_(0). (Triggered internally at ../aten/src/ATen/native/Resize.cpp:28.)
  torch.add(x,y,out=result)

 

in-place 방식

  • in-place방식으로 텐서의 값을 변경하는 연산 뒤에는 _''가 붙음
  • x.copy_(y), x.t_()
print(x)
print(y)
y.add_(x)#x와 y의 원소합이 y로 나오도록, 원본 변경
print(y)

tensor([[0.3240, 0.5966],

[0.6831, 0.8738]])

tensor([[0.0522, 0.2589],

[0.7465, 0.1907]])

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

 

torch.sub 뺄셈

print(x)
print(y)
print(x-y)
print(torch.sub(x,y))
print(x.sub(y))

tensor([[0.3240, 0.5966],

[0.6831, 0.8738]])

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

tensor([[-0.0522, -0.2589],

[-0.7465, -0.1907]])

tensor([[-0.0522, -0.2589],

[-0.7465, -0.1907]])

tensor([[-0.0522, -0.2589],

[-0.7465, -0.1907]])

 

torch.mul 곱셈

print(x)
print(y)
print(x * y)
print(torch.mul(x,y))
print(x.mul(y))

tensor([[0.3240, 0.5966],

[0.6831, 0.8738]])

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

tensor([[0.1219, 0.5105],

[0.9765, 0.9303]])

tensor([[0.1219, 0.5105],

[0.9765, 0.9303]])

tensor([[0.1219, 0.5105],

[0.9765, 0.9303]])

 

torch.div: 나눗셈

print(x)
print(y)
print(x / y)
print(torch.div(x,y))
print(x.div(y))

tensor([[0.3240, 0.5966],

[0.6831, 0.8738]])

tensor([[0.3763, 0.8556],

[1.4296, 1.0646]])

tensor([[0.8611, 0.6974],

[0.4778, 0.8208]])

tensor([[0.8611, 0.6974],

[0.4778, 0.8208]])

tensor([[0.8611, 0.6974],

[0.4778, 0.8208]])

 

torch.mm 내적(dot product)

print(x)
print(y)
print(torch.matmul(x,y))
z = torch.mm(x,y)
print(z)
print(torch.svd(z))#행렬분해

tensor([[0.3240, 0.5966], [0.6831, 0.8738]])

tensor([[0.3763, 0.8556], [1.4296, 1.0646]])

tensor([[0.9749, 0.9124], [1.5062, 1.5147]])

tensor([[0.9749, 0.9124], [1.5062, 1.5147]])

torch.return_types.svd( U=tensor([[-0.5299, -0.8480], [-0.8480, 0.5299]]),

S=tensor([2.5188, 0.0406]),

V=tensor([[-0.7122, -0.7019], [-0.7019, 0.7122]]))