본문 바로가기

Deep Learning & Machine Learning/PyTorch

[PyTorch] tutorial, 6.최적화(Optimization)

지금까지 모델과 데이터를 준비하는 단계가 완료되어, 데이터에 매개변수를 최적화하여 모델을 학습하고, 검증하고, 테스트를 해야 한다.
모델을 학습하는 과정은 반복 과정을 거친다.
즉, 각 반복 단계에서 모델은 출력을 추측하고, 추측과 정답 사이의 오류(손실, 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() 호출
      • 역전파 단계에서 수집된 변화도로 매개변수를 조정한다. 

 

 

전체 구현

  • 아래 코드에서, 최적화 코드를 반복하여 수행하는 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