MNIST ๋ฐ์ดํฐ์ ์๊ธ์จ๋ก ์ ํ ์ซ์ ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฅํ๋ ๋ค์ค ๋ถ๋ฅ(Multiclass classification) ๋ฌธ์ ๋ฅผ ๋ค๋ฃฐ ๊ฒ์ด๋ค. ๋ฐ์ดํฐ๋ ์ฌ๊ธฐ(https://www.kaggle.com/c/digit-recognizer)์์ ์ป์ ์ ์๋ค.
ํ์ดํ ์น๋ฅผ ์ด์ฉํ์ฌ ์ธ๊ณต์ ๊ฒฝ๋ง(Artificial Neural Network)์ ๊ตฌํํ ๊ฒ์ด๋ค. ๊ตฌํ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. ๋ฐ์ดํฐ ์ ๋ ฅ ๋ฐ ํ์ธ
2. ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
3. ๋ชจ๋ธ ์ค์
4. ๋ฐ์ดํฐ ํ์ต ๋ฐ ๊ฒ์ฆ
1. ๋ฐ์ดํฐ ์ ๋ ฅ ๋ฐ ํ์ธ
In:
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
โท ๋ฐ์ดํฐ ์ ๋ ฅ์ pandas, ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ์ numpy, ๋ฅ๋ฌ๋ ๊ตฌํ์ torch, ์๊ฐํ์ matplotlib ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ ๊ฒ์ด๋ค.
In:
df_total = pd.read_csv('../input/train.csv', dtype = np.float32)
โท pandas์ read_csv()๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฅธ๋ค. dtype ์ธ์๋ฅผ np.float32๋ก ์ฃผ์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ผ ์ ์๋๋ก ํ์.
In:
print(df_total.columns)
print(df_total.index)
Out:
Index(['label', 'pixel0', 'pixel1', 'pixel2', 'pixel3', 'pixel4', 'pixel5',
'pixel6', 'pixel7', 'pixel8',
...
'pixel774', 'pixel775', 'pixel776', 'pixel777', 'pixel778', 'pixel779',
'pixel780', 'pixel781', 'pixel782', 'pixel783'],
dtype='object', length=785)
RangeIndex(start=0, stop=42000, step=1)
โท ๋ฐ์ดํฐ์ ์ด์ ๊ฐ์๋ 785๊ฐ๋ก, ๋ ์ด๋ธ(Label)๊ณผ ํด๋น ์์น์ ํฝ์ (Pixel)์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค. ๊ฐ ์ด๋ฏธ์ง๋ฅผ ์ด๋ฃจ๋ ์ ์ฒด ํฝ์ ์ ๊ฐ์๋ 784(28×28)๊ฐ์ด๊ณ , ๋ฐ์ดํฐ์ ํ์ ๊ฐ์๋ 42,000๊ฐ์ด๋ค.
2. ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
In:
arr_feature = df_total.loc[:, df_total.columns != 'label'].values/255
arr_target = df_total.label.values
arr_feature_train, arr_feature_test, arr_target_train, arr_target_test = train_test_split(arr_feature,
arr_target,
test_size = 0.2)
โท df_total๋ก๋ถํฐ ํผ์ฒ(Feature)์ ๋ ์ด๋ธ์ ํด๋นํ๋ ๋ถ๋ถ์ ๋ถ๋ฆฌํ์ฌ arr_feature๊ณผ arr_target๋ฅผ ๋ง๋ค์๋ค. arr_feature์ ๊ฒฝ์ฐ, ํผ์ฒ์ 255๋ก ๋๋์ด ์ ๊ทํ(Normalization)ํ์๋ค.
โท train_test_split()์ ์ด์ฉํ์ฌ ํ๋ จ ์ธํธ(arr_feature_train, arr_target_train)์ ํ ์คํธ ์ธํธ(arr_feature_test, arr_target_test)๋ฅผ 8:2๋ก ๋๋๋ค.
In:
ts_feature_train = torch.from_numpy(arr_feature_train)
ts_target_train = torch.from_numpy(arr_target_train).type(torch.LongTensor)
ts_feature_test = torch.from_numpy(arr_feature_test)
ts_target_test = torch.from_numpy(arr_target_test).type(torch.LongTensor)
print(type(ts_feature_train))
print(type(ts_target_train))
print(type(ts_feature_test))
print(type(ts_target_test))
Out:
<class 'torch.Tensor'>
<class 'torch.Tensor'>
<class 'torch.Tensor'>
<class 'torch.Tensor'>
โท ๊ฐ ๋ฐ์ดํฐ ์ธํธ์ ๋ฐ์ดํฐ ํ์ ์ ํ ์(Tensor)๋ก ๋ฐ๊พผ๋ค.
In:
ds_train = torch.utils.data.TensorDataset(ts_feature_train, ts_target_train)
ds_test = torch.utils.data.TensorDataset(ts_feature_test, ts_target_test)
โท ๊ฐ ๋ฐ์ดํฐ ์ธํธ๋ณ ํผ์ฒ์ ๋ ์ด๋ธ ํ ์๋ฅผ ํ ์ ๋ฐ์ดํฐ ์ธํธ(Tensor dataset)๋ก ํฉ์น๋ค.
In:
batch_size = 256
ldr_train = torch.utils.data.DataLoader(ds_train,
batch_size = batch_size,
shuffle = True)
ldr_test = torch.utils.data.DataLoader(ds_train,
batch_size = batch_size,
shuffle = True)
batch_size: ํ๋ จ ๋ฐ ํ ์คํธ ์ธํธ์ ๋ฐฐ์น ํฌ๊ธฐ
โท ํ๋ จ ๋ฐ ํ ์คํธ ์ธํธ์ ํ์ ์ ๋ฐ์ดํฐ๋ก๋(Data loader)๋ก ๋ฐ๊พผ๋ค. ์ด ๋, batch_size์ shuffle ์ธ์์ ๊ฐ์ ์ฃผ์ด ๋ฐ์ดํฐ ๊ตฌ์ฑ์ ์ค์ ํ๋ค.
In:
def get_image(data, idx):
plt.imshow(data[idx].reshape(28, 28))
plt.axis('off')
plt.show()
for i in range(10):
get_image(arr_feature_train, np.where(arr_target_train == i)[0][1])
Out:
โท ํ๋ จ ์ธํธ์ ๊ฐ ์ซ์๋ณ ์ฒซ ๋ฒ์งธ ์ด๋ฏธ์ง์ ๊ฒฐ๊ณผ์ด๋ค. ๊ฐ ์ซ์๋ณ ์ฒซ ๋ฒ์งธ์ ์ธ๋ฑ์ค๋ฅผ ์ฐพ๊ธฐ ์ํด np.where()๋ฅผ ์ด์ฉํ์๋ค.
โท 784๊ฐ์ ํฝ์ ์ 28×28์ ํํ๋ก ๋ง๋ค๊ธฐ ์ํด reshape()๋ฅผ ์ด์ฉํ์๋ค.
3. ๋ชจ๋ธ ์ค์
๋ชจ๋ธ์ ์ํคํ ์ณ(Architecture)๋ ๋ค์๊ณผ ๊ฐ๋ค.
In:
class ANN(nn.Module):
def __init__(self):
super().__init__()
self.fc_1 = nn.Linear(28*28, 512)
self.fc_2 = nn.Linear(512, 256)
self.fc_3 = nn.Linear(256, 128)
self.fc_4 = nn.Linear(128, 64)
self.fc_5 = nn.Linear(64, 10)
self.dropout = nn.Dropout(p = 0.2)
self.log_softmax = F.log_softmax
def forward(self, x):
x = self.dropout(F.relu(self.fc_1(x)))
x = self.dropout(F.relu(self.fc_2(x)))
x = self.dropout(F.relu(self.fc_3(x)))
x = self.dropout(F.relu(self.fc_4(x)))
x = self.log_softmax(self.fc_5(x), dim = 1)
return x
โท nn.Linear()๋ฅผ ์ด์ฉํ์ฌ ๋ชจ๋ธ์ ์ํคํ ์ณ์ ๊ฐ์ด ์ ๊ฒฐํฉ ๋ ์ด์ด(Fully-connected layer)๋ฅผ ๊ตฌ์ฑํ๋ค.
โท nn.Dropout()๋ฅผ ์ด์ฉํ์ฌ ์์ ํ(Propagation) ๊ณผ์ ์ ๊ฐ ๋ ธ๋๋ฅผ ๋๋กญ์์(Dropout)ํ๋๋ก ํ์๋ค. ๋๋กญ์์๋ ํ๋ฅ ์ 0.2๋ก ์ค์ ํ์๋ค.
โท F.log_softmax()๋ฅผ ์ด์ฉํ์ฌ ๋ง์ง๋ง ๋ ์ด์ด์์ ๋ก๊ทธ ์ํํธ ๋งฅ์ค(Log softmax)๋ฅผ ๊ณ์ฐํ๋ค. ์ด๋ ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ(Cross entropy loss)๋ฅผ ๊ตฌํ๊ธฐ ์ํ ์์ ์ด๋ค.
โท F.relu()๋ฅผ ์ด์ฉํ์ฌ ํ์ฑํ ํจ์(Activation function)๋ก ReLU ํจ์๋ฅผ ์ฌ์ฉํ๋ค. ReLU๋ ๋ง์ง๋ง ๋ ์ด์ด๋ฅผ ์ ์ธํ ๋ชจ๋ ๋ ์ด์ด์ ์ ์ฉ๋๋ค.
4. ๋ฐ์ดํฐ ํ์ต ๋ฐ ๊ฒ์ฆ
In:
model = ANN()
loss_fun = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr = 0.0001)
โท loss_fun์ nn.NLLLoss()๋ก ์ ์ํจ์ผ๋ก์จ ์์ ๋ก๊ทธ ์ํํธ ๋งฅ์ค ๊ณ์ฐ ๊ฒฐ๊ณผ์ ์ ์ฉํ์ฌ ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ๋ฅผ ๊ตฌํ๊ฒ ๋๋ค.
โท ๋ชจ๋ธ์ ์ต์ ํ ๊ณผ์ ์๋ optim.Adam()์ ์ด์ฉํ์ฌ ์งํํ ๊ฒ์ด๋ค. ํ์ต๋ฅ (Learning rate)๋ 0.0001๋ก ์ค์ ํ์๋ค.
In:
# (1) ํ์ต ํ๋ผ๋ฏธํฐ ๋ฐ ๋ณ์ ์ค์
epoch = 25
train_loss, test_loss = [], []
for e in range(epoch):
# (2) ๋ชจ๋ธ ํ์ต
running_loss_train = 0
for image, label in ldr_train:
optimizer.zero_grad()
log_pred = model(image)
loss = loss_fun(log_pred, label)
loss.backward()
optimizer.step()
running_loss_train += loss.item()
# (3) ๋ชจ๋ธ ๊ฒ์ฆ
running_loss_test = 0
accuracy = 0
with torch.no_grad():
model.eval()
for image, label in ldr_test:
log_pred = model(image)
running_loss_test += loss_fun(log_pred, label)
pred = torch.exp(log_pred)
top_prob, top_class = pred.topk(1, dim = 1)
equal = (top_class == label.view(*top_class.shape))
accuracy += torch.mean(equal.type(torch.FloatTensor))
model.train()
train_loss.append(running_loss_train/len(ldr_train))
test_loss.append(running_loss_test/len(ldr_test))
print("Epoch: {}/{}.. ".format(e + 1, epoch),
"Training Loss: {:.3f}.. ".format(train_loss[-1]),
"Test Loss: {:.3f}.. ".format(test_loss[-1]),
"Test Accuracy: {:.3f}".format(accuracy/len(ldr_test)))
(1) ํ์ต ํ๋ผ๋ฏธํฐ ๋ฐ ๋ณ์ ์ค์
epoch: ์ ์ฒด ๋ฐ์ดํฐ์ ํ์ต(์์ ํ์ ์ญ์ ํ ๊ณผ์ ) ํ์ ์ค์
train_loss, test_loss: ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ์ ํ์ต ๊ฒฐ๊ณผ ์ค์ฐจ ๊ธฐ๋ก
(2) ๋ชจ๋ธ ํ์ต
running_loss_train: ํ๋ จ ์ธํธ์ ํ์ต ํ์๋ณ ์ค์ฐจ ๊ธฐ๋ก
โท optimizer.zero_grad()๋ฅผ ์ด์ฉํ์ฌ ์ตํฐ๋ง์ด์ (Optimizer)์ ๊ฒฝ์ฌ๋๋ฅผ 0์ผ๋ก ๋ง๋ ๋ค. ์์ ํ์ ์ญ์ ํ ๊ณผ์ ์ ๋ฐ๋ฅธ ์ ๋ฐ์ดํธ(Update)๋ ๊ฒฝ์ฌ๋๊ฐ ๋์ ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, ๋ฐฐ์น์ ๋ํ ํ์ต์ด ๋๋ ๋๋ง๋ค ์ตํฐ๋ง์ด์ ์ ๊ฒฝ์ฌ๋๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํ ๊ฒ์ด๋ค.
โท model()์ ์ด์ฉํ์ฌ ์์ ํ ๊ณผ์ ์ ์ํํ์ฌ ๊ฐ ํด๋์ค ๋ณ ๋ก๊ทธ ์ํํธ ๋งฅ์ค ๊ฐ์ ๊ตฌํ๋ค. log_pred์ label์ loss_fun()์ ์ธ์๋ก ์ฃผ์ด ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ๋ฅผ ๊ตฌํ๋ค.
โท model.eval()์ ์ด์ฉํ์ฌ ํ๊ฐ๋ชจ๋๋ก ๋ณํํ๋ค.
โท loss.backward()๋ฅผ ์ด์ฉํ์ฌ ์ญ์ ํ ๊ณผ์ ์ ์ํํ๊ณ , optimizer.step()์ ์ด์ฉํ์ฌ ๋ชจ๋ธ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
โท running_loss_train์ ํ๋ จ ์ธํธ์ ๋ชจ๋ ๋ฐฐ์น loss.item()์ ๋ํ์ฌ ์ ์ฒด ์ค์ฐจ๋ฅผ ๊ตฌํ๋ค.
โท model.train()์ ์ด์ฉํ์ฌ ํ์ต๋ชจ๋๋ก ๋ณํํ๋ค.
(3) ๋ชจ๋ธ ๊ฒ์ฆ
running_loss_test: ํ ์คํธ ์ธํธ์ ํ์ต ํ์๋ณ ์ค์ฐจ ๊ธฐ๋ก
accuracy: ๋ชจ๋ธ์ ์์ธก๊ณผ ์ค์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ์ฌ ๋ชจ๋ธ์ ์ ํ๋ ๊ธฐ๋ก
โท torch.no_grad()๋ ํ ์์ ์ ์ฅ๋ ๊ฒฝ์ฌ๋๋ฅผ ์ง์ด๋ค. ๋ชจ๋ธ ๊ฒ์ฆ ๊ณผ์ ์์ ํ ์์ ์ ์ฅ๋ ๊ฒฝ์ฌ๋๊ฐ ํ์์๊ธฐ ๋๋ฌธ์ with๋ฅผ ์ด์ฉํ์ฌ ๊ฒ์ฆ ๊ณผ์ ์ ๋ชจ๋ ํ ์์ torch.no_grad()๋ฅผ ์ ์ฉํ๋ค. ์ด๋ ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ๋ฐ ์ฐ์ฐ ์๋ ์ฆ๊ฐ์ ๋์์ด ๋๋ค.
โท model()์ ์ด์ฉํ์ฌ ํ์ต๋ ๋ชจ๋ธ์ ์ด์ฉํ์ฌ ์์ธกํ๊ณ , log_pred์ label์ loss_fun()์ ์ธ์๋ก ์ฃผ์ด ๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ๋ฅผ ๊ตฌํ๋ค.
โท running_loss_test์ ํ ์คํธ ์ธํธ์ ๋ชจ๋ ๋ฐฐ์น loss.item()์ ๋ํ์ฌ ์ ์ฒด ์ค์ฐจ๋ฅผ ๊ตฌํ๋ค.
โท torch.exp()๋ฅผ ์ด์ฉํ์ฌ log_pred๋ฅผ ํ๋ฅ ๋ก ๋ง๋ค๊ณ , torch.topk()๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ํด๋์ค๋ฅผ ์์ธก ๊ฒฐ๊ณผ๋ก ํ๋ค.
โท torch.view()๋ label๊ณผ top_class์ ํํ๋ฅผ ๊ฐ๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉ๋์๋ค. top_class == label์ ํตํด ์์ธก ๊ฒฐ๊ณผ์ ์ค์ ๋ ์ด๋ธ์ด ๊ฐ์ผ๋ฉด 1, ์๋๋ฉด 0์ด๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ๋ค, ํ๊ท ์ ๊ตฌํ์ฌ ์ ํ๋๋ฅผ ๊ณ์ฐํ์๋ค.
Out:
Epoch: 1/25.. Training Loss: 1.829.. Test Loss: 0.833.. Test Accuracy: 0.775
Epoch: 2/25.. Training Loss: 0.755.. Test Loss: 0.473.. Test Accuracy: 0.864
Epoch: 3/25.. Training Loss: 0.535.. Test Loss: 0.365.. Test Accuracy: 0.894
Epoch: 4/25.. Training Loss: 0.438.. Test Loss: 0.310.. Test Accuracy: 0.910
Epoch: 5/25.. Training Loss: 0.376.. Test Loss: 0.270.. Test Accuracy: 0.922
Epoch: 6/25.. Training Loss: 0.329.. Test Loss: 0.238.. Test Accuracy: 0.930
Epoch: 7/25.. Training Loss: 0.293.. Test Loss: 0.210.. Test Accuracy: 0.937
Epoch: 8/25.. Training Loss: 0.265.. Test Loss: 0.193.. Test Accuracy: 0.942
Epoch: 9/25.. Training Loss: 0.242.. Test Loss: 0.171.. Test Accuracy: 0.949
Epoch: 10/25.. Training Loss: 0.225.. Test Loss: 0.157.. Test Accuracy: 0.954
Epoch: 11/25.. Training Loss: 0.209.. Test Loss: 0.143.. Test Accuracy: 0.958
Epoch: 12/25.. Training Loss: 0.191.. Test Loss: 0.131.. Test Accuracy: 0.961
Epoch: 13/25.. Training Loss: 0.177.. Test Loss: 0.121.. Test Accuracy: 0.965
Epoch: 14/25.. Training Loss: 0.164.. Test Loss: 0.114.. Test Accuracy: 0.967
Epoch: 15/25.. Training Loss: 0.158.. Test Loss: 0.104.. Test Accuracy: 0.970
Epoch: 16/25.. Training Loss: 0.148.. Test Loss: 0.098.. Test Accuracy: 0.972
Epoch: 17/25.. Training Loss: 0.138.. Test Loss: 0.093.. Test Accuracy: 0.973
Epoch: 18/25.. Training Loss: 0.130.. Test Loss: 0.090.. Test Accuracy: 0.974
Epoch: 19/25.. Training Loss: 0.122.. Test Loss: 0.078.. Test Accuracy: 0.978
Epoch: 20/25.. Training Loss: 0.114.. Test Loss: 0.075.. Test Accuracy: 0.979
Epoch: 21/25.. Training Loss: 0.110.. Test Loss: 0.069.. Test Accuracy: 0.980
Epoch: 22/25.. Training Loss: 0.105.. Test Loss: 0.065.. Test Accuracy: 0.982
Epoch: 23/25.. Training Loss: 0.098.. Test Loss: 0.060.. Test Accuracy: 0.983
Epoch: 24/25.. Training Loss: 0.096.. Test Loss: 0.056.. Test Accuracy: 0.984
Epoch: 25/25.. Training Loss: 0.089.. Test Loss: 0.053.. Test Accuracy: 0.985
In:
plt.plot(train_loss, label = 'Training loss')
plt.plot(test_loss, label = 'Test loss')
plt.xlabel('Epoch')
plt.ylabel('Cross Entropy Loss')
plt.legend(frameon = True)
Out:
โท ํ์ต์ด ์งํ๋จ์ ๋ฐ๋ผ ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ์ ์ค์ฐจ๊ฐ ์ค์ด๋ค๊ณ ์๋ ๋ชจ์ต์ ํ์ธํ ์ ์๋ค.
โท ๋ง์ง๋ง ์ํญ(Epoch)์์ ํ ์คํธ ์ธํธ์ ์ ํ๋๊ฐ 98.5%๋ก ์๋นํ ํก์กฑํ ๋งํผ ๋์๋ค. ๋ฌผ๋ก , ์ ํํ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ธก์ ํ๊ธฐ ์ํด์๋ ๋ณด์ง ์์(Unseen) ๋ฐ์ดํฐ์ ๋ํ ๊ฒ์ฆ์ด ํ์ํ ๊ฒ์ด๋ค. ์ด๋ ์๋ตํ๋๋ก ํ๊ฒ ๋ค.
Reference:
"MNIST: Introduction to ComputerVision with PyTorch," Abhinand, https://www.kaggle.com/abhinand05/mnist-introduction-to-computervision-with-pytorch.
'Deep Learning > Model' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
LSTM(Long Short-Term Memories model) ๊ตฌํ (0) | 2020.10.10 |
---|---|
์ํ ์ ๊ฒฝ๋ง(Recurrent Neural Network) ๊ตฌํ (0) | 2020.10.01 |
ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง(Convolutional Neural Network) ๊ตฌํ (0) | 2020.08.07 |