이번에는 MNIST 데이터에 대해서 이해하고, PYTORCH로 소프트맥스 회귀를 구현하여 분류하는 실습을 진행해보자.
for X,Y in data_loader:
# 입력 이미지를 [batch_size * 784]의 크기로 reshape
# 레이블은 원-핫 인코딩
X = X.view(-1,28*28)
# view를 통해서 (배치크기 * 784)로 크기 변환
# 원래는 (배치크기 * 1 * 28 * 28)
torchvision
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import torch.nn as nn
import matplotlib.pyplot as plt
import random
USE_CUDA = torch.cuda.is_available() # gpu 사용 가능하면 true or false
device = torch.device("cuda" if USE_CUDA else "cpu")
print("다음 기기로 학습합니다.",device)
# 랜덤 시드 고정
random.seed(777)
torch.manual_seed(777)
if device == 'cuda':
torch.cuda.manual_seed_all(777)
training_epochs = 15
batch_size = 100
torchvision
을 통해서 MNIST 데이터셋 불러오기
#MNIST dataset
mnist_train = dsets.MNIST(root = 'MNIST_data/',
train = True,
transform = transforms.ToTensor(),
download=True)
mnist_test = dsets.MNIST(root = 'MNIST_data/',
train = False,
transform = transforms.ToTensor(),
download = True)
dataset
: 로드할 대상batch_size
: 배치 크기shuffle
: 매 에포크마다 미니 배치를 셔플할 것인지의 여부 (bool) drop_last
: 마지막 배치를 버릴 것인지 의미 drop_last = True
임 .# dataset loader
data_loader = DataLoader(dataset = mnist_train,
batch_size = batch_size,
shuffle = True,
drop_last = True)
to()
함수를 사용하여 모델의 매개변수를 지정한 장치의 메모리로 보냄.to(device)
를 꼭 해줘야함. # MNIST data image of shape 28 * 28 = 784
linear = nn.Linear(784, 10, bias = True).to(device)
criterion = nn.CrossEntropyLoss().to(device) # 내부적으로 소프트맥스 함수 포함
optimizer = torch.optim.SGD(linear.parameters(), lr = 0.1)
for epoch in range(training_epochs): # 15
avg_cost = 0
total_batch = len(data_loader)
for X, Y in data_loader:
# 배치 크기가 100이므로 아래의 연산에서 X는 (100,784)의 텐서가 된다.
X = X.view(-1,28*28).to(device)
# 레이블은 원-핫 인코딩이 된 상태가 아니라 0~9의 정수
Y = Y.to(device)
# 가설, 비용 선언
hypothesis = linear(X)
cost = criterion(hypothesis,Y)
# 갱신 과정
optimizer.zero_grad()
cost.backward()
optimizer.step()
avg_cost += cost/total_batch
print('Epoch: ', '%04d' %(epoch + 1), 'cost = ','{:9f}'.format(avg_cost))
print("Learning finished")
with torch.no_grad(): # gradient 계산을 수행하지 않음
X_test = mnist_test.test_data.view(-1,28*28).float().to(device)
Y_test = mnist_test.test_labels.to(device)
prediction = linear(X_test)
correct_prediction = torch.argmax(prediction,1) == Y_test
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())
# MNIST 테스트 데이터에서 무작위로 하나를 뽑아서 예측
r = random.randint(0,len(mnist_test)-1)
X_single_data = mnist_test.test_data[r:r+1].view(-1,28*28).float().to(device)
Y_single_data = mnist_test.test_labels[r:r+1].to(device)
print('Label: ', Y_single_data.item())
single_prediction = linear(X_single_data)
print('Prediction: ', torch.argmax(single_prediction,1).item())
plt.imshow(mnist_test.test_data[r:r+1].view(28,28),cmap='Greys',interpolation = 'nearest')
plt.show()