본문 바로가기
수업 복습/머신러닝과 딥러닝

포켓몬 분류

by 김복칠 2024. 3. 27.

1. 포켓몬 분류

 

Pokemon Generation One

Gotta train 'em all!

www.kaggle.com

 

Complete Pokemon Image Dataset

2,500+ clean labeled images, all official art, for Generations 1 through 8.

www.kaggle.com

import os

os.environ['KAGGLE_USERNAME'] = 'sakongmyoungheun'
os.environ['KAGGLE_KEY'] = 'eebb8c6baa890a589e08e51889cc3832'
!kaggle datasets download -d thedagger/pokemon-generation-one
!unzip -q pokemon-generation-one.zip
!kaggle datasets download -d hlrhegemony/pokemon-image-dataset
!unzip -q pokemon-image-dataset.zip
!mv dataset train
!rm -rf train/dataset # 데이터가 중복되어 있기 때문에 삭제하는 과정, -rf 명령어는 없어도 에러나지 말라는 뜻
!mv images validation

# train : 149, validation : 898
# validation 에서 train 에 있는 디렉토리를 확인하여 없는 디렉토리를 모두 제거

import shutil

# train과 val에 동일한 폴더(label)이 없으면 제거하는 과정
for val_label in validation_labels:
    if val_label not in train_labels:
        shutil.rmtree(os.path.join('validation', val_label))
        
# train과 val에 없는 폴더가 있으면 생성하는 과정
for train_label in train_labels:
    if train_label not in val_label:
        print(train_label)
        os.makedirs(os.path.join('validation', train_label),exist_ok=True)
		# os.makedirs 함수는 하위 디렉토리도 생성
        # exist_ok=True 옵션은 이미 디렉토리가 존재해도 에러를 발생시키지 않고 계속 진행

val_label = os.listdir('validation')
  • 케글에 있는 포켓몬 데이터를 가지고 학습을 하여 분류 예측을 하는 과정을 진행해 보겠습니다
  • 사이트에 있는 데이터를 가지고 와서 압축을 풀어줍니다
  • 두 데이터셋의 구성이 다르므로 동일한 구성으로 만들어줍니다
# 필요한 모듈
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from torchvision import datasets, models,transforms
from torch.utils.data import DataLoader

# GPU 사용 확인
device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 이미지 증강기법 사용
# data_transforms       증강
# train / validation    텐서 및 사이즈 변경

data_transforms = {
    'train': transforms.Compose([
        # 크기 재조정
        transforms.Resize((224, 224)),
        # 각도, 찌그러뜨림, 크기,
        transforms.RandomAffine(0, shear = 10, scale = (0.8, 1.2)),
        transforms.RandomHorizontalFlip(),
        # tensor로 전환
        transforms.ToTensor()
    ]),
    'validation': transforms.Compose([
        transforms.Resize((224, 224)),
        transforms.ToTensor()
    ])
}
  • 이제 학습할 train, validation 데이터가 준비되었다면 필요한 모듈(?)을 import 해주고 동일한 크기, 스케일로 transforms 해줄 딕셔너리를 만들어 줍니다
# 데이터셋 객체 생성
# image_datasets
# train / validation

image_datasets = {
    'train': datasets.ImageFolder('train', data_transforms['train']),
    'validation': datasets.ImageFolder('validation', data_transforms['validation'])
}

# 데이터로더 생성
# dataloaders
# batch_size = 32
# suffle = True

dataloaders = {
    'train':DataLoader(
        image_datasets['train'],
        batch_size=32,
        shuffle=True
    ),
    'validation':DataLoader(
        image_datasets['validation'],
        batch_size=32,
        shuffle=True
    )
}
  • 이후 만들어진 데이터셋을 가지고 transforms 딕셔너리에 적용하여 정제된 train, validation 데이터셋 객체를 만들어 줍니다
  • 그리고 학습할 때 적용할 Dataloader에 넣고 dataloader 딕셔너리를 만들어줍니다
  • 이전에 했던 과정들과 동일하게 32개씩 학습을 시키기 위해 batch_size를 32로 주었습니다
# 사전 학습된 EfficientNetB4 모델
from torchvision.models import efficientnet_b4, EfficientNet_B4_Weights
from torchvision.models._api import WeightsEnum
from torch.hub import load_state_dict_from_url

def get_state_dict(self, *args, **kwargs):
    kwargs.pop("check_hash")
    return load_state_dict_from_url(self.url, *args, **kwargs)

WeightsEnum.get_state_dict = get_state_dict

efficientnet_b4(weights=EfficientNet_B4_Weights.IMAGENET1K_V1)
efficientnet_b4(weights="DEFAULT")

model = efficientnet_b4(weights=EfficientNet_B4_Weights.IMAGENET1K_V1)
model = efficientnet_b4(weights="DEFAULT").to(device)

# cl Layer 수정
# print(model)
model.classifier = nn.Sequential(
    nn.Linear(1792, 512),
    nn.ReLU(),
    nn.Linear(512, 149),
).to(device)
  • 이번에 사용해볼 모델은 EfficientNetB4 입니다
  • 구글에서 2019년에 개발한 이 모델은 이미지 인식 및 객체 감지, 세그멘테이션 등의 작업에서 좋은 성능을 보입니다
  • 그리고 모델을 불러와서 출력 Layer를 수정해서 모델을 완성해 줍니다
#  학습
# optimizer: Adam
# epochs : 10
optimizer = optim.Adam(model.classifier.parameters(), lr=0.001)

epochs = 10

for epoch in range(epochs  + 1):

    for phase in ['train', 'validation']:
        if phase == 'train':
            model.train()
        else:
            model.eval()
        sum_losses = 0
        sum_accs = 0

        for x_batch, y_batch in dataloaders[phase]:
            x_batch, y_batch = x_batch.to(device), y_batch.to(device)

            y_pred = model(x_batch)
            loss = nn.CrossEntropyLoss()(y_pred,  y_batch)

            if phase == 'train':
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

            sum_losses =  sum_losses + loss
            y_prob = nn.Softmax(1)(y_pred)
            y_pred_index = torch.argmax(y_prob, axis=1)

            acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
            sum_accs = sum_accs + acc

        avg_loss = sum_losses / len(dataloaders[phase])
        avg_acc = sum_accs / len(dataloaders[phase])
  • 이제 데이터 구성과 모델 수정이 끝났으면 학습을 진행합니다
  • 이번에는 train 데이터셋과 validation 데이터셋을 동시에 학습해보겠습니다
  • 먼저 데이터셋 종류에 따라 모델을 그에 맞게 설정해주고 반복문을 돌립니다
  • 이때 validaion 데이터는 학습된 후에 결과를 보는 데이터셋이기 때문에 train 데이터셋인 경우에만 optimizer 파라미터를 바꿔주는 코드를 추가해 줍니다

'수업 복습 > 머신러닝과 딥러닝' 카테고리의 다른 글

전이 학습  (0) 2024.03.26
간단한 CNN 모델 만들기 실습  (2) 2024.01.23
CNN 기초  (0) 2024.01.23
비선형 활성화 함수  (0) 2024.01.17
딥러닝  (0) 2024.01.16