본문 바로가기
AI Framework/PyTorch

[PyTorch] 9주차: 모델 최적화 및 고급 주제

by cogito21_python 2024. 5. 30.
반응형

강의 목표

  • 모델 최적화 기법 이해 및 적용
  • 고급 PyTorch 기능 학습
  • 실제 프로젝트를 통해 모델 최적화 경험

강의 내용

1. 모델 최적화 개념

  • 모델 최적화의 중요성
    • 모델 성능 향상 및 학습 시간 단축
  • 주요 최적화 기법
    • 학습률 조정(Learning Rate Scheduling)
    • 조기 종료(Early Stopping)
    • 배치 정규화(Batch Normalization)
    • 드롭아웃(Dropout)

2. 학습률 조정

  • 학습률 조정의 필요성
    • 초기 학습률 설정의 어려움
    • 학습 진행에 따라 학습률을 조정하여 효율적인 학습
  • PyTorch에서의 학습률 스케줄러 사용
    • torch.optim.lr_scheduler 모듈 활용
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR

# 옵티마이저 및 학습률 스케줄러 설정
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)

# 학습 루프 내에서 스케줄러 사용
for epoch in range(num_epochs):
    model.train()
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    scheduler.step()  # 매 epoch 끝에서 학습률 갱신
    print(f'Epoch {epoch+1}, Loss: {loss.item()}, Learning Rate: {scheduler.get_last_lr()}')

 

3. 조기 종료(Early Stopping)

  • 조기 종료의 필요성
    • 과적합 방지
    • 학습 시간 단축
  • 조기 종료 구현
    • 검증 데이터셋의 성능 모니터링
    • 일정 에폭 동안 성능 향상이 없으면 학습 종료
     
import numpy as np

class EarlyStopping:
    def __init__(self, patience=5, min_delta=0):
        self.patience = patience
        self.min_delta = min_delta
        self.best_score = None
        self.counter = 0
        self.early_stop = False

    def __call__(self, val_loss):
        score = -val_loss

        if self.best_score is None:
            self.best_score = score
        elif score < self.best_score + self.min_delta:
            self.counter += 1
            if self.counter >= self.patience:
                self.early_stop = True
        else:
            self.best_score = score
            self.counter = 0

early_stopping = EarlyStopping(patience=3, min_delta=0.01)

for epoch in range(num_epochs):
    model.train()
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    val_loss = evaluate_model(model, val_loader)  # 검증 손실 계산
    early_stopping(val_loss)

    if early_stopping.early_stop:
        print(f'Early stopping at epoch {epoch+1}')
        break

 

4. 배치 정규화(Batch Normalization) 및 드롭아웃(Dropout)

  • 배치 정규화
    • 훈련 속도 향상 및 초기화 민감도 감소
    • nn.BatchNorm2d 사용
     
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(32)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(64)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.bn1(self.conv1(x))))
        x = self.pool(F.relu(self.bn2(self.conv2(x))))
        x = x.view(-1, 64 * 7 * 7)  # Flatten the tensor
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

 

  •  드롭아웃
    • 과적합 방지
    • nn.Dropout 사용
     
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.dropout = nn.Dropout(0.5)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 64 * 7 * 7)  # Flatten the tensor
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

 

5. 프로젝트 설명 및 진행

  • 프로젝트 개요
    • 고급 주제를 활용한 실전 프로젝트 수행
    • 모델 최적화 및 고급 기능을 활용한 성능 향상 시도
  • 데이터셋 선택
    • Kaggle 또는 기타 오픈 데이터셋에서 프로젝트 데이터셋 선택
    • 예시: CIFAR-10, Dogs vs. Cats, etc.
  • 프로젝트 단계
    • 데이터 전처리 및 준비
    • 모델 설계 및 구현
    • 모델 훈련 및 검증
    • 성능 평가 및 결과 분석

6. 프로젝트 예시

  • 예시 프로젝트: CIFAR-10 이미지 분류
    • 데이터셋 로드 및 전처리
    • 최적화 기법 및 고급 기능 적용
import torch
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torchvision.models as models
import torch.optim as optim
import torch.nn as nn
from torch.utils.data import DataLoader

# 데이터 전처리 변환
transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# CIFAR-10 데이터셋 로드
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
val_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)

# Pretrained ResNet 모델 로드 및 수정
model = models.resnet18(pretrained=True)
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 10)

# 배치 정규화 및 드롭아웃 추가
for param in model.parameters():
    param.requires_grad = False
for param in model.fc.parameters():
    param.requires_grad = True

# 손실 함수와 옵티마이저 설정
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=0.001)
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)

# 모델 학습
num_epochs = 25
early_stopping = EarlyStopping(patience=5, min_delta=0.01)

for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()

    scheduler.step()  # 매 epoch 끝에서 학습률 갱신
    val_loss = evaluate_model(model, val_loader)  # 검증 손실 계산

    print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}, Val Loss: {val_loss}, Learning Rate: {scheduler.get_last_lr()}')

    early_stopping(val_loss)
    if early_stopping.early_stop:
        print(f'Early stopping at epoch {epoch+1}')
        break

# 모델 평가
model.eval()
correct = 0
total = 0
반응형