페이스북이 초기 루아(Lua) 언어로 개발된 토치(Torch)를 파이썬 버전으로 개발하여 2017년도에 공개
초기에 토치(Torch)
는 넘파이(NumPy)
라이브러리처럼 과학 연산을 위한 라이브러리로 공개
이후 GPU를 이용한 텐서 조작 및 동적 신경망 구축이 가능하도록 딥러닝 프레임워크로 발전시킴
파이썬답게 만들어졌고, 유연하면서도 가속화된 계산 속도
를 제공
torch
: 메인 네임스페이스, 텐서 등의 다양한 수학 함수가 포함
torch.autograd
: 자동 미분 기능을 제공하는 라이브러리
torch.nn
: 신경망 구축을 위한 데이터 구조나 레이어 등의 라이브러리
torch.multiprocessing
: 병럴처리 기능을 제공하는 라이브러리
torch.optim
: SGD(Stochastic Gradient Descent)를 중심으로 한 파라미터 최적화 알고리즘 제공
torch.utils
: 데이터 조작 등 유틸리티 기능 제공
torch.onnx
: ONNX(Open Neural Network Exchange), 서로 다른 프레임워크 간의 모델을 공유할 때 사용
데이터 표현을 위한 기본 구조로 텐서(tensor)
를 사용
텐서는 데이터를 담기위한 컨테이너(container)로서 일반적으로 수치형 데이터를 저장
넘파이(NumPy)의 ndarray
와 유사
GPU를 사용한 연산 가속 가능
import torch torch.__version__ #2.1.0+cu121
x = torch.empty(4,2) print(x) #tensor([[6.4460e-44, 1.5134e-43], # [1.3593e-43, 1.6956e-43], # [1.4153e-43, 1.5975e-43], # [4.4842e-44, 8.5479e-44]])
무작위로 초기화된 텐서
x = torch.rand(4,2) print(x) #tensor([[0.6114, 0.8115], # [0.1097, 0.3828], # [0.3179, 0.9290], # [0.3845, 0.1246]])
데이터 타입(dtype)이 long이고, 0으로 채워진 텐서
x = torch.zeros(4,2, dtype=torch.long) print(x) #tensor([[0, 0], # [0, 0], # [0, 0], # [0, 0]])
2X4크기, double 타입, 1로 채워진 텐서
x = x.new_ones(2,4, dtype=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) print(x) #tensor([[-0.0923, -0.9947, -0.5870, -0.3204], # [-1.2466, -0.1598, -0.7607, 0.0678]])
텐서의 크기 계산
print(x.size()) #torch.Size([2, 4])
ft = torch.FloatTensor([1,2,3]) print(ft) print(ft.dtype) #tensor([1., 2., 3.]) #torch.float32
print(ft.short()) print(ft.int()) print(ft.long()) #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.float()) print(it.double()) print(it.half()) #tensor([1., 2., 3.]) #tensor([1., 2., 3.], dtype=torch.float64) #tensor([1., 2., 3.], dtype=torch.float16)
CUDA
Tensors.to
메소드를 사용하여 텐서를 어떠한 장치(cpu, gpu)로도 옮길 수 있음
x = torch.randn(1) print(x) print(x.item()) print(x.dtype) #tensor([-0.7097]) #-0.7096615433692932 #torch.float32
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(device) y = torch.ones_like(x, device=device) print(y) x = x.to(device) print(x) z = x + y print(z) print(z.to('cpu', torch.double)) cpu #tensor([1.]) #tensor([-0.7097]) #tensor([0.2903]) #tensor([0.2903], dtype=torch.float64)
하나의 숫자를 담고 있는 텐서(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개의 축
컬러 이미지 데이터가 대표적인 사례 (흑백 이미지 데이터는 3D Tensor로 가능)
주로 샘플(samples)
, 높이(height)
, 너비(width)
, 컬러 채널(channel)
을 가진 구조로 사용
5D Tensor
5개의 축
비디오 데이터
가 대표적인 사례
주로 샘플(samples)
, 프레임(frames)
, 높이(height)
, 너비(width)
, 컬러 채널(channel)
을 가진 구조로 사용
텐서에 대한 수학 연산, 삼각 함수, 비트 연산, 비교 연산, 집계등을 제공
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)) #tensor([[-0.1788, -0.3389]]) #tensor([[0.1788, 0.3389]]) #tensor([[-0., -0.]]) #tensor([[-1., -1.]]) #tensor([[-0.1788, -0.3389]])
print(a) print(torch.min(a)) print(torch.max(a)) print(torch.std(a)) print(torch.prod(a)) print(torch.unique(torch.tensor([1,2,3,1,2,2]))) #tensor([[-0.1788, -0.3389]]) #tensor(-0.3389) #tensor(-0.1788) #tensor(0.1132) #tensor(0.0606) #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.min(dim=1)) # tensor([[0.1849, 0.3840], # [0.4086, 0.2098]]) # torch.return_types.max( # values=tensor([0.4086, 0.3840]), # indices=tensor([1, 0])) # torch.return_types.min( # values=tensor([0.1849, 0.2098]), # indices=tensor([0, 1]))
print(x) print(x.max(dim=0)) print(x.min(dim=1)) #tensor([[0.1849, 0.3840], # [0.4086, 0.2098]]) #torch.return_types.max( #values=tensor([0.4086, 0.3840]), #indices=tensor([1, 0])) #torch.return_types.min( #values=tensor([0.1849, 0.2098]), #indices=tensor([0, 1]))
x = torch.rand(2,2) print(x) y = torch.rand(2,2) print(y) #tensor([[0.7506, 0.2843], # [0.1169, 0.6632]]) #tensor([[0.8958, 0.3545], # [0.0266, 0.1434]])
torch.add
: 덧셈
print(x + y) print(torch.add(x,y)) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]
결과 텐서를 인자로 제공
result = torch.empty(2,4) torch.add(x, y, out=result) print(result) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]])
in-place
방식
in-place
방식으로 텐서의 값을 변경하는 연산 뒤에는 _''가 붙음
x.copy()
, x.t()
print(x) print(y) y.add_(x) print(y) #tensor([[0.7506, 0.2843], # [0.1169, 0.6632]]) #tensor([[0.8958, 0.3545], # [0.0266, 0.1434]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]])
torch.sub
: 뺄셈
print(x) print(y) print(x-y) print(torch.sub(x,y)) print(x.sub(y)) #tensor([[0.7506, 0.2843], # [0.1169, 0.6632]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]) #tensor([[-0.8958, -0.3545], # [-0.0266, -0.1434]]) #tensor([[-0.8958, -0.3545], # [-0.0266, -0.1434]]) #tensor([[-0.8958, -0.3545], # [-0.0266, -0.1434]])
torch.mul
: 곱셉
print(x) print(y) print(x*y) print(torch.mul(x,y)) print(x.mul(y)) #tensor([[0.7506, 0.2843], # [0.1169, 0.6632]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]) #tensor([[1.2357, 0.1816], # [0.0168, 0.5350]]) #tensor([[1.2357, 0.1816], # [0.0168, 0.5350]]) #tensor([[1.2357, 0.1816], # [0.0168, 0.5350]])
torch.div
: 나눗셈
print(x) print(y) print(x/y) print(torch.div(x,y)) print(x.div(y)) #tensor([[0.7506, 0.2843], # [0.1169, 0.6632]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]) #tensor([[0.4559, 0.4450], # [0.8146, 0.8222]]) #tensor([[0.4559, 0.4450], # [0.8146, 0.8222]]) #tensor([[0.4559, 0.4450], # [0.8146, 0.8222]])
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.7506, 0.2843], 3 [0.1169, 0.6632]]) #tensor([[1.6464, 0.6388], # [0.1435, 0.8066]]) #tensor([[1.2765, 0.7088], # [0.2876, 0.6096]]) #tensor([[1.2765, 0.7088], # [0.2876, 0.6096]]) #torch.return_types.svd( #U=tensor([[-0.9284, -0.3715], # [-0.3715, 0.9284]]), #S=tensor([1.5658, 0.3668]), #V=tensor([[-0.8251, -0.5649], # [-0.5649, 0.8251]]))
인덱싱(Indexing)
: NumPy처럼 인덱싱 형태로 사용가능
x = torch.Tensor([[1,2], [3,4]]) print(x) print(x[0,0]) print(x[0,1]) print(x[1,0]) print(x[1,0]) print(x[:,0]) print(x[:,1]) print(x[0, :]) print(x[1, :]) #tensor([[1., 2.], # [3., 4.]]) #tensor(1.) #tensor(2.) #tensor(3.) #tensor(3.) #tensor([1., 3.]) #tensor([2., 4.]) #tensor([1., 2.]) #tensor([3., 4.])
view
: 텐서의 크기(size)
나 모양(shape)
을 변경
기본적으로 변경 전과 후에 텐서 안의 원소 개수가 유지되어야 함
-1로 설정되면 계산을 통해 해당 크기값을 유추