지금까지 모델과 데이터를 준비하는 단계가 완료되어, 데이터에 매개변수를 최적화하여 모델을 학습하고, 검증하고, 테스트를 해야 한다.
모델을 학습하는 과정은 반복 과정을 거친다.
즉, 각 반복 단계에서 모델은 출력을 추측하고, 추측과 정답 사이의 오류(손실, loss)를 계산하고, 매개변수에 대한 오류의 도함수(derivation)를 수집한 뒤, 경사하강법을 사용하여 이 파라미터들을 최적화(optimize)한다.
기본(Pre-requisite) 코드
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor()
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNetwork()
하이퍼파라미터(Hyperparameter)
- 모델 최적화 과정을 제어할 수 있는 조절 가능한 매개변수이다.
- 서로 다른 하이퍼파라미터 값은 모델 학습과 수렴율(convergence rage)에 영향을 미칠 수 있다.
- 학습 시, 정의하는 하이퍼파라미터 종류
- 에폭(epoch) 수: 데이터셋을 반복하는 횟수
- 배치 크기(batch size): 매개변수가 갱신되기 전, 신경망을 통해 전파된 데이터 샘플의 수
- 학습률(learning rate): 각 배치-에폭에서 모델의 매개변수를 조절하는 비율로, 값이 작을수록 학습 속도가 느려지고, 값이 크면 학습 중 예측할 수 없는 동작이 발생할 수 있다.
learning_rate = 1e-3
batch_size = 64
epochs = 5
최적화 단계(Optimization Loop)
- 하이퍼파라미터를 설정한 뒤, 최적화 단계를 통해 모델을 학습하고 최적화할 수 있는데 최적화 단계의 각 반복(iteration)을 에폭이라고 하며 하나의 에폭은 두 개의 부분으로 구성된다.
- 학습 단계(train loop): 학습용 데이터셋을 반복(iterate)하고 최적의 매개변수로 수렴한다.
- 검증/테스트 단계(validation/test loop): 모델 성능이 개선되고 있는지를 확인하기 위해 테스트 데이터셋을 반복(iterate)한다.
손실 함수(loss function)
- 획득한 결과와 실제 값 사이의 틀린 정도(degree of dissimilarity)를 측정하며, 학습 중 이 값을 최소화하려고 한다.
- 주어진 데이터 샘플을 입력으로 계산한 예측과 정답(label)을 비교하여 손실(loss)을 계산한다.
- 회귀 문제(regression task)에 사용하는 nn.MSELoss 나, 분류(classification)에 사용하는 nn.NLLLoss, 그리고 nn.LogSoftmax와 nn.NLLLoss를 합친 nn.CrossEntropyLoss 등이 있다.
- 아래의 코드는 모델의 출력 로짓(logit)을 nn.CrossEntropyLoss에 전달하여 로짓을 정규화하고 예측 오류를 계산한다.
# 손실 함수를 초기화합니다.
loss_fn = nn.CrossEntropyLoss()
옵티마이저(Optimizer)
- 각 학습 단계에서 모델의 오류를 줄이기 위해 모델 매개변수를 조정하는 과정인 최적화 과정이 수행되는 방식(여기에서는 SGD)을 정의한다.
- 확률적 경사하강법, SGD, Stochastic Gradient Descent
- 이외에도 ADAM, RMSProp 등 다른 종류의 모델과 데이터에서 더 잘 작동하는 다양한 옵티마이저가 있다.
- 학습하려는 모델의 매개변수와 학습률(learning rate) 하이퍼파라미터를 등록하여 옵티마이저를 초기화한다.
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
- 학습 단계(loop)에서 최적화는 세단계로 이루어진다.
- optimizer.zero_grad() 호출
- 모델 매개변수의 변화도를 재설정
- 기본적으로 변화도는 더해지기 (add up) 때문에 중복 계산을 막기 위해 반복할 때마다 명시적으로 0으로 설정한다.
- loss.backwards() 호출
- 예측 손실(prediction loss)를 역전파하여 각 매개변수에 대한 손실의 변화도를 저장한다.
- optimizer.step() 호출
- 역전파 단계에서 수집된 변화도로 매개변수를 조정한다.
- optimizer.zero_grad() 호출
전체 구현
- 아래 코드에서, 최적화 코드를 반복하여 수행하는 train_loop 와 테스트 데이터로 모델의 성능을 측정하는 test_loop 를 정의한다.
def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
for batch, (X, y) in enumerate(dataloader):
# 예측(prediction)과 손실(loss) 계산
pred = model(X)
loss = loss_fn(pred, y)
# 역전파
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
def test_loop(dataloader, model, loss_fn):
size = len(dataloader.dataset)
num_batches = len(dataloader)
test_loss, correct = 0, 0
with torch.no_grad():
for X, y in dataloader:
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
- 손실 함수와 옵티마이저를 초기화하고, train_loop와 test_loop에 전달한다. (모델의 성능 향상을 알아보기 위해 자유롭게 에폭 수를 증가시킬 수도 있다)
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
epochs = 10
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
train_loop(train_dataloader, model, loss_fn, optimizer)
test_loop(test_dataloader, model, loss_fn)
print("Done!")
Out:
Epoch 1
-------------------------------
loss: 2.318174 [ 64/60000]
loss: 2.301629 [ 6464/60000]
loss: 2.280822 [12864/60000]
loss: 2.261336 [19264/60000]
loss: 2.270061 [25664/60000]
loss: 2.228065 [32064/60000]
loss: 2.237042 [38464/60000]
loss: 2.204938 [44864/60000]
loss: 2.201452 [51264/60000]
loss: 2.170017 [57664/60000]
Test Error:
Accuracy: 42.3%, Avg loss: 2.168972
Epoch 2
-------------------------------
loss: 2.186067 [ 64/60000]
loss: 2.172493 [ 6464/60000]
loss: 2.115172 [12864/60000]
loss: 2.119171 [19264/60000]
loss: 2.096284 [25664/60000]
loss: 2.024268 [32064/60000]
loss: 2.050137 [38464/60000]
loss: 1.977369 [44864/60000]
loss: 1.982604 [51264/60000]
loss: 1.908258 [57664/60000]
Test Error:
Accuracy: 56.0%, Avg loss: 1.913715
Epoch 3
-------------------------------
loss: 1.950127 [ 64/60000]
loss: 1.916448 [ 6464/60000]
loss: 1.805573 [12864/60000]
loss: 1.836245 [19264/60000]
loss: 1.748724 [25664/60000]
loss: 1.682930 [32064/60000]
loss: 1.706518 [38464/60000]
loss: 1.608603 [44864/60000]
loss: 1.647332 [51264/60000]
loss: 1.530819 [57664/60000]
Test Error:
Accuracy: 60.0%, Avg loss: 1.552530
Epoch 4
-------------------------------
loss: 1.623605 [ 64/60000]
loss: 1.578829 [ 6464/60000]
loss: 1.437440 [12864/60000]
loss: 1.501638 [19264/60000]
loss: 1.396851 [25664/60000]
loss: 1.375182 [32064/60000]
loss: 1.389938 [38464/60000]
loss: 1.310492 [44864/60000]
loss: 1.362651 [51264/60000]
loss: 1.249477 [57664/60000]
Test Error:
Accuracy: 62.7%, Avg loss: 1.277640
Epoch 5
-------------------------------
loss: 1.360952 [ 64/60000]
loss: 1.328950 [ 6464/60000]
loss: 1.172525 [12864/60000]
loss: 1.271350 [19264/60000]
loss: 1.160109 [25664/60000]
loss: 1.170827 [32064/60000]
loss: 1.189889 [38464/60000]
loss: 1.122468 [44864/60000]
loss: 1.177245 [51264/60000]
loss: 1.080366 [57664/60000]
Test Error:
Accuracy: 64.4%, Avg loss: 1.103479
Epoch 6
-------------------------------
loss: 1.180911 [ 64/60000]
loss: 1.167298 [ 6464/60000]
loss: 0.996107 [12864/60000]
loss: 1.126352 [19264/60000]
loss: 1.013324 [25664/60000]
loss: 1.032886 [32064/60000]
loss: 1.066103 [38464/60000]
loss: 1.003461 [44864/60000]
loss: 1.058020 [51264/60000]
loss: 0.974137 [57664/60000]
Test Error:
Accuracy: 65.8%, Avg loss: 0.991567
Epoch 7
-------------------------------
loss: 1.057039 [ 64/60000]
loss: 1.062698 [ 6464/60000]
loss: 0.876523 [12864/60000]
loss: 1.030043 [19264/60000]
loss: 0.921778 [25664/60000]
loss: 0.936227 [32064/60000]
loss: 0.985611 [38464/60000]
loss: 0.926966 [44864/60000]
loss: 0.977010 [51264/60000]
loss: 0.904160 [57664/60000]
Test Error:
Accuracy: 66.9%, Avg loss: 0.916095
Epoch 8
-------------------------------
loss: 0.967174 [ 64/60000]
loss: 0.990879 [ 6464/60000]
loss: 0.791893 [12864/60000]
loss: 0.962317 [19264/60000]
loss: 0.861355 [25664/60000]
loss: 0.865889 [32064/60000]
loss: 0.929974 [38464/60000]
loss: 0.876629 [44864/60000]
loss: 0.919236 [51264/60000]
loss: 0.854770 [57664/60000]
Test Error:
Accuracy: 68.3%, Avg loss: 0.862301
Epoch 9
-------------------------------
loss: 0.898741 [ 64/60000]
loss: 0.938024 [ 6464/60000]
loss: 0.729368 [12864/60000]
loss: 0.912538 [19264/60000]
loss: 0.818715 [25664/60000]
loss: 0.812803 [32064/60000]
loss: 0.888883 [38464/60000]
loss: 0.841987 [44864/60000]
loss: 0.876351 [51264/60000]
loss: 0.817710 [57664/60000]
Test Error:
Accuracy: 69.5%, Avg loss: 0.821909
Epoch 10
-------------------------------
loss: 0.844182 [ 64/60000]
loss: 0.896613 [ 6464/60000]
loss: 0.681131 [12864/60000]
loss: 0.874642 [19264/60000]
loss: 0.786545 [25664/60000]
loss: 0.771748 [32064/60000]
loss: 0.856368 [38464/60000]
loss: 0.816688 [44864/60000]
loss: 0.843121 [51264/60000]
loss: 0.788382 [57664/60000]
Test Error:
Accuracy: 70.7%, Avg loss: 0.790105
Done!
https://tutorials.pytorch.kr/beginner/basics/optimization_tutorial.html
모델 매개변수 최적화하기
파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 이제 모델과 데이터가 준비
tutorials.pytorch.kr
'Deep Learning & Machine Learning > PyTorch' 카테고리의 다른 글
[인프런 데이터과학 Part3]섹션1. 딥러닝 기본 배경지식(이론) (0) | 2024.05.20 |
---|---|
[PyTorch] tutorial, 5.Autograd (0) | 2024.05.19 |
[PyTorch] tutorial, 4.신경망 모델 구성하기 (0) | 2024.05.19 |
[PyTorch] tutorial, 3.변형(Transform) (0) | 2024.05.19 |
[PyTorch] tutorial, 2.Dataset과 DataLoader (0) | 2024.05.19 |