Pytorch Tutorials
Pytorch_Brief Tutorials
0. Why PyTorch?
🤔 Tensorflow:
∙Google에서 개발
∙딥러닝전용하드웨어인 TPU를 갖고 있어 GPU에서 상대적으로 자유로움
🤔 Pytorch:
∙facebook의 주도하에 개발,
∙Nvidia의 cuda GPU에 더욱 최적화
∙Python First, 깔끔한 코드, numpy와의 호환성, Autograd, Dynamic Graph 등의 장점
1. Tensor
pytorch의 tensor는 numpy의 배열인 ndarray와 같은 개념으로
pytorch에서 연산을 수행하기 위한 가장 기본적인 객체이다. (앞으로의 모든 연산은 이 tensor 객체를 통해서 진행)
ex) numpy와 pytorch는 굉장히 비슷한 방식의 코딩스타일을 갖는다.
(자료형의 경우에도 torch.uint8과 같이 표기가 가능)
import numpy as np x = np.array([[1,2], [3,4]]) import torch x = torch.Tensor([[1,2], [3,4]]) cf) torch.Tensor는 default로 float32를 갖는다.
2. Autograd
Autograd는 자동으로 미분 및 역전파를 수행하는 기능이다.
즉, 대부분의 tensor간의 연산을 크게 신경 쓸 필요 없이 역전파알고리즘 수행 명령어를 호출할 수 있다.
이때, tensor간의 연산을 수행할 때마다 동적으로 computational graph를 생성하며,
연산의 결과물이 어떤 tensor로부터 어떤 연산을 통해 왔는지 또한 추적한다.
→ 결과적으로 최종 스칼라값에 역전파를 통한 미분을 수행 시, 각 tensor는 자식노드에 해당하는 tensor와 연산을 자동으로 찾아 역전파알고리즘을 계속 수행할 수 있게한다.
🤔 기존 keras 및 tensorflow와 다른점??
keras와 tensorflow는 미리 정의한 연산들을 컴파일을 통해 고정, 정해진 입력에 맞춰 tensor를 순전파 시켜야 한다.
반면, Pytorch는 정해진 연산이 없고 모델은 배워야 하는 parameter tensor만 미리 알고있다.
즉, 가중치들이 어떠한 연산을 통해 학습 or 연산에 관여하는지 알 수 없고, 연산이 수행된 직 후 알 수 있다.
기울기를 구할 필요가 없는 연산의 경우, 다음과 같은 with 문법을 사용해 연산을 수행할 수 있는데, 이는 prediction과 inference등을 수행할 때 유용하며, 기울기를 구하기 위한 computational graph 생성 등의 사전작업을 생략하여 연산속도 및 메모리 사용측면에서도 큰 이점이 존재한다.
with torch.no_grad(): z = (x+y) + torch.Tensor(2,2)
3. nn.Module
nn.Module 클래스는 사용자가 그 위에서 필요한 모델 구조를 구현할 수 있게 해준다.
nn.Module을 상속한 사용자클래스는 다시 내부에 nn.Module을 상속한 클래스객체를 선언 및 변수로 사용할 수 있다.
ex) Feed Forward 구현
x ∈ R16×10import torch import torch.nn as nn def linear(x, W, b): return torch.mm(W, x) + b class MyLinear(nn.Module): def __init__(self, input_size, output_size): super().__init__() self.W = torch.FloatTensor(input_size, output_size) self.b = torch.FloatTensor(output_size) def forward(self, x): y = torch.mm(self.W, x) + self.b return y x = torch.Tensor(16, 10) linear = MyLinear(10, 5) y = linear(x)
W ∈ R 10×5
b ∈ R5
다만, 현재 parameter(W, b)의 경우, [ ]로 학습가능한 파라미터가 없다고 출력된다.>>> print([p.size() for p in linear.parameters()]) >>> [ ]
따라서 Parameter 클래스를 사용해 tensor를 감싸야 한다.
import torch import torch.nn as nn def linear(x, W, b): return torch.mm(W, x) + b class MyLinear(nn.Module): def __init__(self, input_size, output_size): super().__init__() self.W = nn.Parameter(torch.FloatTensor(input_size, output_size), requires_grad=True) self.b = nn.Parameter(torch.FloatTensor(output_size), requires_grad=True) def forward(self, x): y = torch.mm(self.W, x) + self.b return y x = torch.Tensor(16, 10) linear = MyLinear(10, 5) y = linear(x)
위의 경우, 출력값으로 [torch.Size([10, 5]), torch.Size([5])] 가 출력된다.
4. train()과 eval()
Backpropagation Algorithm의 경우, backward()함수를 이용해 진행가능하며, 이때 loss함수를 앞에 붙이는 형태로 표현한다.
loss.backward()
train과 eval함수는 모델에 대한 training time과 inference time의 모드를 쉽게 전환할 수 있는 방법이다.
nn.Module을 상속받아 구현∙생성된 객체는 기본적으로 train모드로 이를 eval()을 사용해 추론모드로 바꿀 수 있다.
이는 Dropout, Batch Norm 같은 학습시와 추론 시 서로 다른 forward()동작을 하는 모듈들에도 올바르게 동작할 수 있다.
다만, 추론이 끝나면 다시 train()을 선언 해 원래의 train모드로 돌아가줘야 한다.
5. GPU 사용하기
cuda() 함수
① 원하는 tensor객체를 GPU메모리에 복사하거나
② nn.Module의 하위클래스를 GPU메모리로 이동시킬 수 있다.
x = torch.cuda.FloatTensor(16, 10) linear = MyLinear(10, 5) linear.cuda() y = linear(x)
cpu() 함수
다시 PC의 메모리로 복사하거나 이동시킬 수 있다.
to() 함수
tensor 또는 모듈을 원하는 device로 보낼 수 있다.
6. Pytorch에서 DNN을 수행하는 과정 요약 및 예시
① nn.Module 클래스를 상속받아 forward함수를 통해 모델구조 선언
② 해당 클래스 객체 생성
③ Optimizer 생성, 생성한 모델의 parameter를 최적화대상으로 등록
④ Data로 mini-batch를 구성, 순전파 연산그래프 생성
⑤ 손실함수를 통해 최종결과값, 손실값 계산
⑥ 손실에 대해서 backward() 호출
→ 이를통해 연산그래프 상의 tensor들의 gradient가 채워짐
⑦ ③의 optimizer에서 step()을 호출, 1 step 수행
⑧ ④로 돌아가 반복
7. Pytorch 실습
[Linear Regression 분석]
📌 조건
∙ 임의로 tensor를 생성, 근사하고자하는 정답함수(wx+b)에 넣어 정답(y)을 구함
∙ 신경망 통과한 y_hat과의 차이를 구함(이때, 오류함수는 MSE Loss function을 사용)
∙ SGD를 이용해 optimization 진행
❗️ 1개의 Linear Layer를 갖는 MyModel이라는 모듈 선언
import random
import torch
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self, input_size, output_size):
super(MyModel, self).__init__()
self.linear = nn.Linear(input_size, output_size)
def forward(self, x):
y = self.linear(x)
return y
❗️ Wx + b가 3x1 + x2 - 2x3에 근사한다 가정하자.
def ground_truth(x):
return 3*x[:,0] + x[:,1] - 2*x[:,2]
❗️ Hyper-Parameter 설정
batch_size = 1
epoch = 1000
iter = 10000
model = Mymodel(3, 1)
optim = torch.optim.SGD(model.parameters(), lr=0.0001, momentum=0.1)
❗️ Model과 tensor를 입력받아 순전파 후, 역전파알고리즘을 수행해 경사하강법 1 step을 진행
def train(model, x, y, optim):
# 모듈의 모든 파라미터의 기울기 초기화
optim.zero_grad()
# Feed-Forward
y_hat = model(x)
# MSE Loss
loss = ((y-y_hat)**2).sum() / x.size(0)
# BP Algorithm
loss.backward()
# GD 1 step
optim.step()
return loss.data
❗️ Train & Inference time
for epoch in range(epoch):
# train 설정
avg_loss = 0
for i in range(iter):
x = torch.rand(batch_size, 3)
y = ground_truth(x.data)
loss = train(model, x, y, optim)
avg_loss += loss
avg_loss = avg_loss / iter
# valid 설정
x_val = torch.FloatTensor([[.3, .2, .1]])
y_val = ground_truth(x_val.data)
# inference
model.eval()
y_hat = model(x_val)
model.train()
print(avg_loss, y_val.data[0], y_hat.data[0, 0])
# finish
if avg_loss < .001:
break
'Gain Study' 카테고리의 다른 글
[Gain Study]. inference time, Mobilenet, 배포 (0) | 2023.08.19 |
---|