본문 바로가기
AI

CNN으로 mnist 분류하기

by KJY 2021. 5. 2.

CNN으로 mnist 분류하기

1. 모델 이해하기

1. 첫번째 표기 방법

합성곱 + 활성화 함수를 하나의 합성곱 층으로 보고, 맥스 풀링은 풀링 층으로 별도로 명명

2. 두번째 표기 방법

합성곱 + 활성화 함수 + 맥스 풀링을 하나의 합성곱 층으로 봄.

두번째 표기법을 사용하기로 함.

# 1번 레이어 : 합성곱층(Convolutional layer)
합성곱(in_channel = 1, out_channel = 32, kernel_size=3, stride=1, padding=1) + 활성화 함수 ReLU
맥스풀링(kernel_size=2, stride=2))

# 2번 레이어 : 합성곱층(Convolutional layer)
합성곱(in_channel = 32, out_channel = 64, kernel_size=3, stride=1, padding=1) + 활성화 함수 ReLU
맥스풀링(kernel_size=2, stride=2))

# 3번 레이어 : 전결합층(Fully-Connected layer)
특성맵을 펼친다. # batch_size × 7 × 7 × 64 → batch_size × 3136
전결합층(뉴런 10개) + 활성화 함수 Softmax

 

2. 모델 구현하기

1. 필요한 도구 임포트와 입력의 정의

import torch
import torch.nn as nn

임의의 텐서를 만듦

# 배치 크기 * 채널 * 높이 * 너비의 크기의 텐서를 선언
inputs = torch.Tensor(1, 1, 28, 28)

2. 합성곱층과 풀링 선언하기

첫번째 합성곱 층 : 1채널 짜리를 입력 받아서 32 채널을 뽑아냄

conv1 = nn.Conv2d(1, 32, 3, padding=1)

두번째 합성곱 층 : 64 채널을 뽑아내는데 커널 사이즈는 3이고 패딩은 1

conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)

맥스 풀링 : 정수 하나를 인자로 넣으면 커널 사이즈와 스트라이드가 둘다 해당값으로 지정됨.

pool = n.MaxPool2d(2)

3. 구현체를 연결하여 모델 만들기

입력을 첫번째 합성곱 층을 통과 시킴

out = conv1(inputs)
print(out.shape)
torch.Size([1, 32, 28, 28])

맥스 폴링 통과

out = pool(out)
print(out.shape)
torch.Size([1, 32, 14, 14])

두번째 합성곱 층 통과

out = conv2(out)
print(out.shape)
torch.Size([1, 64, 14, 14])

맥스 폴링 통과

out = pool(out)
print(out.shape)
torch.Size([1, 64, 7, 7])

배치 차원을 그대로 두고 나머지를 펼침

out = out.view(out.size(0), -1)
print(out.shape)
torch.Size([1, 3136])

전결합층(Fully-Connteced layer) 통과. 출력층으로 10개의 뉴련을 배치하여 10개의 차원의 텐서로 변환

fc = nn.Linear(3136, 10)
out = fc(out)
print(out.shape)
torch.Size([1, 10])

 

3. CNN으로 MNIST 분류하기

필요한 도구 임포트

import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
device = 'cuda' if torch.cuda.is_available() else 'cpu'
torch.manual_seed(777)
if device == 'cuda':
  torch.cuda.manual_seed_all(777)

학습에 사용할 파라미터 설정

learning_rate = 0.001
training_epochs = 15
batch_size = 100

데이터로더를 사용하여 데이터를 다루기 위해서 데이터셋을 정의

mnist_train = dsets.MNIST(root='MNIST_data/', # 다운로드 경로 지정
                          train=True, # True를 지정하면 훈련 데이터로 다운로드
                          transform=transforms.ToTensor(), # 텐서로 변환
                          download=True)

mnist_test = dsets.MNIST(root='MNIST_data/', # 다운로드 경로 지정
                         train=False, # False를 지정하면 테스트 데이터로 다운로드
                         transform=transforms.ToTensor(), # 텐서로 변환
                         download=True)

데이터로더를 사용하여 배치 크기를 정해줌.

data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
                                          batch_size=batch_size,
                                             suffle=True,
                                             drop_last=True)

클래스로 모델 설계

class CNN(torch.nn.Module):
  def __init(self):
    super(CNN, self).__init__()
    self.layer1 = torch.nn.Sequential(
            torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
    self.layer2 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2))
    self.fc = torch.nn.Linear(7 * 7 * 64, 10, bias=True)

    # 전결합층 한정으로 가중치 초기화
    torch.nn.init.xavier_uniform_(self.fc.weight)

  def forward(self, x):
    out = self.layer1(x)
    out = self.layer2(out)
    out = out.view(out.size(0), -1)
    out = self.fc(out)
    return out

모델 정의

model = CNN().to(device)

비용 함수와 옵티마이저 정의

criterion = torch.nn.CrossEntropyLoss().to(device) # 소프트 맥스 포함
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

학습 진행

for epoch in range(training_epochs):
  avg_cost = 0

  for x, y in data_loader:
    X = x.to(device)
    Y = Y.to(device)

    optimizer.zero_grad()
    hypothesis = model(X)
    cost = criterion(hypothesis, Y)
    cost.backward()
    optimizer.step()

    avg_cost += cost / total_batch

  print('[Epoch: {:>4}] cost = {:>.9}'.format(epoch + 1, avg_cost))

테스트 진행

with torch.no_grad():
    X_test = mnist_test.test_data.view(len(mnist_test), 1, 28, 28).float().to(device)
  Y_test = mnist_test.test_labels.to(device)

  prediction = model(X_test)
  correct_prediction = torch.argmax(prediction, 1) == Y_test
  accuracy = correct_prediction.float().mean()
  print('Accuracy:', accuracy.item())

'AI' 카테고리의 다른 글

CNN  (0) 2021.05.02
ANN  (0) 2021.05.02

댓글