728x90

전이학습 (transfer learning)

ImageNet 처럼 큰 데이터셋을 써서 훈련 된 모델의 가중치를 가져와 우리가 해결하려는 과제에 맞게 보정해서 사용하는 것을 의미
사전 훈련된 모델(네트워크)라고 부름 pretrained model

특성추출(feature extractor)은 pretrained model을 불러와서 fully connected layer만 새로 만듦

이미지 분류 모델
Xception, Inception V3, ResNet50, VGG16, VGG19, MobileNet

2023-08-18

미세 조정 기법

특성이 잘못 추출 되었다면 새로운 이미지 데이터를 사용하여 네트워크의 가중치를 업데이트 하여 특성을 다시 추출할 수 있음

  1. 데이터 셋이 크고 사전 훈련된 모델과 유사성이 작을 경우
    • 모델 전체를 재학습시킴
    • 데이터 셋 크기가 크기 때문에 재학습 시키는 것이 좋은 전략
  2. 데이터 셋이 크고 사전 훈련된 모델과 유사성이 클 경우
    • 합성곱층의 뒷부분과 데이터 분류기를 학습시킴
    • 데이터 셋이 유사하기 때문에 전체를 학습시키는 것 보다는 강한 특징이 나타나는 합성곱층의 뒷부분과 데이터 분류기만 새로 학습하더라도 최적의 성능을 낼 수 있음
  3. 데이터 셋이 작고 사전 훈련된 모델과 유사성이 작을 경우
    • 합성곱층의 일부분과 데이터 분류기를 학습시킴
    • 데이터가 적기 때문에 일부 계층에 미세 조정 기법을 적용한다고 해도 효과가 없을 수 있음
    • 합성곱층 중 어디까지 새로 학습시켜야 할지 적당히 설정해야 함
  4. 데이터 셋이 작고 사전 훈련된 모델과 유사성이 클 경우
    • 데이터 분류기만 학습시킴
    • 데이터가 적기 때문에 많은 계층에 미세 조정 기법을 조정하면 과적합이 발생할 수 있음
    • 최종 데이터 분류기인 완전연결층에 대해서만 미세 조정 기법을 적용

설명 가능한 CNN

내부는 블랙박스처럼 되어있어 설명하기 어려움
특성 맵 시각화

로그 소프트맥스(log_softmax())는 신경망 말단의 결괏값들을 확률 개념으로 해석하기 위
해 소프트맥스(softmax) 함수의 결과에 log 값을 취한 연산

  • unsqueeze 차원 증강

GCN

https://process-mining.tistory.com/176

개와 고양이 분류

import os  
import time  
import copy  
import glob  
import cv2  
import shutil  
  
import torch  
import torchvision  
import torchvision.transforms as transforms  
import torchvision.models as models  
import torch.nn as nn  
import torch.optim as optim  
from torch.utils.data import DataLoader  
  
import matplotlib.pyplot as plt  
  
  
data_path = './data/catanddog/train'  
  
transform = transforms.Compose([  
    transforms.Resize([256,256]),  
    transforms.RandomResizedCrop(224),  
    transforms.RandomHorizontalFlip(),  
    transforms.ToTensor()  
    ])  
  
train_dataset = torchvision.datasets.ImageFolder(  
    data_path,  
    transform=transform  
    )  
  
train_loader = torch.utils.data.DataLoader(  
    train_dataset,  
    batch_size=32,  
    num_workers=4,  
    shuffle=True  
    )  
  
print(len(train_dataset))

img show

import matplotlib.pyplot as plt  
import mxnet as mx  
from mxnet.gluon.data.vision import transforms  
  
example_image = mx.image.imread("./data/cat.jpg")  
plt.imshow(example_image.asnumpy())  
  
def show_images(imgs, num_rows, num_cols, scale=2):   
    aspect_ratio = imgs[0].shape[0]/imgs[0].shape[1]  
    figsize = (num_cols * scale, num_rows * scale * aspect_ratio)  
    _, axes = plt.subplots(num_rows, num_cols, figsize=figsize)  
    for i in range(num_rows):  
        for j in range(num_cols):  
            axes[i][j].imshow(imgs[i * num_cols + j].asnumpy())  
            axes[i][j].axes.get_xaxis().set_visible(False)  
            axes[i][j].axes.get_yaxis().set_visible(False)  
    plt.subplots_adjust(hspace=0.1, wspace=0)  
    return axes  
  
def apply(img, aug, num_rows=2, num_cols=4, scale=3):  
    Y = [aug(img) for _ in range(num_rows * num_cols)]  
    show_images(Y, num_rows, num_cols, scale)  
      
      
shape_aug = transforms.RandomResizedCrop(size=(200, 200), scale=(0.1, 1), ratio=(0.5, 2))  
apply(example_image, shape_aug)

resnet

samples, labels = next(iter(train_loader))  
classes = {0:'cat', 1:'dog'}  
fig = plt.figure(figsize=(16,24))  
for i in range(24):  
    a = fig.add_subplot(4,6,i+1)  
    a.set_title(classes[labels[i].item()])  
    a.axis('off')  
    a.imshow(np.transpose(samples[i].numpy(), (1,2,0)))  
plt.subplots_adjust(bottom=0.2, top=0.6, hspace=0)  
  
  
resnet18 = models.resnet18(pretrained=True)

데이터 학습

def set_parameter_requires_grad(model, feature_extracting=True):  
    if feature_extracting:  
        for param in model.parameters():  
            param.requires_grad = False  
            set_parameter_requires_grad(resnet18)  
  
