Perceptron 을 이용한 MNIST 손글씨 데이터셋 분류
MNIST Datebase (Modified National Institute of Standards and Technology)
- 손으로 쓴 숫자들로 이루어진 대형 데이터베이스
- Train dataset 60,000개, Test dataset 10,000개로 구성됨
1. Single Layer Perceptron (SLP) 실습
목표 : MNIST 손글씨 데이터를 분류하는 single layer(단층) perceptron 모델 학습
입력 : 손글씨 이미지 (28x28x1)
출력 : 0~9까지 숫자들의 정답 확률
▼ 패키지 선언
import torch
import torch.nn as nn
import torchvision.datasets as dataset
import torchvision.transforms as transform
from torch.utils.data import DataLoader
▼ Dataset 다운로드
# Training dataset 다운로드
mnist_train = dataset.MNIST(root = "./",
train = True,
transform = transform.ToTensor(),
download = True)
# Testing dataset 다운로드
mnist_test = dataset.MNIST(root = "./",
train = False,
transform = transform.ToTensor(),
download = True)
▼ MNIST 데이터셋 형상 확인
import matplotlib.pyplot as plt
print(len(mnist_train)) # training dataset 개수 확인
first_data = mnist_train[0]
print(first_data[0].shape) # 첫번째 data의 형상 확인
print(first_data[1]) # 첫번째 data의 정답 확인
plt.imshow(first_data[0][0,:,:], cmap='gray') # 이미지를 시각화
plt.show()
60000
torch.Size([1, 28, 28])
5
※ 참고 _ MNIST 데이터셋 형상
Image : 28x28 (pixels)
MNIST "train" dataset 과 MNIST "test" dataset
MNIST 데이터셋의 perceptron 입력 방법
- Perceptron의 각 노드는 한 번에 한 개의 값을 입력받을 수 있다
- 따라서 2D 형태의 이미지 전처리가 필요하다 → 평탄화
▼ 평탄화 확인
first_img = first_data[0]
print(first_img.shape)
first_img = first_img.view(-1, 28*28) # 이미지 평탄화 수행 2D -> 1D
print(first_img.shape)
torch.Size([1, 28, 28])
torch.Size([1, 784])
● MNIST 이미지는 28x28 픽셀의 2D 배열로 표현된다. (이미지 데이터는 보통 2D 형태로 표현된다.)
● 일부 신경망 모델은 1D 벡터 형태의 입력을 기대할 수 있다.
● 따라서 원래 2D 이미지를 1D로 평탄화하는 역할을 수행한다 → view(-1, 28*28)
● 이렇게 평탄화된 1D 벡터는 주로 이미지의 모든 픽셀 값을 포함하고 신경망의 입력으로 사용되어 이미지의 구조적 특징을 보존하면서도 효과적으로 처리될 수 있다
▼ Single Layer Perceptron 모델 정의
class SLP(nn.Module):
def __init__(self):
super(SLP, self).__init__()
# SLP의 입력은 784개, 출력은 10개
self.fc = nn.Linear(in_features=784, out_features=10)
def forward(self, x):
x = x.view(-1, 28*28) #이미지 평탄화
y = self.fc(x)
return y
Pytorch에서 구현하는 모델은 반드시 2가지 함수를 선언해야 한다.
__init__() 함수 에 포함해야 하는 정보
- Parameter를 가지는 layer 정보 (Fully connected layer, Convolutional layer 등)
- Activation function
- ※참고 : torch.nn.Linear = Fully connected layer
forward() 함수 에 포함해야 하는 정보
- 모델의 동작 순서
- 각 layer, 함수의 입출력 관계
▼ Hyper-parameters 지정
batch_size = 100 # 60,000개에 대해서 600번의 weight update
learning_rate = 0.1
training_epochs = 15 # 15번 반복
loss_function = nn.CrossEntropyLoss()
network = SLP()
optimizer = torch.optim.SGD(network.parameters(), lr = learning_rate)
data_loader = DataLoader(dataset=mnist_train,
batch_size=batch_size,
shuffle=True,
drop_last=True)
✓ Batch size : 100 (한번에 학습할 데이터의 개수)
✓ Learning rate : 0.1 (가중치를 얼마나 변경시킬지 정하는 상수)
✓ Epoch : 15 (1 Epoch: 전체 데이터셋에 대해 1회 학습)
✓ Loss function : Cross entropy error (학습 모델이 얼마나 잘못 예측하고 있는지는 표현하는 지표)
※ 참고 : torch.nn.CrossEntropyLoss()함수
1. 예측 값들에 대해서 자동으로 softmax 적용
2. 정답 값과 예측 값을 이용해서 cross entropy loss 측정
✓ Optimizer: SGD (Loss function을 최소로 만들기 위한 가중치, 편향을 찾는 알고리즘)
✓ Batch 단위의 학습을 위해서 data_loader 함수 사용
▼ Perceptron 학습을 위한 반복문 선언
network.train()
for epoch in range(training_epochs): # 전체 데이터에 대한 반복 : epoch
avg_cost = 0
total_batch = len(data_loader)
for img, label in data_loader: # 1 epoch 내의 1 batch에 대한 반복 : iteration
pred = network(img) → 1. 입력 이미지에 대해서 forward pass
loss = loss_function(pred, label) → 2. 예측 값, 정답 값을 이용해 loss 계산
optimizer.zero_grad() # gradient 초기화
loss.backward() → 3. 모든 weight에 대해 편미분 값 계산
optimizer.step() → 4. 파라미터 업데이트
avg_cost += loss / total_batch # 모든 batch에 대한 평균 loss값 계산
print('Epoch: %d Loss = %f'%(epoch+1, avg_cost))
print('Learning finished')
Epoch: 1 Loss = 0.535026
Epoch: 2 Loss = 0.358744
Epoch: 3 Loss = 0.330988
Epoch: 4 Loss = 0.316194
Epoch: 5 Loss = 0.306888
Epoch: 6 Loss = 0.300198
Epoch: 7 Loss = 0.294928
Epoch: 8 Loss = 0.290794
Epoch: 9 Loss = 0.287432
Epoch: 10 Loss = 0.284395
Epoch: 11 Loss = 0.281804
Epoch: 12 Loss = 0.279809
Epoch: 13 Loss = 0.277766
Epoch: 14 Loss = 0.275743
Epoch: 15 Loss = 0.274424
Learning finished
▼ 학습이 완료된 모델을 이용해 정답률 확인
network.eval()
img_test = mnist_test.data.float()
label_test = mnist_test.targets
with torch.no_grad(): # test에서는 기울기 계산 제외
prediction = network(img_test) # 전체 test data를 한번에 계산
correct_prediction = torch.argmax(prediction, 1) == label_test # 예측 값이 가장 높은 숫자(0~9)와 정답 데이터가 일치한지 확인
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())
Accuracy: 0.8894000053405762
▼ 예측 결과 확인
first_data = mnist_test.data[0] # Test dataset 중 첫 번째 Image에 대해 예측 값 확인
with torch.no_grad():
prediction = network(first_data.float())
prediction_num = torch.argmax(prediction, 1)
print(prediction)
print(prediction_num)
plt.imshow(first_data, cmap="gray")
plt.show
tensor([[ 215.8501, -2486.6294, 311.1895, 1416.2732, -800.1486, -419.4375, -2076.6809, 2521.7944, 381.8009, 792.3948]])
tensor([7])
<function matplotlib.pyplot.show(close=None, block=None)>
2. Multi Layer Perceptron (MLP) 실습
목표 : MNIST 손글씨 데이터를 분류하는 multi layer(단층) perceptron 모델 학습
입력 : 손글씨 이미지 (28x28x1)
출력 : 0~9까지 숫자들의 정답 확률
▼ 패키지 선언 (SLP 와 동일)
import torch
import torch.nn as nn
import torchvision.datasets as dataset
import torchvision.transforms as transform
from torch.utils.data import DataLoader
▼ Dataset 다운로드 (SLP 와 동일)
# Training dataset 다운로드
mnist_train = dataset.MNIST(root = "./",
train = True,
transform = transform.ToTensor(),
download = True)
# Testing dataset 다운로드
mnist_test = dataset.MNIST(root = "./",
train = False,
transform = transform.ToTensor(),
download = True)
▼ Multi Layer Perceptron 모델 정의 (2-layer)
class MLP(nn.Module): # 2-layer
def __init__(self):
super(MLP, self).__init__()
self.fc1 = nn.Linear(in_features=784, out_features=100)
self.fc2 = nn.Linear(in_features=100, out_features=10)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = x.view(-1, 28*28)
y = self.sigmoid(self.fc1(x))
y = self.fc2(y)
return y
fc1의 출력 노드와 fc2의 입력 노드가 반드시 동일해야 한다.
self.fc1 = nn.Linear(in_features=784, out_features=100)
self.fc2 = nn.Linear(in_features=100, out_features=10)
▼ Hyper-parameters 지정 (SLP 와 동일_network만 MLP()로 바꾸면 됨)
batch_size = 100 # 60,000개에 대해서 600번의 weight update
learning_rate = 0.1
training_epochs = 15 # 15번 반복
loss_function = nn.CrossEntropyLoss()
network = MLP()
optimizer = torch.optim.SGD(network.parameters(), lr = learning_rate)
data_loader = DataLoader(dataset=mnist_train,
batch_size=batch_size,
shuffle=True,
drop_last=True)
✓ Batch size : 100 (한번에 학습할 데이터의 개수)
✓ Learning rate : 0.1 (가중치를 얼마나 변경시킬지 정하는 상수)
✓ Epoch : 15 (1 Epoch: 전체 데이터셋에 대해 1회 학습)
✓ Loss function : Cross entropy error (학습 모델이 얼마나 잘못 예측하고 있는지는 표현하는 지표)
※ 참고 : torch.nn.CrossEntropyLoss()함수
1. 예측 값들에 대해서 자동으로 softmax 적용
2. 정답 값과 예측 값을 이용해서 cross entropy loss 측정
✓ Optimizer: SGD (Loss function을 최소로 만들기 위한 가중치, 편향을 찾는 알고리즘)
✓ Batch 단위의 학습을 위해서 data_loader 함수 사용
▼ Perceptron 학습을 위한 반복문 선언 (SLP 와 동일)
network.train()
for epoch in range(training_epochs): # 전체 데이터에 대한 반복 : epoch
avg_cost = 0
total_batch = len(data_loader)
for img, label in data_loader: # 1 epoch 내의 1 batch에 대한 반복 : iteration
pred = network(img) → 1. 입력 이미지에 대해서 forward pass
loss = loss_function(pred, label) → 2. 예측 값, 정답 값을 이용해 loss 계산
optimizer.zero_grad() # gradient 초기화
loss.backward() → 3. 모든 weight에 대해 편미분 값 계산
optimizer.step() → 4. 파라미터 업데이트
avg_cost += loss / total_batch # 모든 batch에 대한 평균 loss값 계산
print('Epoch: %d Loss = %f'%(epoch+1, avg_cost))
print('Learning finished')
Epoch: 1 Loss = 1.154235
Epoch: 2 Loss = 0.450059
Epoch: 3 Loss = 0.360999
Epoch: 4 Loss = 0.324635
Epoch: 5 Loss = 0.302197
Epoch: 6 Loss = 0.285472
Epoch: 7 Loss = 0.271260
Epoch: 8 Loss = 0.258964
Epoch: 9 Loss = 0.247979
Epoch: 10 Loss = 0.237658
Epoch: 11 Loss = 0.228358
Epoch: 12 Loss = 0.219735
Epoch: 13 Loss = 0.211678
Epoch: 14 Loss = 0.204083
Epoch: 15 Loss = 0.196845
Learning finished
▼ 학습이 완료된 모델을 이용해 정답률 확인 (SLP 와 동일)
network.eval()
img_test = mnist_test.data.float()
label_test = mnist_test.targets
with torch.no_grad(): # test에서는 기울기 계산 제외
prediction = network(img_test) # 전체 test data를 한번에 계산
correct_prediction = torch.argmax(prediction, 1) == label_test # 예측 값이 가장 높은 숫자(0~9)와 정답 데이터가 일치한지 확인
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())
Accuracy: 0.9406999945640564
▼ 예측 결과 확인 (SLP 와 동일)
first_data = mnist_test.data[0] # Test dataset 중 첫 번째 Image에 대해 예측 값 확인
with torch.no_grad():
prediction = network(first_data.float())
prediction_num = torch.argmax(prediction, 1)
print(prediction)
print(prediction_num)
plt.imshow(first_data, cmap="gray")
plt.show
tensor([[ 215.8501, -2486.6294, 311.1895, 1416.2732, -800.1486, -419.4375, -2076.6809, 2521.7944, 381.8009, 792.3948]])
tensor([7])
<function matplotlib.pyplot.show(close=None, block=None)>
'머신러닝' 카테고리의 다른 글
Support Vector Machine : Gradient Decent Method (GD) (1) | 2023.12.18 |
---|---|
Support Vector Machine : Quadratic Programming(2차 계획법) (0) | 2023.12.18 |
[머신러닝] Loss Function, Optimization, Batch size (2) | 2023.11.24 |
[머신러닝] Activation Function (0) | 2023.11.17 |
[머신러닝] MLP (Multi Layer Perceptron) (0) | 2023.11.16 |