본문 바로가기

인공지능/DeepLearning

[Computer Vision] 확장된 Image를 이용한 훈련 모델 사용

%matplotlib inline
from d2l import torch as d2l
import torch
import torchvision
from torch import nn

사용될 모듈 항목들이다.


학습에 사용될 모델들은 torchvision에서 제공하는 image 데이터셋인 CIFAR-10을 사용한다.

all_images = torchvision.datasets.CIFAR10(train=True, root="../data", download=True)
d2l.show_images([all_images[i][0] for i in range(32)], 4, 8, scale=0.8);

train        : train 데이터셋을 받아올지 test용 데이터셋을 받아올지 선택

root         : 데이터셋을 받아올 경로를 지정

download : 데이터셋이 해당 경로에 없다면 다운로드를 할지의 유무

transform : transform은 예시에 없지만 해당 인자에는 이미지 처리를 위한 argument가 들어간다.

 

images는 이미지와 타깃 값을 받아오게 된다.

all_images [i][0] : 이미지, all_images [i][1] : 이미지에 해당하는 타깃 값

따라서 show_images를 통해 이미지를 볼때에는 all_images [i][0]만 확인한다.


train_augs = torchvision.transforms.Compose([
     torchvision.transforms.RandomHorizontalFlip(),
     torchvision.transforms.ToTensor()])

test_augs = torchvision.transforms.Compose([
     torchvision.transforms.ToTensor()])

사용할 데이터셋의 이미지 처리 부분을 정의하여준다.

이미지를 학습할 경우 모든 이미지는 ToTensor()를 통해 Tensor형으로 변환을 시켜준다.

pytorch의 기본 베이스는 Tensor형을 지원하며, GPU 가속 연산에도 사용할 수 있기 때문이다.

 

다양한 이미지 데이터를 학습시켜주기 위해,

train 데이터셋에 RandomHorizontalFlip()을 사용해 랜덤으로 좌우 반전을 시켜준다.

test 데이터셋은 평가를 위한 데이터셋이기 때문에 적용하지 않는다.


def load_cifar10(is_train, augs, batch_size):
    dataset = torchvision.datasets.CIFAR10(root="../data", train=is_train,
                                           transform=augs, download=True)
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                    shuffle=is_train, num_workers=d2l.get_dataloader_workers())
    return dataloader

앞에서 처럼 CIFAR-10을 다운 받고 학습에 사용하도록 배치 단위로 나누는 모듈을 함수화시킨 것이다.

 

DataLoader를 이용해 데이터셋을 배치단위로 나누어준다.

shuffle          : shuffle를 해서 나눌 건지의 유무

num_workers : 학습 도중 cpu를 몇개 사용할지 선택한다.

학습을 GPU를 통해 하더라도 GPU는 기본적으로 CPU의 컨트롤을 받게 된다.

따라서 CPU의 성능도 GPU의 성능에 영향을 끼치게 된다. 그래서 적절한 num_workers의 선택이 필요하다.


batch_size, devices, net = 256, d2l.try_all_gpus(), d2l.resnet18(10, 3)

def init_weights(m):
    if type(m) in [nn.Linear, nn.Conv2d]:
        nn.init.xavier_uniform_(m.weight)

net.apply(init_weights)

사용 모델은 resnet18를 이용한다.

init_weights()함수를 이용해 resnet18 모델 내부 layer의 타입이 Linear 타입이거나, Conv2d 타입일 경우

가중치들을 xavier_uniform 형태로 값으로 초기화해준다.


def train_batch(net, X, y, loss, optimzer, devices):
    X = X.to(devices[0])
    y = y.to(devices[0])
    
    net.train()               #train 모드로 변환
    optimzer.zero_grad()      #optimzer 기울기 0으로 초기화
    
    pred = net(X)             #실행하여 예측값 출력
    l = loss(pred, y)         #loss 값 게산
    l.sum().backward()        #loss의 합을 미분하여 기울기 계산
    
    optimzer.step()           #기울기에 맞춰서 optimzer 업데이트
    
    train_loss_sum = l.sum()
    train_acc_sum = d2l.accuracy(pred, y)
    return train_loss_sum, train_acc_sum

차후 모델을 학습할 때 배치 단위에서 학습 하는 부분을 함수화 한것이다.

모델은 학습을 할 때 net.train()을 통해 net을 train모드로 바꿔준다. 

train에서만 사용되는 Batch Normalization, DropOut 같은 학습 할 때만 사용되는 기능을 사용해주기 위함이다.


def train(net, train_iter, test_iter, loss, optimzer, num_epochs, devices):
    net.to(devices[0])
    for epoch in range(num_epochs):
        for i, (images, labels) in enumerate(train_iter):
            l, acc = train_batch(net, images, labels, loss, optimzer, devices)
        test_acc = d2l.evaluate_accuracy_gpu(net, test_iter)
        print("epoch_{0} = {1}".format(epoch, test_acc))

전체 학습을 train 하는 함수이다.

학습할 데이터셋을 devices상에 올려놓았으므로

동일한 devices에서 연산할 수 있도록 net 또한 동일 devices로 옮겨준다. (동일한 devices 여야만 연산이 가능하다.)

 

각 epoch를 돌리고, 배치 단위로 학습을 하고 1 epoch가 끝이 나면 test 데이터셋으로 test를 한다.


def train_with_data_aug(train_augs, test_augs, net, lr=0.001):
    train_iter = load_cifar10(True, train_augs, batch_size)
    test_iter = load_cifar10(False, test_augs, batch_size)
    
    loss = nn.CrossEntropyLoss(reduction="none")
    optimizer = torch.optim.Adam(net.parameters(), lr=lr)
    
    train(net, train_iter, test_iter, loss, optimizer, 10, devices)

최종적으로 train_with_data_aug를 통해 데이터를 불러오고 학습까지 하는 함수를 보낸다.


train_with_data_aug(train_augs, test_augs, net)

최종적으로 실행이 되게 된다.


ref. Dive into Deep Learning, Aston Zhang and Zachary C. Lipton and Mu Li and Alexander J. Smola, 2020