resnet18.fc = nn.Linear(512, 2)  
  
for name, param in resnet18.named_parameters():  
    if param.requires_grad:  
        print(name, param.data)  
          
  
model = models.resnet18(pretrained = True)  
  
for param in model.parameters():  
    param.requires_grad = False  
  
model.fc = torch.nn.Linear(512, 2)  
for param in model.fc.parameters():  
    param.requires_grad = True  
  
optimizer = torch.optim.Adam(model.fc.parameters())  
cost = torch.nn.CrossEntropyLoss()  
print(model)  
  
  
def train_model(model, dataloaders, criterion, optimizer, device, num_epochs=13, is_train=True):  
    since = time.time()      
    acc_history = []  
    loss_history = []  
    best_acc = 0.0  
    for epoch in range(num_epochs):  
        print('Epoch {}/{}'.format(epoch, num_epochs - 1))  
        print('-' * 10)  
  
        running_loss = 0.0  
        running_corrects = 0  
  
        for inputs, labels in dataloaders:  
            inputs = inputs.to(device)  
            labels = labels.to(device)  
              
            model.to(device)  
            optimizer.zero_grad()  
            outputs = model(inputs)  
            loss = criterion(outputs, labels)  
            _, preds = torch.max(outputs, 1)  
            loss.backward()  
            optimizer.step()  
  
            running_loss += loss.item() * inputs.size(0)  
            running_corrects += torch.sum(preds == labels.data)  
  
        epoch_loss = running_loss / len(dataloaders.dataset)  
        epoch_acc = running_corrects.double() / len(dataloaders.dataset)  
  
        print('Loss: {:.4f} Acc: {:.4f}'.format(epoch_loss, epoch_acc))  
  
        if epoch_acc > best_acc:  
            best_acc = epoch_acc  
  
        acc_history.append(epoch_acc.item())  
        loss_history.append(epoch_loss)          
        torch.save(model.state_dict(), os.path.join('catanddog/', '{0:0=2d}.pth'.format(epoch)))  
        print()  
  
    time_elapsed = time.time() - since  
    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))  
    print('Best Acc: {:4f}'.format(best_acc))      
    return acc_history, loss_history  
  
# 파라미터 학습 결과를 옵티마이저에 전달  
params_to_update = []  
for name,param in resnet18.named_parameters():  
    if param.requires_grad == True:  
        params_to_update.append(param)  
        print("\t",name)  
              
optimizer = optim.Adam(params_to_update)  
  
# 모델 학습  
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  
criterion = nn.CrossEntropyLoss()  
train_acc_his, train_loss_hist = train_model(resnet18, train_loader, criterion, optimizer, device)  
  
from IPython.testing import test  
test_path = './catanddog/test/'  
  
transform = transforms.Compose(  
                [  
                    transforms.Resize(224),  
                    transforms.CenterCrop(224),  
                    transforms.ToTensor(),  
                ])  
test_dataset = torchvision.datasets.ImageFolder(  
    root=test_path,  
    transform=transform  
)  
test_loader = torch.utils.data.DataLoader(  
    train_dataset,  
    batch_size=32,  
    num_workers=1,  
    shuffle=True  
)  
  
print(len(test_dataset))  
  
def eval_model(model, dataloaders, device):  
    since = time.time()      
    acc_history = []  
    best_acc = 0.0  
  
    saved_models = glob.glob('catanddog/' + '*.pth')  
    saved_models.sort()  
    print('saved_model', saved_models)  
  
    for model_path in saved_models:  
        print('Loading model', model_path)  
  
        model.load_state_dict(torch.load(model_path))  
        model.eval()  
        model.to(device)  
        running_corrects = 0  
  
        for inputs, labels in dataloaders:  
            inputs = inputs.to(device)  
            labels = labels.to(device)  
  
            with torch.no_grad():  
                outputs = model(inputs)  
  
            _, preds = torch.max(outputs.data, 1)             
            preds[preds >= 0.5] = 1  
            preds[preds < 0.5] = 0  
            running_corrects += preds.eq(labels).int().sum()  
              
        epoch_acc = running_corrects.double() / len(dataloaders.dataset)  
        print('Acc: {:.4f}'.format(epoch_acc))  
          
        if epoch_acc > best_acc:  
            best_acc = epoch_acc  
  
        acc_history.append(epoch_acc.item())  
        print()  
  
    time_elapsed = time.time() - since  
    print('Validation complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))  
    print('Best Acc: {:4f}'.format(best_acc))  
      
    return acc_history  
  
# 테스트 데이터를 평가 함수에 적용  
val_acc_hist = eval_model(resnet18, test_loader, device)  
  
  
  
preds = torch.randn(10,5).softmax(dim=-1)  
target = torch.randint(5, (10,))  
  
print(preds)  
print(target)

shape_aug = transforms.RandomResizedCrop(size=(200, 200), scale=(0.1, 1), ratio=(0.5, 2))
apply(example_image, shape_aug)

500

import numpy as np  
  
samples, labels = next(iter(train_loader))  
classes = {0:'cat', 1:'dog'}  
fig = plt.figure(figsize=(16,24))  
for i in range(24):  
    a = fig.add_subplot(4,6,i+1)  
    a.set_title(classes[labels[i].item()])  
    a.axis('off')  
    a.imshow(np.transpose(samples[i].numpy(), (1,2,0)))  
plt.subplots_adjust(bottom=0.2, top=0.6, hspace=0)  

반응형