pytorch (mnist 데이터 실습)

yeoni·2023년 6월 21일
0

딥러닝-Pytorch

목록 보기
2/3

1. import

import torch
import torch.nn as nn # 딥러닝에 필요한 모듈이 담겨 있다
import torch.nn.functional as F # 딥러닝에서 사용하는 함수들
import torch.optim as optim # 최적화 알고리즘
from torchvision import datasets, transforms # torchvision 딥러닝에서 사용되는 dataset을 가지고 있음
from matplotlib import pyplot as plt
%matplotlib inline

2. cuda 설정

is_cuda = torch.cuda.is_available() # 런타임 - 런타임 유형 변경 - GPU면 cuda 사용 가능
device = torch.device('cuda' if is_cuda else 'cpu')
print('Current cuda device is ', device)

3. 데이터 불러오기

#mnist 데이터
#torchvision의 datasets 기능 -> 현재 data 폴더로 다운로드, transform 전처리 옵션 -> tensor로 변환
train_data = datasets.MNIST(root='./data', train=True, download=True, transform=transforms.ToTensor())
test_data = datasets.MNIST(root='./data', train=False, download=True, transform=transforms.ToTensor())
print('number of training data: ', len(train_data))
print('number of testing data: ', len(test_data))
'''
number of training data:  60000
number of testing data:  10000
'''

4. 데이터 하나 확인

  • torch에서는 [1, 28, 28] → 채널의 차원이 앞으로 온다.
    tensorflow(28, 28, 1) → 채널의 차원이 뒤로 온다.
  • squeeze() : '1'인 demension1제거
    • 3인 demension을 2차원으로 바꿔 그림으로 바꿀 수 있게 해줌
# train_data에 image, label
image, label = train_data[0]

#numpy(): tensor -> numpy로
plt.imshow(image.squeeze().numpy(), cmap='gray')
plt.title('label : %s' % label)
plt.show()

5. 미니 배치 구성

# 미니 배치 구성
# DataLoader(데이터, 배치 사이즈, 데이터의 순서 학습하지 못하게 shuffle)
train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)

# 첫 번째 배치
first_batch = train_loader.__iter__().__next__()

# :15 15칸 확보 / :< 왼쪽 정렬 25칸
# first_batch[0] 픽셀 데이터
# first_batch[1] label
print('{:15s} | {:<25s} | {}'.format('name', 'type', 'size'))
print('{:15s} | {:<25s} | {}'.format('Number of Batch', '', len(train_loader)))
print('{:15s} | {:<25s} | {}'.format('first_batch', str(type(first_batch)), len(first_batch)))
print('{:15s} | {:<25s} | {}'.format('first_batch[0]', str(type(first_batch[0])), first_batch[0].shape))
print('{:15s} | {:<25s} | {}'.format('first_batch[1]', str(type(first_batch[1])), first_batch[1].shape))
'''
name            | type                      | size
Number of Batch |                           | 1200
first_batch     | <class 'list'>            | 2
first_batch[0]  | <class 'torch.Tensor'>    | torch.Size([50, 1, 28, 28])
first_batch[1]  | <class 'torch.Tensor'>    | torch.Size([50])
'''

6. 모델

class CNN(nn.Module):
  def __init__(self):
    # nn.Module 상속
    super(CNN, self).__init__()
    # conv1 -> Conv2d(입력 채널 수, 출력 채널, 커널 size 3*3, strides, padding)
    self.conv1 = nn.Conv2d(1, 32, 3, 1, padding='same')
    # conv2 -> 32 > 64
    self.conv2 = nn.Conv2d(32, 64, 3, 1, padding='same')
    self.dropout = nn.Dropout2d(0.25)
    # 28 * 28 -> pooling size 2 -> 14 * 14 -> pooling size 2 -> 7 * 7 * 채널 64
    self.fc1 = nn.Linear(3136, 1000) #7*7*64 = 3136 입력
    self.fc2 = nn.Linear(1000, 10) # 출력 1000 -> 10

  def forward(self, x):
    x = self.conv1(x)
    # activation function
    x = F.relu(x)
    # max_pooling 2 * 2 -> 가중치x
    x = F.max_pool2d(x, 2)
    x = self.conv2(x)
    x = F.relu(x)
    x = F.max_pool2d(x, 2)
    x = self.dropout(x)
    # 펼치기 -> 1차원
    x = torch.flatten(x, 1)
    # layer
    x = self.fc1(x)
    # 은닉층에 대한 활성함수
    x = F.relu(x)
    x = self.fc2(x)
    # softmax 보다 log_softmax 연산 속도 조금 더 올려줌
    output = F.log_softmax(x, dim=1)
    return output

7. 모델 선언

#파라미터 설정
batch_size=50
learning_rate=0.0001
epoch_num=15

model = CNN().to(device)
optimizer = optim.Adam(model.parameters(), lr=learning_rate) #Adam
criterion = nn.CrossEntropyLoss()

8. 학습

model.train() #train를 시작하는게 아니라 시작하겠다는 선언!
i = 1
for epoch in range(epoch_num): # 전체 데이터 50번
  for data, target in train_loader: #12000개 묶음
    data = data.to(device)
    target = target.to(device)
    optimizer.zero_grad() #gredient 초기화
    output = model(data)
    loss = criterion(output, target)
    loss.backward() #역전파
    optimizer.step() #가중치 업데이트
    if i % 1000 == 0:
      print('Train Step: {} \tLoss: {:.3f}'.format(i, loss.item()))
    i += 1

9. 테스트

model.eval() #평가모드 dropout 기능이 자동으로 꺼진다
correct = 0
for data, target in test_loader:
  # data, target = Variable(data, volatile=True), Variable(target)
  data = data.to(device)
  target = target.to(device)
  output = model(data)
  prediction = output.data.max(1)[1] #output-> one hot encode -> maxinum index
  correct += prediction.eq(target.data).sum() #몇개가 맞는지 저장

print('Test set: Accuracy: {:.2f}%'.format(100 * correct / len(test_loader.dataset))) #Test set: Accuracy: 99.24%
profile
데이터 사이언스 / just do it

0개의 댓글