Pytorch 공식 문서와 함께하는 Pytorch 튜토리얼_6(optimization)

bellfollow·2023년 9월 17일
0

Pytorch_tutorial

목록 보기
7/7
post-thumbnail

모델 변수 최적화하기

  • 모델과 데이터를 앞서 준배해놨으니, 데이터에 매개변수를 최적화하여 모델을 학습하고, 검증하고 테스트할 차례입니다.
  • 모델을 학습하는 과정은 반복적인 과정을 거칩니다
  1. 각 반복 단계에서 모델은 출력을 추측하고
  2. 추측과 정답사이의 오류(손실)을 계산하고
  3. 매개변수에 대한 오류의 도 함수를 수집한뒤
  4. 경사하강법을 사용하여 이 파라미터들을 최적화 함
    -이 과정에 대한 설명은 역전파 미적분링크를 보시면 이해가 빠릅니다. 개인적으로 이 링크에 있는 심층학습 부분을 들었더니 이해가 편하게 됐습니다.

기본코드

-이전 Dataset과 DataLoader, 신경망 모델 구성하기의 코드입니다.

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()
  • import 부분은 파이토치 라이브러리를 위한 torch, 뉴럴 네트워크를 위한 nn, 데이터 다운로드와 같은 기타 등등의 기능을 위한 DataLoader,datasets, 텐서를 활용하기 위한 ToTensor
  • FashionMNIST 훈련데이터와 테스트 데이터를 활용하기 위한 변수 traing_data, test_data
  • 데이터 사이즈 64(배치 사이즈)의 train_dataloader, test_dataloader 를 로드
  • NeuralNetwork 클래스 정의
  • 순전파는 forward로 진행, 역전파는 나중에 기술될 것

하이퍼파라미터(Hyperparameter)

  • 하이퍼파라마티 : 모델 최적화 과정을 제어할 수 있는 조절 가능한 매개변수
  • 서로 다른 하이퍼파라미터 값은 모델 학습과 수렴율(converagence rate)에 영향을 미칠 수 있습니다.
    -수렴율(converagence rate) : 정답에 얼마나 수렴하는지 비율
  • 하이퍼파라미터 정의
    -에폭(epoch)수 : 데이터셋을 반복하는 횟수
    -배치 크기(batch size) : 매개 변수가 갱신되기 전 신경망을 통해 전파된 데이터 샘플의 수
    -학습률(learning rate) : 각 batch/epoch에서 모델의 매개변수를 조절하는 비율, 값이 작을수록 학습 속도가 느려지고, 값이 크면 학습 중 에측할 수 없는 도작이 발생할 수 있음.
learning_rate = 1e-3
batch_size = 64
epochs = 5
  • 여기서 1e-3은 0.001을 지수표기법으로 표현하는 것
    -지수표기법: 1e+3의 경우 1000,10^3, 1e-3은 10^-3

최적화 단계(Optimazation Loop)

  • 하이퍼파라미터를 설정한 뒤엔느 최적화 단계를 통해 모델을 학습하고 최적화 할 수 있습니다.
  • 최적화 단계의 각 반복(iteration) epoch이라고 함, 하나의 epoch은 두 부분으로 구성됨
    1) 학습 단계(train loop) : 학습용 데이터셋을 반복하고 최적의 매개변수로 수렴합니다.
    2) 검증/테스트 단계(vaildation/test loop) : 모델 성능이 개선되고 있는지를 확인하기 위해 테스트 데이터셋을 반복

-학습 단계에서 일어나는 몇가지 개념을 간략히 살펴보겠습니다.

손실함수(loss function)

  • 손실함수는 획득한 결과와 실제 값의 틀린 정도를 측정하며, 이 값을 최소화하려고 합니다.
    -주어진 데이터 샘플을 입력으로 계산된 예측 값과 정답(label)을 비교하여 손실을 계산
  • 일반적인 손실함수는 회귀 문제(regression task)에 사용하는 nn.MSELoss나 분유레 사용되는 nn.NLLLoss 그리고 nn.LogSoftmaxnn.NLLLoss를 합친 nn.CrossEntropyLoss등이 있음
#손실 함수를 초기화합니다.
loss_fn = nn.CrossEntropyLoss()
  • nn.MSELoss : 평균 제곱 오차(Mean Squared Error), 예측값과 실제 타겟값의 차이의 제곱을 평균한 것
torch.nn.MSELoss(reduction='mean')

-인수와 기본값
-reduction: 손실 값을 어떻게 줄일지를 지정하는 인수로, 기본값은 mean

  • nn.NLLLoss : (Negative Log Likelihood) 주로 다중 클래스 분류(Multi-class classification) 문제에 사용되며, 모델의 출력 확률 분포와 실제 타깃 레이블 사이의 차이를 측정하여 모델을 학습하는데 사용됨
  • 모델이 출력하는 로그 확률 중 실제 타깃 레이블에 해당하는 값이 로그 확률을 사용하여 NLL 손실을 계산합니다.
  • NLL손실은 실제 타깃 레이블에 해당하는 로그 확률의 음수 값으로 정의되며, 모델의 예측이 실제 타깃 레이블과 일치할수록 손실 값이 낮아짐,
    -NLLLoss는 모델의 예측이 정확하게 타깃 레이블을 예측하는 데 중요한 역할을 함
  • NLLLoss는 다양한 옵션을 제공하여 손실 값의 계산방식을 조절할 수 있음, 가중치, 무시할 레이블 , 손실 값의 평균 또는 합, 그리고 손실 값의 줄임 방식 등을 설정하여 모델 학습에 적합한 손실 함수를 사용할 수 있음
