%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
'인공지능 > DeepLearning' 카테고리의 다른 글
[Computer Vision] Object Detection and Bounding Boxes (0) | 2021.01.14 |
---|---|
[Computer Vision] Fine-Tuning (0) | 2021.01.12 |
[Computer Vision] Image Augmentation (0) | 2021.01.11 |
모델 성능 평가지표 (0) | 2020.12.29 |
모델 성능 평가 지표 - 분류(Classification) - 미완성 (0) | 2020.12.28 |