[Classification] CNN으로 MNIST data 분류하기
728x90
반응형
# 딥러닝 학습 단계 (code 기준)
1) 라이브러리 불러오기 (torch, torchvision, matplotlib 등등)
2) GPU 사용 설정하고 randon value를 위한 seed 설정
3) 학습에 사용되는 hyper-parameter 설정 (learning rate, training epochs, batch size 등)
4) Dataset download & 학습에 사용되기 편하게 DataLoader 생성
5) 학습 모델 만들기 (CNN, DNN 등)
6) Loss function(=Criterion) 정의하고 Optimizer 선언
7) 모델 학습 및 Loss check (=Criterion의 output)
8) 학습된 모델의 성능 Test
MNIST 데이터를 CNN을 적용하여 분류해보는 실습을 해보자.

목차
1. Package Load 및 초기 설정
# 초기 라이브러리 불러오기
import torch
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import torch.nn.init
import torch.nn as nn
# GPU 설정
device = 'cuda' if torch.cuda.is_available() else 'cpu'
'''cuda가 사용가능하면 GPU 사용, 그렇지 않으면 CPU 사용'''
torch.manual_seed(123) # random value를 고정해주는 역할
if device == 'cuda':
torch.cuda.manual_seed_all(123)
print(device) # GPU or CPU 사용여부 check
torch.cuda.is_available() # True : GPU 사용 가능
>>
cuda
True
2. 하이퍼파라미터 설정
# parameter 설정
learning_rate = 0.001
training_epoch = 15
batch_size = 100
3. MNIST dataset 및 DataLoader
# MNIST dataset 불러오기
mnist_train = dsets.MNIST(root='MNIST_data/',
train=True,
transform=transforms.ToTensor(),
download=True)
mnist_test = dsets.MNIST(root='MNIST_data/',
train=False,
transform=transforms.ToTensor(),
download=True)
# dataloader 생성
data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
batch_size = batch_size,
shuffle=True,
drop_last=True)
- transform을 통해 불러온 input 데이터를 어떻게 변환할 것인지 결정한다.
→ ToTensor() : 데이터를 Tensor로 전환
- 다운로드 완료한 data로 DataLoader 생성
4. CNN 모델 설계 ***
# CNN 모델 생성 (layer1 - layer2 - view - FC layer)
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
# Layer 1
self.layer1 = nn.Sequential(
nn.Conv2d(1,32,kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
# Layer 2
self.layer2 = nn.Sequential(
nn.Conv2d(32,64,kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
# Layer 3
self.layer3 = nn.Sequential(
nn.Conv2d(64,128, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
# Fully Connected Layer
self.fc1 = nn.Linear(3*3*128, 625)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(625, 10, bias=True)
torch.nn.init.xavier_uniform_(self.fc1.weight) # weight 초기화
torch.nn.init.xavier_uniform_(self.fc2.weight) # weight 초기화
def forward(self, x):
out = self.layer1(x) # forward에 input으로 받은 x가 layer1를 통과하고 out으로 출력
out = self.layer2(out)
out = self.layer3(out)
out = out.view(out.size(0), -1) # batch_size만큼 펼치고, 나머지는 한 줄로 펼침
out = self.fc1(out)
out = self.relu(out)
out = self.fc2(out) # 마지막으로 통과할 Fully Connected layer 통과
return out
# 모델 적용 및 출력
model = CNN().to(device)
model
>>
CNN(
(layer1): Sequential(
(0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(layer2): Sequential(
(0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(layer3): Sequential(
(0): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(fc1): Linear(in_features=1152, out_features=625, bias=True)
(relu): ReLU()
(fc2): Linear(in_features=625, out_features=10, bias=True)
)
- CNN 모델이 잘 설계되었는지 확인하는 작업!
→ layer1, 2, 3 그리고 FC layer를 가지는 CNN 모델을 확인할 수 있다.
# 테스트하기
input = torch.Tensor(1,1,28,28).to(device)
print((model(input)).shape)
>> torch.Size([1, 10])
5. Loss function & Optimizer 정의
# loss function & Optimizer 선언
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
6. Training (학습)
# Training code
total_batch = len(data_loader)
print('Learning Started.')
for epoch in range(training_epoch):
avg_cost = 0 # avg_cost에 loss를 하나씩 추가하기 위함
for X, Y in data_loader: # X : Image, Y : Label
X = X.to(device)
Y = Y.to(device)
optimizer.zero_grad()
hypothesis = model(X) # model의 input값을 넣어서 출력값이 가설(hypothesis)
cost = criterion(hypothesis, Y)
# cost값은 위에 선언한 CrossEntropy로 계산 - 가설과 실제 Label 사이의 loss 계산
cost.backward()
optimizer.step()
# cost값은 total_batch로 나누어서 누적 연산
avg_cost += cost / total_batch
# 1 epoch이 끝날때마다 cost값 출력
print('[Epoch:{:2d}] Cost = {}'.format(epoch+1, avg_cost))
print('Learning Finished!')
>>
Learning Started.
[Epoch: 1] Cost = 0.023552587255835533
[Epoch: 2] Cost = 0.019308632239699364
[Epoch: 3] Cost = 0.015114493668079376
[Epoch: 4] Cost = 0.013405434787273407
[Epoch: 5] Cost = 0.010400256142020226
[Epoch: 6] Cost = 0.010682093910872936
[Epoch: 7] Cost = 0.008156407624483109
[Epoch: 8] Cost = 0.00843567494302988
[Epoch: 9] Cost = 0.006146769970655441
[Epoch:10] Cost = 0.005543440580368042
[Epoch:11] Cost = 0.006324873771518469
[Epoch:12] Cost = 0.005305475555360317
[Epoch:13] Cost = 0.005281165707856417
[Epoch:14] Cost = 0.004536697641015053
[Epoch:15] Cost = 0.005650686100125313
Learning Finished!
→ Epoch이 돌수록 cost(=loss)값이 현저히 감소하는 것을 확인할 수 있다. 학습 잘 됨!
7. Test (테스트)
# 학습 결과값에 대한 Test
with torch.no_grad(): # 학습할 필요가 없으므로 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())
>> Accuracy: 0.9878000020980835
- X_test : 위에 선언한 mnist_test값을 불러와서 한번에 넣기 위해 view() 함수 이용
→ model에 X_test값을 통째로 입력한다.
- torch.argmax : 얻어진 예측값이 실제 Label인 Y_test값과 같은지 체크
- accuracy : correct_prediction의 평균으로 출력된다.
→ 위에서 확인할 수 있듯이 학습한 모델의 정확도가 98.78% 를 가진다.
References :
- 파이토치로 시작하는 딥러닝 기초(boostcourse), 모두의 딥러닝
- CNN for MNIST Handwritten dataset (https://medium.com/@yash.4198/cnn-for-mnist-handwritten-dataset-cc94d61f6c94)
'AI |Computer Vision > Image Classification' 카테고리의 다른 글
[Classification] Convolution Neural Network(CNN, 합성곱 신경망) (0) | 2022.06.04 |
---|
댓글