ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • PyTorch | DNN
    Deep Learning/PyTorch 2021. 6. 20. 03:50
    728x90

    DNN(Deep Neural Network)

    Fashion MNIST 데이터셋을 심층 신경망으로 분류해보자.

     

    Fashion MNIST

    필요한 모듈

    from torchvision import datasets, transforms, utils
    from torch.utils import data
    import matplotlib.pyplot as plt
    import numpy as np

     

    torch.utils.data : 데이터셋을 불러오고 자르고 섞는데 쓰는 도구들이 들어있는 모듈

    torchvision.datasets : 데이터셋의 모음

    torchvision.transforms : 이미지 데이터셋에 쓸 수 있는 여러 가지 변환 필터를 담고 있는 모듈

    torchvision.utils : 이미지 데이터를 저장하고 시각화하기 위한 도구가 들어있는 모듈

     

    이미지를 텐서로 바꿔주는 코드

    transform = transforms.Compose([
        transforms.ToTensor()
    ])

    transforms.Resize(), Normalize() 등 편리한 함수가 많다.

    Compose() 안에 리스트 형태로 넣어주면 순서대로 변환이 이루어짐

     

    Data 불러오기

    trainset = datasets.FashionMNIST(
        root='./.data',
        train=True,
        download=True,
        transform=transform
    )
    testset = datasets.FashionMNIST(
        root='./.data',
        train=False,
        download=True,
        transform=transform
    )

    dowunload = True 넣고 root 경로에 데이터 셋이 존재하는지 확인 후 없다면 자동으로 저장

    train : train 과 test 셋을 구분,

     

    torchvision.datasets로 생성된 객체는 torch.utils.data.Dataset을 상속함

    DataLoader 클래스에 넣어 바로 사용 가능

    DataLoader : 데이터셋을 배치단위로 쪼개고 학습 시 반복문 안에 데이터를 공급해주는 클래스

     

    DataLoader

    batch_size = 16
    
    train_loader = data.DataLoader(
        dataset=trainset,
        batch_size=batch_size
    )
    test_loader = data.DataLoader(
        dataset=testset,
        batch_size=batch_size
    )

    이제 편리하게 데이터를 뽑아 쓸 수 있음

    batch_size = 16 이므로 한번 뽑을 때 16개를 뽑음

     

    image

    dataiter = iter(train_loader)
    images, labels = next(dataiter)
    
    img = utils.make_grid(images, padding=0)  # 여러 이미지를 모아 하나의 이미지로 만듬
    npimg = img.numpy()  # matplotlib 호환을 위해 np로 변환
    plt.figure(figsize=(10, 7))
    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # 맷 플롯립이 인식하는 차원의 순서가 달라 0번째를 맨뒤로
    plt.show()

     

    CLASSES

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

    각 레이블에 대한 값을 딕셔너리로 정의함

     

    개별 이미지 보기

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

     

    인공 신경망

    필요한 모듈

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

    torch.nn : 인공 신경망 모델의 재료들을 담고 있는 모듈

    torch.optim : 최적화를 위한 모듈

    torch.nn.functional : nn의 함수 버전

     

    CUDA 사용 가능 여부

    >>> torch.cuda.is_available()
    False
    USE_CUDA = torch.cuda.is_available()
    DEVICE = torch.device("cuda" if USE_CUDA else "cpu")

     

    신경망 구현

    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)	# 1차원 행렬로 변환
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    더보기

    fc : 'fully connected'의 약자, keras에서는 Dense 층이라고 함

    nn.Module을 상속하는 Net을 정의함

    Linear() : 선형 결합을 수행하는 객체를 만듬

     

    GPU or CPU

    model = Net().to(DEVICE)

    SGD

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

    확률적 경사 하강법을 사용

    model.parameters() 함수를 이용하여 모델 내부의 정보를 전달 학습률은 0.01

     

     

    train

    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()  # 한걸음

    model.train() : 학습 모드 설정

    학습 / 평가 모드에 따라 동작이 다른 파이토치 모듈(드롭 아웃 등)이 있으므로 습관을 들이자!

     

    evaluate

    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]  # output의 가장 큰 값의 인덱스 (argmax)
                correct += pred.eq(target.view_as(pred)).sum().item()  # target, pred 일치하는 값의 개수
    
            test_loss /= len(test_loader.dataset)  # 오차의 평균값
            test_accuracy = 100 * correct / len(test_loader.dataset)
            return test_loss, test_accuracy

    target.view_as(pred) : target을 pred의 차원과 같게 변환함


    전체 코드

    import torch
    import torch.nn as nn
    import torch.optim as optim
    import torch.nn.functional as F
    from torchvision import datasets, transforms, utils
    from torch.utils import data
    
    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
    )
    
    # 데이터 로더 준비
    batch_size = 16
    
    train_loader = data.DataLoader(
        dataset=trainset,
        batch_size=batch_size
    )
    test_loader = data.DataLoader(
        dataset=testset,
        batch_size=batch_size
    )
    
    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)  # 1차원 행렬로 변환
            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)
    
    
    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]  # output의 가장 큰 값의 인덱스 (argmax)
                correct += pred.eq(target.view_as(pred)).sum().item()  # target, pred 일치하는 값의 개수
    
            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(f'[{epoch}] Test Loss: {test_loss:.4f}, Accuracy:{test_accuracy:.2f}')
    
    728x90

    'Deep Learning > PyTorch' 카테고리의 다른 글

    PyTorch | GAN  (4) 2022.01.09
    Pytorch | ANN  (0) 2021.06.12
    PyTorch | 이미지 복원  (0) 2021.06.04
    Pythrch | 기초  (0) 2021.06.01
    PyTorch 설치  (0) 2021.06.01

    댓글

Designed by Tistory.