본문 바로가기
CODING/AI & ML & DL

[인공지능] Digit Recognizer | kaggle (ver.DNN)

by 밍톨맹톨 2020. 7. 25.
728x90
728x90

 

MNIST 한번 풀어보려고 오랜만에 Kaggle에 들어가서 

[ Digit Recognizer ] 

 

Digit Recognizer

Learn computer vision fundamentals with the famous MNIST data

www.kaggle.com

이걸 풀어보려고 했는데 CNN으로 풀려고 했는데 데이터를 1D로 받아서 2D로 만드는 과정이 안돼서 일단 DNN으로 풀었다.

 

  • DNN (Deep Neural Network) 

입력층과 출력층 사이에 은닉층이 2개 이상 지닌 학습방법을 뜻한다. DNN은 MLP ( multilayer perceptron) 다층 퍼셉트론 레이어라고도 볼 수 있다. 입력층 사이에 너무 많은 레이어가 들어가도 좋지 않고 적당한 레이어를 넣어야 한다.

 

간단하게 DNN을 설명하자면 저렇게 볼 수 있고, 바로 문제를 풀면 일단 

 

⭐️중요⭐️ 런타임에 들어가서 잊지 말고 런타임 유형을 GPU로 바꿔줘야한다. 아니면 정말,, 생각보다 코드 돌리는 게 오래 걸린다.

google에 있는 colaboratory를 사용하기 할 것이기 때문에 아래의 코드를 써주고

!pip uninstall -y kaggle
!pip install --upgrade pip
!pip install kaggle

!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle
!chmod 600 ~/.kaggle/kaggle.json

 

데이터를 불러 오기 위해서 data탭에 들어가서 API를 복사해서 

코드를 작성하면 아래처럼 나온다 

 

[ Import 라이브러리 ]

import torch
import torch.optim as optim
import torch.nn.functional as F
import pandas as pd
import numpy as np
import random
from sklearn.preprocessing import MinMaxScaler

device = 'cuda' if torch.cuda.is_available() else 'cpu'

random.seed(777)
torch.manual_seed(777)
if device == 'cuda':
  torch.cuda.manual_seed_all(777)

 

[ 데이터 불러오기 ]

원래 train 데이터가 저렇게 생겼기 때문에 .loc으로 필요한 부분만 뽑아와 준다.

train = pd.read_csv('train.csv',header = None)
test = pd.read_csv('test.csv',header = None)

x_train = train.loc[1:,1:]
y_train = train.loc[1:,0]

x_train = np.array(x_train,dtype=float)
y_train = np.array(y_train,dtype=float)

x_train = torch.FloatTensor(x_train)
y_train = torch.LongTensor(y_train)

 

 

train_dataset = torch.utils.data.TensorDataset(x_train,y_train)

data_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                          batch_size = batch_size,
                                          shuffle = True,
                                          drop_last = True)

데이터 셋을 만들어주고 data_loader는 batch size만큼 데이터를 잘라서 꺼내 준다고 보면 된다.

shuffle - 데이터를 섞어주는 역할 

drop_last - 만약에 데이터가 30이고 batch size가 4면 마지막 batch는 2개가 될 텐데 이것을 버릴 건지 아니면 사용할 건지 결정하는 것인데 True면 버리고 False면 그냥 사용한다.

 

[ 모델 정의 ]

linear1 = torch.nn.Linear(784,512,bias = True)
linear2 = torch.nn.Linear(512,512,bias = True)
linear3 = torch.nn.Linear(512,512,bias = True)
linear4 = torch.nn.Linear(512,512,bias = True)
linear5 = torch.nn.Linear(512,10,bias = True)

relu = torch.nn.ReLU()
dropout = torch.nn.Dropout(p = 0.3)

torch.nn.init.xavier_uniform_(linear1.weight)
torch.nn.init.xavier_uniform_(linear2.weight)
torch.nn.init.xavier_uniform_(linear3.weight)
torch.nn.init.xavier_uniform_(linear4.weight)
torch.nn.init.xavier_uniform_(linear5.weight)

Linear 하나하나가 레이어가 되는데 1번과 5번은 각각 입력층과 출력층이 된다.

입력이 28*28이지만 1D로 들어가기 때문에 784로 설정하고 나갈 때는 0 - 9까지의 숫자가 되기 때문에 마지막은 10이 된다.

중간 은닉층의 숫자는 바꿔도 상관없다. 

 

초기화 방법은 xavier_uniform을 사용하였고

relu와 dropout은 다음 게시물로 설명해야겠다. 

relu는 activation function인데 종류가 엄청 여러 가지이다. 

 

model = torch.nn.Sequential(linear1,relu,dropout,
                            linear2,relu,dropout,
                            linear3,relu,dropout,
                            linear4,relu,dropout,
                            linear5).to(device)

학습을 위해 차례차례 쌓아주는데 마지막 relu와 dropout을 사용하면 성능이 많이 떨어지기 때문에 빼준다.

loss = torch.nn.CrossEntropyLoss().to(device)
optimzier = optim.Adam(model.parameters(),lr = lr)

결국 이 문제도 분류 문제이기 때문에 loss함수는 CrossEntropyLoss를 사용하고 

optimizer는 Adam을 사용하였다. 

opimizer의 종류도 다양하기 때문에 다음에 다루도록 해야겠다.

 

[ 모델 학습 ] 

total_batch = len(data_loader)
for epoch in range(epochs):
  avg_cost = 0
  for x,y in data_loader:
    x = x.to(device)
    y = y.to(device)


    optimzier.zero_grad()

    hypo = model(x)

    cost = loss(hypo,y)

    cost.backward()

    optimzier.step()

    avg_cost += cost / total_batch

  print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

 

seed값을 바꿀 때마다 다를 수 있긴 하지만 이 정도 나왔고, 제출하고 나니까

95% 정도의 성능을 내는 것을 볼 수 있다. 

 

CNN을 사용하면 더 높은 성능을 낼 수 있기 때문에 다음에는 CNN으로 돌아와야겠다 ㅎ,,,ㅎ,

728x90

댓글