PyTorch로 구현하는 Optimization
모델과 데이터를 준비한 후에는 데이터에 대해 모델을 훈련, 검증, 테스트하고 매개변수를 최적화하는 과정을 진행합니다. 모델 훈련은 반복적인 과정으로, 각 반복에서 모델은 출력에 대한 추측을 하고, 추측의 오류(손실)를 계산하며, 오류에 대한 매개변수의 도함수(기울기)를 수집한 후, 경사 하강법을 사용하여 이 매개변수들을 최적화합니다.
필수 코드 로드
이전 섹션에서의 Datasets & DataLoaders 및 모델 구축 코드를 불러와서 진행합니다.
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
# FashionMNIST 데이터셋 로드
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().__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()
훈련 프로세스
모델의 훈련 과정은 다음 단계를 포함합니다:
1. 손실 함수 설정: 모델의 성능을 측정하기 위해 손실 함수를 정의합니다. 이 예제에서는 크로스 엔트로피 손실 함수를 사용할 수 있습니다.
2. 옵티마이저 설정: 매개변수를 업데이트하기 위한 옵티마이저를 설정합니다. 일반적으로 SGD(확률적 경사 하강법)나 Adam과 같은 옵티마이저가 사용됩니다.
3. 훈련 루프 실행: 각 에폭마다 훈련 데이터셋을 사용하여 모델을 실행하고, 손실을 계산한 후, `backward()`를 호출하여 기울기를 계산하고, `optimizer.step()`을 호출하여 매개변수를 업데이트합니다.
4. 성능 평가: 훈련 과정에서 정기적으로 또는 훈련 후에 테스트 데이터셋을 사용하여 모델의 성능을 평가합니다.
이러한 단계들을 통해 모델은 점차적으로 데이터에 대한 정확한 예측을 할 수 있게 최적화됩니다.
모델 매개변수 최적화를 위한 훈련 및 검증 과정
모델과 데이터가 준비되었으므로, 이제 데이터에 대한 모델의 매개변수를 최적화하면서 모델을 훈련, 검증 및 테스트할 차례입니다. 모델 훈련은 반복적인 과정으로, 각 반복(iteration)에서 모델은 출력을 예측하고, 그 예측의 오류(손실)를 계산하며, 이 손실에 대한 매개변수의 기울기를 수집한 후, 경사 하강법을 통해 이러한 매개변수를 최적화합니다.
하이퍼파라미터 설정
모델 최적화 과정을 제어할 수 있는 조정 가능한 매개변수인 하이퍼파라미터를 정의합니다:
- 에폭 수(Number of Epochs): 데이터셋을 반복하는 횟수
- 배치 크기(Batch Size): 매개변수가 업데이트되기 전에 네트워크를 통해 전파되는 데이터 샘플의 수
- 학습률(Learning Rate): 각 배치/에폭에서 모델 매개변수를 얼마나 업데이트할지 결정합니다. 작은 값은 학습 속도를 느리게 하며, 큰 값은 훈련 중 예측할 수 없는 행동을 유발할 수 있습니다.
learning_rate = 1e-3
batch_size = 64
epochs = 5
최적화 루프
하이퍼파라미터를 설정한 후, 최적화 루프를 통해 모델을 훈련하고 최적화합니다. 최적화 루프의 각 반복을 에폭이라고 합니다.
각 에폭은 주로 두 부분으로 구성됩니다:
1. 훈련 루프(Train Loop): 훈련 데이터셋을 반복하고 최적의 매개변수로 수렴하려고 시도합니다.
2. 검증/테스트 루프(Validation/Test Loop): 테스트 데이터셋을 반복하여 모델 성능이 개선되고 있는지 확인합니다.
손실 함수와 최적화기
- 손실 함수(Loss Function): 훈련 데이터로부터 얻은 출력이 정답과 얼마나 다른지 측정합니다. 이 손실을 최소화하려고 합니다. 예를 들어, 회귀 작업에는 `nn.MSELoss`가 사용되고, 분류 작업에는 `nn.CrossEntropyLoss`가 사용됩니다.
loss_fn = nn.CrossEntropyLoss()
- 최적화(Optimizer): 모델 오류를 감소시키기 위해 매 훈련 단계에서 매개변수를 조정하는 과정입니다. 여기서는 확률적 경사 하강법(SGD)을 사용합니다.
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
훈련과 테스트 루프는 다음과 같습니다:
def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
model.train()
for batch, (X, y) in enumerate(dataloader):
pred = model(X)
loss = loss_fn(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
loss, current = loss.item(), batch * batch_size + 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
model.eval()
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")
위 코드를 실행하여 에폭 수를 증가시키면 모델의 성능 향상을 확인할 수 있습니다.
* 위 글은 모두 PyTorch 공식 문서를 바탕으로 작성되었습니다.