<목차>
1. MNIST
2. Torchvision
3. Torchvision을 이용해 MNIST 불러오기
Softmax
Test & Visulization
MNIST
- 숫자 0부터 9까지의 이미지로 구성된 손글씨 데이터셋. 과거에 우체국에서 편지의 우편 번호를 인식하기 위해서 만들어진 훈련 데이터
- 28 픽셀 × 28 픽셀의 이미지
Torchvision
- 유명한 데이터셋들, 이미 구현되어져 있는 유명한 모델들, 일반적인 이미지 전처리 도구들을 포함하고 있는 패키지
- torchvision.utils 를 통해 dataset을 쉽게 읽어올 수 있음
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
Torchvision을 이용해 MNIST 불러오기
- pytorch의 경우 이미지는 0과 1 사이의 값을 가짐 (채널, 높이, 너비 순). 그런데 일반적인 이미지는 0에서 255의 값을 가지고 높이, 너비, 채널 순으로 되어있음. -> toTensor()는 pytorch에 맞게 순서와 값을 바꿔줌
import torchvision.datasets as dsets
mnist_train = dsets.MNIST(root='MNIST_data/',
train=True,
transform=transforms.ToTensor(),
download=True)
# root는 MNIST 데이터를 다운로드 받을 경로
# train은 인자로 True를 주면, MNIST의 훈련 데이터를 리턴받으며 False를 주면 테스트 데이터를 리턴
# transform은 현재 데이터를 파이토치 텐서로 변환해줌
# download는 해당 경로에 MNIST 데이터가 없다면 다운로드 받겠다는 의미
mnist_test = dsets.MNIST(root='MNIST_data/',
train=False,
transform=transforms.ToTensor(),
download=True)
# dataset loader
data_loader = DataLoader(dataset=mnist_train,
batch_size=batch_size, # 배치 크기는 100
shuffle=True,
drop_last=True)
# dataset은 로드할 대상을 의미
# batch_size는 배치 크기
# shuffle은 매 에포크마다 미니 배치를 셔플할 것인지의 여부
# drop_last는 마지막 배치를 버릴 것인지
- drop_last를 하는 이유를 이해하기 위해서 1,000개의 데이터가 있다고 했을 때, 배치 크기가 128이라고 해봅시다. 1,000을 128로 나누면 총 7개가 나오고 나머지로 104개가 남습니다. 이때 104개를 마지막 배치로 한다고 하였을 때 128개를 충족하지 못하였으므로 104개를 그냥 버릴 수도 있습니다. 이때 마지막 배치를 버리려면 drop_last=True를 해주면 됩니다. 이는 다른 미니 배치보다 개수가 적은 마지막 배치를 경사 하강법에 사용하여 마지막 배치가 상대적으로 과대 평가되는 현상을 막아줍니다.
- 784차원의 벡터로 만드는 코드
for X, Y in data_loader:
# 입력 이미지를 [batch_size × 784]의 크기로 reshape
# 레이블은 원-핫 인코딩
X = X.view(-1, 28*28)
X에는 MNIST 이미지가 불러와짐. Y는 label (0-9)가 불러와짐.
X는 for문에서 호출될 때는 (배치 크기 × 1 × 28 × 28)의 크기를 가지지만, view를 통해서 (배치 크기 × 784)의 크기로 변환
Softmax
- 앞서 소프트맥스 회귀를 배울 때는 torch.nn.functional.cross_entropy()를 사용하였으나 여기서는 torch.nn.CrossEntropyLoss()을 사용하고 있음. 둘 다 파이토치에서 제공하는 크로스 엔트로피 함수로 둘 다 소프트맥스 함수를 포함하고 있음.
# MNIST data image of shape 28 * 28 = 784
# MNIST 0-9까지 10개
linear = nn.Linear(784, 10, bias=True).to(device)
# parameters
training_epochs = 15
batch_size = 100
# 비용 함수와 옵티마이저 정의
criterion = nn.CrossEntropyLoss().to(device) # 내부적으로 소프트맥스 함수를 포함하고 있음.
optimizer = torch.optim.SGD(linear.parameters(), lr=0.1)
for epoch in range(training_epochs): # 앞서 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)
optimizer.zero_grad()
hypothesis = linear(X)
cost = criterion(hypothesis, Y)
cost.backward()
optimizer.step()
avg_cost += cost / total_batch
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))
print('Learning finished')
Test & Visualization
with torch.no_grad(): # 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()
'전공공부 > 인공지능' 카테고리의 다른 글
[실습] softmax model, train, validation, learning rate 조절, data processing (0) | 2022.07.28 |
---|---|
Softmax regression 구현하기 (0) | 2022.07.27 |
Softmax Classification (0) | 2022.07.27 |
Mini Batch 경사하강법, Data Load, Custom Dataset (0) | 2022.07.27 |
Class로 pytorch 모델 구현 (0) | 2022.07.27 |