Sitemap
pjj11005

pjj11005

AI Engineer

Deep Learning-Pytorch(1)

12 min readDec 26, 2024

--

Wanted 10월 AI Challenge 내용 정리 글입니다.

학습과 추론 과정

Press enter or click to view image in full size
https://velog.io/@stresszero/pytorch-workflow

학습 과정

  1. 데이터 저장 및 다운로드 : 양질의 데이터 = 좋은 모델 생성
  2. 데이터 불러오기
  • 데이터 불러오기(Dataset) + 전처리
  • 병렬 처리(DataLoader)

3. 모델 설계하기

  • Class 형태로 설계, 필요 모듈 작성(init), 데이터 흐름 명시

4. 모델 생성 : 하이퍼파라미터로 다양한 모델 조절 생성

Get pjj11005’s stories in your inbox

Join Medium for free to get updates from this writer.

5. 모델 학습 세팅하기

  • AI 모델, Loss, Optimizer
  • 학습 Loop, Logger

6. 모델 학습하기

  • 학습 중간 과정 확인(Loss + meta data Visualize)

7. 평가 과정

  • Validation(test X), 목표 metric 설정, 저장 코드 작성

추론 과정

  1. 데이터 준비 : 평가 데이터 or 실제 데이터 불러오기
  2. 모델 설계 : 학습 가정에서 사용한 모델 설계도 + 최종 모델의 하이퍼파라미터
  3. 학습 모델 : 학습시킨 모델의 weight 값 가져오기
  4. 최종 모델 생성 : 2번 + 3번
  5. 추론 결과 : 추론 결과 해석 및 학습 과정 복기

학습을 했다면 하이퍼파라미터와 weight 값은 꼭 필요하다

Pytorch 코드의 틀

데이터 불러오기

  1. 딱 1개의 데이터 어떻게 가져오기 : Dataset

2. 데이터 1개씩 여러번 가져와 모인 데이터들에 추가적인 처리 적용하여 모델에 넣어주기 : DataLoader

AI 모델 생성

  1. 데이터 입출력(feed forward)을 갖고 있어야 함 : nn.Module 상속 받아 사용

2. nn.Module 능력 활용을 위한 필수 함수 존재

  • __init__ : feed forward 에서 사용되는 모듈 선언, 구조화 된 코드 작업을 위해 필요
  • forward : feed forward의 흐름 정의, 미구현 시 error 발생

코드의 구조화

구조화된 코드
  • 유지 보수와 재사용성을 극대화 시키기 위한 코드 구조화
  • 개념 단위 구조화 & 통합을 통해 가독성 상승

networks/vgg.py

import torch.nn as nn

# 모델 설계도 만들기
class myVGG(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.layer3 = nn.Sequential(
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.layer4 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.layer5 = nn.Sequential(
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.out = nn.Sequential(
nn.Linear(512, 100),
nn.ReLU(),
nn.Linear(100, 100),
nn.ReLU(),
nn.Linear(100, num_classes)
)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.layer5(x)
x = x.view(x.size(0), -1)
x = self.out(x)
return x

utils/getModules.py


from torchvision.datasets import CIFAR10
from torchvision.transforms import Compose, ToTensor, Normalize
from torch.utils.data import DataLoader

# 전처리
def load_transform():
# cifar10 이미지의 평균과 표준편차
CIFAR_MEAN = [0.491, 0.482, 0.447]
CIFAR_STD = [0.247, 0.244, 0.262]

transform = Compose([ToTensor(),
Normalize(mean=CIFAR_MEAN, std=CIFAR_STD)])
return transform

# dataset 필요
def load_datasets(transform):
train_dataset = CIFAR10(root='../data', train=True, download=True, transform=transform)
test_dataset = CIFAR10(root='../data', train=False, download=True, transform=transform)
return train_dataset, test_dataset

# dataloader 필요
def load_dataloaders(batch_size):
transform = load_transform()
train_dataset, test_dataset = load_datasets(transform)

train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True, num_workers=0)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False, num_workers=0)
return train_loader, test_loader

utils/tools.py

import torch 

# 평가 함수
def evaluate(model, test_loader, device):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)

outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
### 다시 train 모드로
model.train()
return correct / total

train.py

# 패키지 임포트 
import torch
import torch.nn as nn
from torch.optim import Adam

from utils.tools import evaluate
from utils.getModules import load_dataloaders
from networks.vgg import myVGG

# Hparam 설정
batch_size = 100
num_classes = 10
num_epochs = 10
# device 설정
device='cuda' if torch.cuda.is_available() else 'cpu'

## 데이터 처리하는 과정 (CIFAR10 활용)
train_loader, test_loader = load_dataloaders(batch_size)

## 모델 만들기 ##

# 모델 생성에 사용이 될 Hparam 설정
''' 상단에 전체 Hparam 적는 과정에 기입 '''
# 모델 객체를 생성 (설계도 + Hparam)
model = myVGG(num_classes=num_classes).to(device)

# Loss
loss_func = nn.CrossEntropyLoss()
# Optimizer
optimizer = Adam(model.parameters(), lr=0.0001)

best_acc = 0
# for loop를 돌면서 데이터를 불러오기
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.to(device)
labels = labels.to(device)

# 불러온 데이터를 모델에 넣기
outputs = model(images)
# 나온 출력물로 loss를 계산
loss = loss_func(outputs, labels)

# Loss로 back prop 진행
loss.backward()
# optimizer를 이용해 최적화를 진행
optimizer.step()
optimizer.zero_grad()

# 학습 중간에
if (i+1) % 100 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item()}')
# 평가를 진행해서
acc = evaluate(model, test_loader, device)
# 성능이 좋으면
if acc > best_acc:
best_acc = acc
# 저장을 진행
torch.save(model.state_dict(), f'./best_model.ckpt')

infer.py

# 패키지를 임포트 
import torch
from PIL import Image
from torch.nn.functional import softmax

from utils.getModules import load_transform
from networks.vgg import myVGG

# device 설정
device='cuda' if torch.cuda.is_available() else 'cpu'

# 추론에 사용할 데이터를 준비 (전처리)
example_image_path = 'plane.png'
# 이미지 읽고
image = Image.open(example_image_path)
# 크기 변환 (32 x 32)
image = image.resize((32, 32))

# 학습에서 사용한 전처리 설정
transform = load_transform()

# 전처리 진행
image = transform(image)
image = image.unsqueeze(0).to(device)

## 학습이 완료된 최고의 모델을 준비하기
num_classes = 10
model = myVGG(num_classes=num_classes)

# 속이 빈 모델에 학습된 모델의 wieght를 덮어 씌우기
weight = torch.load('best_model.ckpt', map_location=device)
model.load_state_dict(weight)
model = model.to(device)

# 준비된 데이터를 모델에 넣기
### model 평가 모드
model.eval()
output = model(image)

## 결과를 분석
# 추론 결과 만들어내기
output = output[0]
probabilities = softmax(output, dim=0) # softmax : 확률값으로 변환
prob, index = torch.max(probabilities, dim=0)
prob = prob * 100

labels = ['airplane', 'automobile', 'bird',
'cat', 'deer', 'dog', 'frog',
'horse', 'ship', 'truck']
predict = labels[index]

print(f'해당 이미지를 보고 딥러닝 모델은 {prob:.2f}% 의 확률로 {predict}이라고 대답했다.')

# 모델의 추론 결과를 보고 객관적인 평가 내려보기

--

--