torch.nn.NLLLoss(weight=None, ignore_index=-100, reduction='mean')

-인수와 기본값

  • weight : 각 클래스에 대한 가중치를 지정하는 인수로, 클래스 불균형을 처리할 때 사용될 수 있습니다. 기본값은 None, 모든 클래스에 대한 동일한 가중치를 사용합니다.
  • ignore_index : 손실 계산시 무시할 레이블의 인덱스를 지정하는 인수로, 기본값은 -100입니다.
    ex)padding이 있는 시퀀스 데이터를 처리할 때, 패딩 토큰에 해당하는 레이블을 무시할 수 있습니다.
  • reduction : 손실 값을 어떻게 줄일지를 지정하는 인수로, 기본값은 mean입니다. sum,none 옵션도 가지고 있습니다.
  • nn.CrossEntropyLoss : 다중 클래스 분류 문제에서 주로 사용되며, 모델의 예측값과 실제 레이블 간의 차이를 계산하여 모델을 학습시키는데 사용됨
  • torch.nn.CrossEntropyLoss 클래스를 제공하여 계산할 수 있음, 그리고 이 클래스는 소프트맥스 함수를 내장하고 있어, 모델의 출력값에 소프트맥스를 적용할 필요 없이 모델의 출려값과 레이블을 입력으로 받아 손실을 계산합니다.
torch.nn.CrossEntropyLoss(weight=None, ignore_index=-100, reduction='mean')

-CrossEntropyLoss 인수

  • weight: 클래스별 가중치를 적용할 경우 사용하는 가중치 텐서, 기본값은 None
  • ignore_index: 무시할 클래스의 인덱스, 기본값은 -100
  • reduction: 손실을 감소할 방법을 지정,(mean,sun,none 중 하나를 선택) 기본값은 mean

옵티마이저

  • 최적화: 각 학습단계에서 모델의 오류를 줄이기 위한 모델 매개변수를 조정하는 과정,
    -최적화 알고리즘은 이 과정이 수행되는 방식,여기서SGD(Stochatic Gradient Descent)를 정의

  • 모든 최적화 절차는 optimizer 객체에 캡슐화 됨
    -이번 코드에서는 SGD 옵티마이저를 사용하고 있고, Pytorch에는 ADAM이나 RMSProp과 같은 다른 종류의 모델과 데이터에서 더 잘 작동되는 다양한 옵티마이저가 있음

  • 학습하려는 모델의 매개변수와 학습률 하이퍼파라미터를 등록하여 옵티마이저를 초기화함

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

Pytorch의 다른 옵티마이저

  • ADAM
  • RMSProp

전체 구현

  • 최적화 코드를 반복하여 수행하는 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 정의이니 넘어가고
  • 두번째 줄부터 데이터셋 전체의 크기를 len에 넘깁니다.
  • for 루프의 경우 batch를 순회합니다. batch는 배치 인덱스 이고, (X,y)는 입력 데이터와, 타깃 레이블의 배치를 나타냅니다.
  • 입력 데이터에 대한 모델의 예측을 계산하고, 지정된 손실함수를 사용해 손실을 계산합니다. 이부분이 순전파에 해당합니다.
  • 역전파 부분입니다. .backward()를 호출하여 역전파를 수행합니다. 역전파를 수행하며 gradient를 계산하고 optimizer를 사용하여 모델의 매개변수를 업데이트 합니다.
  • 마지막은 훈련 진행상황을 출력해 줍니다.
  • 다음은 test_loop 함수정의입니다.
  • 여기도 데이터셋의 크기를 구해 size에 저장합니다.
  • num_batches = len(dataloader)은 제공된 데이터로더로부터 생성될 수 있는 미니 배치의 수를 계산함.
  • test_loss, correct 변수는 각 손실과 정확한 예측을 저장할 변수입니다.
  • torch.no_grad는 더이상 값의 추적이 필요없어짐에 따라 추적을 멈추기위해 붙인다.
    -모델을 학습한 뒤 입력 데이터를 단순히 적용하기만 하는 경우와 같이 순전파 연산만 필요한 경우에는, 이러한 추적이나 지원이 필요없기에 추적을 멈춥니다.
  • 추적을 그만두는 코드 아래는 순전파를 시행합니다.
  • test_loss는 테스트 안에서의 평균적인 손실을 계산하고, correct 는 정확도를 나타냅니다.

최종 코드

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!")
profile
코딩 함 맛있게 요리해보겠심더

0개의 댓글