본문 바로가기
DL/CNN

[DL][CNN] CNN(Convolution Neural Network) PyTorch 예제

by 어떻게든 되겠지~ 2024. 8. 15.

 

앞선 글에서 CNN의 기본 개념에 대해 살펴보았습니다

 

[DL][CNN] Convolution Neural Network(CNN)

Convolution Neural Network(CNN) Convolution Neural Network(CNN) 이란 인간의 시신경을 모바하여 만든 Deep Learning 구조이다특히, Convolution 연산을 이용하여 Image의 공간적인 정보를 유지하고, Fully Connected Neural N

self-objectification.tistory.com

이번 글에서는 Fashion_MNIST 데이터 셋을 CNN을 통해 분류하는 예제 코드에 대해 공부해보도록 하겠습니다


1. 라이브러리 Import

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F

import torchvision
import torchvision.transforms as transforms
import torchvision.datasets as datasets

from torch.utils.data import Dataset, DataLoader

device = torch.device("cuda : 0" if torch.cuda.is_available() else "cpu")

 

  • from torch.autograd import Variable :  PyTorch의 핵심0 기능인 자동미분을 사용하기 위한 Class
    • Tensor를 Variable class로 감싸면 Back - Propagation 과정에서 자동 미분을 사용할 수 있다
  • import torchvision.transforms as transforms : PyTorch에서 Image 데이터 전처리 및 데이터 증강을 위해 사용하는 Module
  • import torchvision.datasets as datasets : Torchvision에 내장되어 있는 데이터 셋 및 여러 Utility Class를 제

2. Fashion_MNIST 데이터 셋 download 및 DataLoader에 전달

# 6만개의 train data
train_dataset = datasets.FashionMNIST(root="../chapter5/data", download=True, train=True,
                                                  transform=transforms.Compose([transforms.ToTensor()]))

# 1만개의 test data
test_dataset = datasets.FashionMNIST(root="../chapter5/data", download=True, train=False,
                                                  transform=transforms.Compose([transforms.ToTensor()]))
                                                  
# DataLoader를 이용하여 원하는 크기의 batch 단위로 데이터를 불러오거나, 순서가 무작위로 섞이도록(shuffle) 할 수 있다
train_loader = DataLoader(train_dataset, batch_size=100)
test_loader = DataLoader(test_dataset, batch_size=100)

 

Torchvision에서 제공하는 Fashion_MNIST 데이터 셋을 다운로드 하고 Tensor로 변환합니다

 

다운받은 데이터 셋을 Mini-batch 단위(batch_size = 100)로 나누어 모델에 전달할 수 있게 DataLoader를 통해 감쌉니다

DataLoader는 데이터 로딩 시 순서를 섞거나(shuffle), 병렬로 데이터를 불러오는 등의 기능을 제공합니다 

※ Fashion_MNIST 데이터 셋

Fashion_MNIST 데이터 셋은 torchvision에 내장된 예제 데이터로 운동화, 셔츠, 샌들 같은 작은 이미지의 모음이며, 기본적으로 MNIST 데이터 셋처럼 열가지로 분류될 수 있는 28 X 28 픽셀의 이미지 7만개로 구성되어 있다
train_data는 0~255 사이의 값을 갖는 28 X 28 배열이고, train_labels는 0~9까지의 정수 값을 갖는 배열이다

각 레이블과 클래스는 다음과 같다
0 : 'T-shirt', 1 : 'Trouser', 2 : 'Pullover', 3 : 'Dress', 4 : 'Coat', 5 : 'Sandal', 6 : 'Shirt', 7 : 'Sneaker', 8 : 'Bag', 9 : 'Ankle Boot'

 

3. Fashion_MNIST 데이터 확인

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

fig = plt.figure(figsize=(8,8))
columns = 4
rows = 5

