심층신경망(Deep Neural Network)

hottogi·2022년 11월 12일
0

심층신경망

데이터셋 준비

from torchvision import datasets, transforms, utils
from torch.utils import data

import matplotlib.pyplot as plt
import numpy as np

torchvision.datasets: 이미지 데이터셋 불러오기
torchvision.transforms: 여러가지 변환 필터를 담은 모듈
torchvision.utils: 이미지 데이터 저장 및 시각화 모듈

FashionMNIST 데이터셋을 trian과 test로 다운받기

transform = transforms.Compose([transforms.ToTensor()]) 
trainset = datasets.FashionMNIST(
    root      = './.data/', 
    train     = True,
    download  = True,
    transform = transform
)
testset = datasets.FashionMNIST(
    root      = './.data/', 
    train     = False,
    download  = True,
    transform = transform
)

torchvision.datasets로 생성된 객체는 파이토치 내부 클래스 torch.utils.data.Dataset을 상속하기 때문에 클래스에 넣어 바로 사용할수 있습니다.

batch_size = 16

train_loader = data.DataLoader(
    dataset     = trainset,
    batch_size  = batch_size
)
test_loader = data.DataLoader(
    dataset     = testset,
    batch_size  = batch_size
)
dataiter       = iter(train_loader) 
images, labels = next(dataiter)  

이미지 모아보기

img   = utils.make_grid(images, padding=0) 
npimg = img.numpy()
plt.figure(figsize=(10, 7))
plt.imshow(np.transpose(npimg, (1,2,0))) 
plt.show()

print(labels) 

tensor([9, 0, 0, 3, 0, 2, 7, 2, 5, 5, 0, 9, 5, 5, 7, 9])

16장 사진의 각 클래스를 뜻하는 숫자가 나열되었습니다.

CLASSES = {
    0: 'T-shirt/top',
    1: 'Trouser',
    2: 'Pullover',
    3: 'Dress',
    4: 'Coat',
    5: 'Sandal',
    6: 'Shirt',
    7: 'Sneaker',
    8: 'Bag',
    9: 'Ankle boot'
}


for label in labels:
    index = label.item()
    print(CLASSES[index])

Ankle boot
T-shirt/top
T-shirt/top
Dress
T-shirt/top
Pullover
Sneaker
Pullover
Sandal
Sandal
T-shirt/top
Ankle boot
Sandal
Sandal
Sneaker
Ankle boot

idx = 1

item_img = images[idx]
item_npimg = item_img.squeeze().numpy() 
plt.title(CLASSES[labels[idx].item()]) 
print(item_npimg.shape)
plt.imshow(item_npimg, cmap='gray')
plt.show()

인공신경망으로 패션 아이템 분류

torch.nn: 인공신경망 모델의 재료를 담고있는 모듈
torch.optim: 최적화를 위한 모듈
torchvision: 토치비전의 데이터셋을 다루는 모듈

import torch
import torch.nn as nn 
import torch.optim as optim 
import torch.nn.functional as F
from torchvision import transforms, datasets 

CPU와 GPU중 사용 가능한것을 사용하기 위한 코드

USE_CUDA = torch.cuda.is_available() 
DEVICE = torch.device("cuda" if USE_CUDA else "cpu") 
EPOCHS = 30 
BATCH_SIZE = 64 
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__() 
        self.fc1 = nn.Linear(784, 256) 
        self.fc2 = nn.Linear(256, 128)
        self.fc3 = nn.Linear(128, 10) 

    def forward(self, x):
        x = x.view(-1, 784) 
        x = F.relu(self.fc1(x)) 
        x = F.relu(self.fc2(x)) 
        x = self.fc3(x)
        return x

model        = Net().to(DEVICE)
optimizer    = optim.SGD(model.parameters(), lr=0.01)

학습 시작.
모델을 학습 모드로 바꾸고 반복때마다 새로 기울기를 계산합니다.
optimizer함수를 통해 기울기의 가중치를 수정합니다.

def train(model, train_loader, optimizer):
    model.train() 
    for batch_idx, (data, target) in enumerate(train_loader):
        
        data, target = data.to(DEVICE), target.to(DEVICE)
        optimizer.zero_grad() 
        output = model(data)
        loss = F.cross_entropy(output, target)
        loss.backward() 
        optimizer.step() 

일반화: 세상의 모든 데이터에 최적화 하는것
일반화 오류: 학습 데이터를 기반으로한 모델이 테스트 데이터에 얼마나 적중하는지 나타낸 수치
일반화 오류는 작을수록 좋습니다.

def evaluate(model, test_loader):
    model.eval() 
    test_loss = 0
    correct = 0 
    with torch.no_grad(): 
        for data, target in test_loader:
            data, target = data.to(DEVICE), target.to(DEVICE)
            output = model(data)

            test_loss += F.cross_entropy(output, target,
                                         reduction='sum').item() 
            
            pred = output.max(1, keepdim=True)[1]
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset) 
    test_accuracy = 100. * correct / len(test_loader.dataset) 
    return test_loss, test_accuracy

for epoch in range(1, EPOCHS + 1):
    train(model, train_loader, optimizer)
    test_loss, test_accuracy = evaluate(model, test_loader)
    
    print('[{}] Test Loss: {:.4f}, Accuracy: {:.2f}%'.format(
          epoch, test_loss, test_accuracy))

