MNIST data 다운로드

import torch
import torchvision
import matplotlib.pyplot as plt
mnist = torchvision.datasets.MNIST(root = './data', train=True,
download=True) # 데이터 셋을 불러온다.
print(mnist.data.size()) # 데이터의 크기를 불러온다.
print(mnist.targets.size()) # 데이터의 타겟의 크기를 불러온다.
num = 6000 # 임의의 위치를 지정해준다.
plt.imshow(mnist.data[num],
cmap='Grey', interpolation='nearest') # imshow를 활용해 해당 임으의 위치의 이미지를 보여준다.
plt.show()
print(mnist.targets[num])
  • 위의 과정을 거치면 ([60000, 28, 28])의 28x28의 크기를 같는 6만개의 데이터가 존재하며 타겟 값 역시 60000개가 존재하는 것을 알 수 있다.
  • 맨 아래 imshow를 통해 출력한 num=6000에 해당하는 이미지는 아래와 같다. num 값을 변경해주면 해당 위치에 맞는 이미지를 출력할 수 있는 것이다.

Figure_1

2. 하이퍼 파라미터 설정

  • 하이퍼 파라미터는 사람이 직접 지정해주어야 하는 파라미터를 말한다.
  • 이번에는 아래와 같이 파라미터를 설정한다.
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # cuda를 기본 연산으로 사용하나 없을 경우 cpu로 연산한다.
print(device) # 어떤 장치로 연산을 진행할지 표현한다.
input_size = 784 # 입력으로 넣는 데이터 크기
hidden_size = 500 # 하나의 layer에 있는 퍼셉트론의 갯수
num_classes = 10 # MNIST의 클래스는 10개이기 때문에 10으로 설정
num_epochs = 5 # 학습량을 의미
batch_size = 100 # 한번에 학습하는 데이터의 크기
learning_rate = 0.001

Dataset과 Dataloader

train_dataset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform.ToTensor())
test_dataset = torchvision.datasets.MNIST(root='./data',
train=Ture, transform=transform.ToTensor())

# 배치 단위로 네트워크에 데이터를 넘겨주는 Data loader 생성
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size=batch_size, shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset, batch_size = batch_size, shuffle=False)
  • 데이터 셋을 모델에 삽입할 수 있는 형태로 변환한 후 이를 배치 단위로 데이터 네트워크에 넘겨주기 위한 Data Loader를 생성한다.
  • Transform을 이용해 데이터를 파이토치에서 잘 작동할 수 있도록 Tensor로 변경해준다.

3. 모델 구조 설계

  • 앞에서 설정한 설정값을 이용해 모델을 구성한다. 우리는 inputd을 784개 정의했고 이를 이용해 은닉층에서 500개로 마지막 출력층에서는 최종 10개의 클래스 출력을 가지도록 만들어야 한다. 이를 구현해보면 아래와 같다.
class NeuralNet(nn.Module):
	def __init__(self, input_size, hidden_size, num_classes):
		super(NeuralNet, self).__init__()
		self.fc1 = nn.Linear(input_size, hidden_size) # 각 층을 나타냄
		self.fc2 = nn.Linear(hidden_size, hidden_size)
		self.fc3 = nn.Linear(hidden_size, num_classes)
	def forward(self, x): # 층을 연결시켜주는 과정
		out = F.relu(self.fc1(x))
		out = F.relu(self.fc2(out))
		out = self.fc3(out)
		reutrn out
		
model = NeuralNet(input_size, hidden_size, num_classes).to(device) # to(device) 모델을 지정한 device로 올림

4. Optimizer와 loss function

  • optimizer와 Loss function을 설정한다.
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# model.parameters

5. 훈련(Training)

  • 앞에서 정한 모든 것들을 토대로 훈련 데이터를 모델에 훈련해 보도록 한다.
loss_arr = []
total_step = len(train_loader)
max_value = 0
for epoch in range(num_epochs):
  model.train()
  for i, (images, labels) in enumerate(train_loader):
    # 이미지와 정답(label)을 device로 올림
    images = images.reshape(-1, 28*28).to(device) 
    labels = labels.to(device)
    # Feedforward 과정
    outputs = model(images)
    # Loss 계산
    loss = criterion(outputs, labels)
    # Backward and optimize
    optimizer.zero_grad() # iteration 마다 gradient를 0으로 초기화
    loss.backward() # 가중치 w에 대해 loss를 미분
    optimizer.step() # 가중치들을 업데이트
    if (i+1) % 100 == 0:
      loss_arr.append(loss)
    print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'
    .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
  with torch.no_grad():
    model.eval()
    acc = evaluation(test_loader)
    if max_value < acc :
      max_value = acc
      print("max dev accuracy: ", max_value)
      torch.save(model.state_dict(), 'model.ckpt')

6. 테스트(test)

  • 훈련 데이터를 통해 훈련한 모델의 성능을 평가하기 위해 미리 만들어둔 teste데이터를 이용한다.
  • 테스트 데이터를 통해 평가를 하기 위해 평가 함수를 먼저 정의하고 이를 이용해 테스트 데이터를 모델에 주입한 후 그 성능 측정치(분류 문제이기 때문에 정확도)를 산출한다.
def evaluation(data_loader):
	correct = 0
	total = 0
	for images, labels in data_loader:
		images = images.reshape(-1, 28*28).to(device)
		labels = labels.to(device)
		outputs = model(images)
		_, predicted = torch.max(ouputs.data, 1)
		total += labels.size(0)
		correct += (predicted == labels).sum().item()
	return correct/total
  • Evaluation 함수를 정의한다. 앞서 정의한 데이터 로더를 통해 데이터를 불러오고 이미지를 2차원배열로 재정의 후 모델에 주입한다. 여기서 나온 값의 실제값과 인덱스 중 가장 정확하게 맞는 데이터 인덱스를 포함하여 불러온다. 이를 실제 타깃값과 일치 여부를 따진 후 이를 실제 타겟 개수로 나누어 반환한다. 이를 100을 곱해 확률로 정확도를 산출 할 수 있다.
# test 과정 ; 학습한 모델의 성능을 확인하는 과정
# 이 과정에서는 gradient를 개선할 필요가 없음
with torch.no_grad():
  correct = 0
  total = 0
  for images, labels in test_loader:
    images = images.reshape(-1, 28*28).to(device)
    labels = labels.to(device)
    outputs = model(images)
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum().item()
  print('Accuracy of the network on the 10000 test images: {} %'
  .format(100 * correct / total))
  • 결과는 아래와 같다.

    Accuracy of the network on the 10000 test images: 96.21 %

    • 테스트 데이터에 대한 정확도는 96.21%로 꽤 높게 나온것을 알 수 있다.

Categories:

Updated:

Leave a comment