for i in range(1, columns*rows+1):
    # train data에서 Image random 선택
    rand_img = np.random.randint(len(train_dataset))
    # 랜덤으로 선택된 이미지 값(0~1)
    # train_data[smaple][0] : 이미지 값 / train_data[samele][1] : Label
    img = train_dataset[rand_img][0][0, :, :]

    fig.add_subplot(rows, columns, i)
    plt.title(labels_map[train_dataset[rand_img][1]])
    plt.axis('off')
    plt.imshow(img, cmap='gray')
plt.show()

 

 

4. 간단한 CNN 모델 정의

class FashionCNN(nn.Module):
    def __init__(self):
        super(FashionCNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1),  
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2) 
        )

        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )

        self.fc1 = nn.Linear(in_features=6*6*64, out_features=600)
        self.drop = nn.Dropout2d(p=0.25)
        self.fc2 = nn.Linear(in_features=600, out_features=120)
        self.fc3 = nn.Linear(in_features=120, out_features=10)

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.view(out.size(0), -1)
        out = self.fc1(out)
        out = self.drop(out)
        out = self.fc2(out)
        out = self.fc3(out)
        return out

 

  • nn.BatchNorm2(num_features, eps, momentum, affine, track_running_stats)
    • num_features : 입력 텐서의 채널 수
    • eps(epsilon) : 수치적으로 안정성을 보장하기 위해 분산 계산 시 더해지는 작은 값(분산이 0이 되는 것을 방지)
    • momentum : MA를 계산할 떄 사용되는 Momentum 값, 기본값 0.1
    • affine : True로 설정할 경우, 학습 가능한 스케일링('gamma')과 오프셋('beta') 파라미터를 사용하여 정규화 된 데이터에 선형 변환을 적용
    • track_running_stats : True(기본값)인 경우, Batch 정규화 계층이 Train 과정동안 이동 평균 및 이동 분산을 추적

5. CNN을 위한 Parameter 정의

learning_rate = 1e-3

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

 

Loss Function을 Cross Entropy Loss로 설정하고 Optimizer를 Adam으로 설정

6. 모델 학습 및 성능 평가

epoches = 5
count = 0
loss_list = []
iteration_list = []
accuracy_list = []

prediction_list = []
label_list = []

for epoch in range(epoches):
    # for문에서 DataLoader를 사용하면 batch_size만큼 데이터를 load
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)

        train = Variable(images.view(100, 1, 28, 28))
        labels = Variable(labels)

        outputs = model(train)
        loss = criterion(outputs, labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        count += 1
		
        # 성능 평가
        if not (count%50):
            total = 0 
            correct = 0
            for images, labels in test_loader:
                images, labels = images.to(device), labels.to(device)
                label_list.append(labels)
                test = Variable(images.view(100, 1, 28, 28))
                outputs = model(test)
                prediction = torch.max(outputs, 1)[1].to(device)
                prediction_list.append(prediction)
                correct += (prediction == labels).sum()
                total += len(labels)

            accuracy = correct * 100 / total
            loss_list.append(loss.data)
            iteration_list.append(count)
            accuracy_list.append(accuracy)

        if not (count%500):
            print("Iteration : {}, Loss : {}, Accuracy : {}%".format(count, loss.data, accuracy))

 

출력 결과 : 
Iteration : 500, Loss : 0.4794490933418274, Accuracy : 87.04000091552734%
Iteration : 1000, Loss : 0.33112308382987976, Accuracy : 88.01000213623047%
Iteration : 1500, Loss : 0.33547765016555786, Accuracy : 89.13999938964844%
Iteration : 2000, Loss : 0.21876569092273712, Accuracy : 88.95999908447266%
Iteration : 2500, Loss : 0.16111746430397034, Accuracy : 89.69000244140625%
Iteration : 3000, Loss : 0.23390652239322662, Accuracy : 89.0999984741211%

반응형

'DL > CNN' 카테고리의 다른 글

[DL][CNN] Convolution Neural Network(CNN)  (1) 2024.08.01