CIFAR10

주제무·2022년 11월 27일
0

나중에 볼것

목록 보기
1/5

친구 과제로 나온 cifar10 acc > 0.9를 시험삼아 해봤다.
cifar10이야 클래스가 10개밖에 되지 않고 쉬운 과제라고 생각해 금방 결과가 나올 것이라 생각했다.

My code

# -*- coding: utf-8 -*-
"""cifar10.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1vz-O_IbWNJ3gSbCdjbhB-zRbpVs8ZHf3
"""

# GPU 스펙 확인
!nvidia-smi -L

import warnings
warnings.filterwarnings("ignore")

import os
from collections import Counter

import albumentations as A
import albumentations.pytorch as AP
import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import torch
import torch. nn as nn
from torch.utils.data import Dataset, DataLoader
import torchvision.transforms as T
from torchvision.datasets import CIFAR10
from tqdm import tqdm

"""# Sample in dataset"""

ds = CIFAR10(root='./data', train=True, download=True)
ds

# 이미지 확인
sample = ds[0][0]
print(sample.size)

plt.imshow(sample)
plt.axis(False)
plt.show()

# 이미지 사이즈가 32로 유일한 지 체크
set([img[0].size for img in ds])

# 레이블 분포가 균등한 지 확인
Counter([label[1] for label in ds])

"""# Load dataset

## Dataset
"""

def transform(img):
  img = np.array(img) / 255.
  t = A.Compose([
            A.OneOf([
                A.VerticalFlip(),
                A.HorizontalFlip()]),
            A.Rotate(limit=45),
            A.ShiftScaleRotate(rotate_limit=20),
            A.Cutout(num_holes=5, max_h_size=4, max_w_size=4, fill_value=0),
            AP.ToTensorV2()
        ])
  transformed = t(image=img)
  return transformed['image']

def transform_test(img):
  img = np.array(img) / 255.
  t = A.Compose([
            AP.ToTensorV2()
        ])
  transformed = t(image=img)
  return transformed['image']

trainds = CIFAR10(root='./data', train=True, download=True, transform=transform)
trainds

"""## DataLoader

### parameter
"""

# parameter
assert torch.cuda.is_available() # highly recommend GPU environment
device = 'cuda'
num_cls = 10
val_size = len(trainds) // 5 # 20% validation size
batch_size = 256
lr = 1e-3
epochs = 100

random_indices = np.random.randint(len(trainds), size=(len(trainds), ))
train_idx = random_indices[val_size:]
val_idx = random_indices[:val_size]
len(train_idx), len(val_idx)

train_loader = DataLoader(trainds, batch_size, num_workers=2, sampler=train_idx)
val_loader = DataLoader(trainds, batch_size, num_workers=2, sampler=val_idx)
len(train_loader), len(val_loader)

"""# Model"""

model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', weights='ResNet50_Weights.IMAGENET1K_V1')
model.fc = nn.Linear(2048, num_cls)
model = model.to(device, dtype=torch.double)

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)

"""# Train"""

patience = 0

for epoch in range(1, epochs+1):
  with tqdm(train_loader, total=len(train_loader), desc='Train ') as iterator:
    num_iter = len(train_loader)
    current_total_loss = 0.

    model.train()
    for idx, (X, y) in enumerate(iterator, start=1):
      X, y = X.to(device), y.to(device)
      output = model(X)
      loss = loss_fn(output, y)

      optimizer.zero_grad()
      loss.backward()
      optimizer.step()

      current_total_loss += loss
      loss_mean = current_total_loss / idx
      log = f'loss: {loss_mean:.4f}   epoch: {epoch}'
      iterator.set_postfix_str(log)
  
  best_val_loss = np.Inf
  
  model.eval()
  with torch.no_grad():
    with tqdm(val_loader, total=len(val_loader), desc='Validation ') as iterator:
      num_iter = len(val_loader)
      num_ds = len(val_idx)
      total_loss = 0.
      acc = 0.

      model.train()
      for X, y in iterator:
        X, y = X.to(device), y.to(device)
        output = model(X)
        acc += (output.argmax(1) == y).cpu().sum().item()
        loss = loss_fn(output, y)
        total_loss += loss

        log = f'loss: {total_loss/num_iter:.4f}   accuracy: {acc/num_ds*100:.2f}%'
        iterator.set_postfix_str(log)
  
  if best_val_loss > total_loss:
    patience = 0
    best_val_loss = total_loss
  if best_val_loss <= total_loss:
    patience += 1
    if patience > 4:
      break
  scheduler.step()
  print()

testds = CIFAR10(root='./data', train=False, download=True, transform=transform_test)
testds

test_loader = DataLoader(testds, batch_size)
len(test_loader)

Test result

Test dataset Accuracy : 0.8304

acc = 0.
model.eval()
with torch.no_grad():
  for X, y in test_loader:
    X, y = X.to(device), y.to(device)
    output = model(X)

    acc += (output.argmax(1)==y).cpu().sum().item()
  acc /= len(test_loader.dataset)
acc # 0.8304

참고

Why is my validation loss lower than my training loss?

loss function & optimization & regularization의 관계
이 셋의 관계가 뚜렷하게 머리에 그려지지 않는다.

crossentropy loss in pytorch
수식으로 이해하고 싶은 것

최종적으로 완성할 것

0개의 댓글