앞선 글에서 CNN의 기본 개념에 대해 살펴보았습니다
이번 글에서는 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 |
---|