[1] Test Loss: 0.5664, Accuracy: 80.22%
[2] Test Loss: 0.4911, Accuracy: 82.49%
[3] Test Loss: 0.4547, Accuracy: 83.86%
[4] Test Loss: 0.4258, Accuracy: 84.75%
[5] Test Loss: 0.4081, Accuracy: 85.45%
[6] Test Loss: 0.3926, Accuracy: 85.83%
[7] Test Loss: 0.3822, Accuracy: 86.31%
[8] Test Loss: 0.3725, Accuracy: 86.83%
[9] Test Loss: 0.3649, Accuracy: 87.10%
[10] Test Loss: 0.3590, Accuracy: 87.24%
[11] Test Loss: 0.3531, Accuracy: 87.42%
[12] Test Loss: 0.3484, Accuracy: 87.68%
[13] Test Loss: 0.3451, Accuracy: 87.82%
[14] Test Loss: 0.3411, Accuracy: 88.01%
[15] Test Loss: 0.3391, Accuracy: 88.17%
[16] Test Loss: 0.3375, Accuracy: 88.20%
[17] Test Loss: 0.3361, Accuracy: 88.40%
[18] Test Loss: 0.3339, Accuracy: 88.39%
[19] Test Loss: 0.3324, Accuracy: 88.33%
[20] Test Loss: 0.3350, Accuracy: 88.33%
[21] Test Loss: 0.3307, Accuracy: 88.39%
[22] Test Loss: 0.3299, Accuracy: 88.42%
[23] Test Loss: 0.3305, Accuracy: 88.56%
[24] Test Loss: 0.3301, Accuracy: 88.45%
[25] Test Loss: 0.3317, Accuracy: 88.42%
[26] Test Loss: 0.3318, Accuracy: 88.44%
[27] Test Loss: 0.3314, Accuracy: 88.47%
[28] Test Loss: 0.3313, Accuracy: 88.51%
[29] Test Loss: 0.3302, Accuracy: 88.70%
[30] Test Loss: 0.3284, Accuracy: 88.75%

Overfitting and Regularization(오버피팅, 정규화)

과적합을 방지하기 위해서는 데이터를 최대한 늘리는 것이 최선입니다.
같은 이미지를 기울여서 보고 돌려서 보고 노이즈를 추가해서 보면 새로운 이미지가 없어도 데이터를 늘릴 수 있습니다.

train_loader = torch.utils.data.DataLoader(
    datasets.FashionMNIST('./.data',
                   train=True,
                   download=True,
                   transform=transforms.Compose([ 
                       transforms.RandomHorizontalFlip(), 
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=BATCH_SIZE, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.FashionMNIST('./.data',
                   train=False, 
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=BATCH_SIZE, shuffle=True)

드롭아웃을 통해 과적합을 해결합니다.
신경망의 일부를 사용하지 않음으로써 자가당착에 빠지는 것을 방지해줍니다.

class Net(nn.Module):
    def __init__(self, dropout_p=0.2): 
        super(Net, self).__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 128)
        self.fc3 = nn.Linear(128, 10)
        self.dropout_p = dropout_p

    def forward(self, x):
        x = x.view(-1, 784)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training, 
                      p=self.dropout_p)
        x = F.relu(self.fc2(x))
        x = F.dropout(x, training=self.training, 
                                            p=self.dropout_p)
        x = self.fc3(x)
        return x
  
model        = Net(dropout_p=0.2).to(DEVICE) 
optimizer    = optim.SGD(model.parameters(), lr=0.01)
for epoch in range(1, EPOCHS + 1): 
    train(model, train_loader, optimizer)
    test_loss, test_accuracy = evaluate(model, test_loader)
    
    print('[{}] Test Loss: {:.4f}, Accuracy: {:.2f}%'.format(
          epoch, test_loss, test_accuracy))

[1] Test Loss: 0.6353, Accuracy: 77.77%
[2] Test Loss: 0.5318, Accuracy: 81.00%
[3] Test Loss: 0.4882, Accuracy: 82.63%
[4] Test Loss: 0.4604, Accuracy: 83.32%
[5] Test Loss: 0.4483, Accuracy: 83.41%
[6] Test Loss: 0.4363, Accuracy: 83.94%
[7] Test Loss: 0.4177, Accuracy: 84.70%
[8] Test Loss: 0.4048, Accuracy: 85.29%
[9] Test Loss: 0.3958, Accuracy: 85.50%
[10] Test Loss: 0.3880, Accuracy: 85.87%
[11] Test Loss: 0.3836, Accuracy: 86.20%
[12] Test Loss: 0.3771, Accuracy: 86.26%
[13] Test Loss: 0.3707, Accuracy: 86.60%
[14] Test Loss: 0.3699, Accuracy: 86.58%
[15] Test Loss: 0.3643, Accuracy: 86.85%
[16] Test Loss: 0.3618, Accuracy: 86.88%
[17] Test Loss: 0.3587, Accuracy: 86.89%
[18] Test Loss: 0.3526, Accuracy: 87.19%
[19] Test Loss: 0.3497, Accuracy: 87.14%
[20] Test Loss: 0.3504, Accuracy: 87.21%
[21] Test Loss: 0.3489, Accuracy: 87.38%
[22] Test Loss: 0.3415, Accuracy: 87.58%
[23] Test Loss: 0.3382, Accuracy: 87.57%
[24] Test Loss: 0.3390, Accuracy: 87.53%
[25] Test Loss: 0.3585, Accuracy: 86.92%
[26] Test Loss: 0.3358, Accuracy: 87.66%
[27] Test Loss: 0.3380, Accuracy: 87.60%
[28] Test Loss: 0.3292, Accuracy: 88.09%
[29] Test Loss: 0.3295, Accuracy: 88.11%
[30] Test Loss: 0.3299, Accuracy: 88.16%

profile

0개의 댓글