본문 바로가기

Programming/[Data Science]

[ML] pytorch로 다층 퍼셉트론 구현하여 손글씨 분류

반응형

1. 숫자 필기 데이터 소개

숫자 필기 데이터는 사이킷런 패키지에서 제공하는 분류용 예제 데이터입니다.

  • 0부터 9까지의 숫자를 손으로 쓴 이미지 데이터입니다.
  • 각 이미지는 0부터 15까지의 명암을 가지는 8 x 8 = 64 픽셀 해상도의 흑백 이미지입니다.
  • 해당 이미지가 1,797개 있습니다.

load_digits()를 통해 이미지 데이터를 로드할 수 있습니다. 로드한 전체 데이터를 digits에 저장합니다.

%matplotlib inline
import matplotlib.pyplot as plt # 시각화를 위한 모듈 임포트
from sklearn.datasets import load_digits
digits = load_digits() # 1,979개의 이미지 데이터 로드

첫 번째 샘플을 출력해보겠습니다. digits.images[index_num]를 사용하면 해당 인덱스의 이미지를 행렬로 출력할 수 있습니다.

print(digits.images[0])
[[ 0.  0.  5. 13.  9.  1.  0.  0.]
 [ 0.  0. 13. 15. 10. 15.  5.  0.]
 [ 0.  3. 15.  2.  0. 11.  8.  0.]
 [ 0.  4. 12.  0.  0.  8.  8.  0.]
 [ 0.  5.  8.  0.  0.  9.  8.  0.]
 [ 0.  4. 11.  0.  1. 12.  7.  0.]
 [ 0.  2. 14.  5. 10. 12.  0.  0.]
 [ 0.  0.  6. 13. 10.  0.  0.  0.]]
print(digits.target[0])
0

이런 샘플이 몇 개 있는지 확인합니다.

print('전체 샘플의 수 : {}'.format(len(digits.images)))

전체 샘플 중 상위 5개의 샘플만 시각화 해봅시다.

images_and_labels = list(zip(digits.images, digits.target))
for index, (image, label) in enumerate(images_and_labels[:5]): # 5개의 샘플만 출력
    plt.subplot(2, 5, index + 1)
    plt.axis('off')
    plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    plt.title('sample: %i' % label)

img

상위 5개의 샘플을 pyplot을 이용하여 시각화 했는데, 순서대로 숫자 0,1,2,3,4의 손글씨로 보입니다. 상위 5개 샘플의 레이블을 확인해보겠습니다.

for i in range(5):
    print(i,'번 인덱스 샘플의 레이블 : ',digits.target[i])
0 번 인덱스 샘플의 레이블 :  0
1 번 인덱스 샘플의 레이블 :  1
2 번 인덱스 샘플의 레이블 :  2
3 번 인덱스 샘플의 레이블 :  3
4 번 인덱스 샘플의 레이블 :  4

훈련 데이터와 레이블을 나누기 전에 digits를 살펴보겠습니다.

digits

벡터화 되어있는 부분이 images와 data 가 있는데 훈련 데이터로 digit.data를 이용하거나 digit.images를 reshape 해도 좋습니다.

X = digits.images.reshape(-1,64)
X.shape
#혹은
X = digits.data 
X.shape
(1797, 64)

다음과 같이 X,Y 변수를 설정합니다.

X = digits.data # 이미지 벡터
Y = digits.target   # 이미지에 대한 레이블

2. 다층 퍼셉트론 분류기 만들기

torch 모듈을 불러오고, 인공신경망을 구축합니다.

import torch
import torch.nn as nn
from torch import optim

# 모델 구축 (인공신경망 구축)
model = nn.Sequential(
    nn.Linear(64, 32),  # input_layer = 64, hidden_layer1 = 32
    nn.ReLU(),
    nn.Linear(32, 16),  # hidden_layer2 = 32, hidden_layer_3 = 16
    nn.ReLU(),
    nn.Linear(16, 10)   # hidden_layer_4 = 16, output_layer = 10
)

케라스와 비교했을 때 토치의 모델 구축이 초급자에겐 불친절할 수 있겠지만 인공신경망 모델링을 어느정도 해본 입장에서는 오히려 직관적일 수 있겠다는 느낌이 들었습니다.

케라스의 인공신경망 모델링

from keras.models import Sequential
from keras.layers import Dense

model = Sequential()
model.add(Dense(32, activation='ReLU', input_shape=(64,)))
model.add(Dense(16, activation='ReLU'))
model.add(Dense(10, activation='softmax'))

X,Y 데이터를 변형하고 손실 함수와 옵티마이저를 설정한 후 학습을 진행합니다.

X = torch.tensor(X, dtype = torch.float32)
Y = torch.tensor(Y, dtype = torch.int64)

loss_fn = nn.CrossEntropyLoss()     # 이 비용 함수는 소프트맥스 함수를 포함하고 있음
optimizer = optim.Adam(model.parameters())
losses = []

for epoch in range(100):
    optimizer.zero_grad()
    y_pred = model(X) # forwar 연산
    loss = loss_fn(y_pred, Y)
    loss.backward()
    optimizer.step()

    if epoch % 10 == 0:
        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
                epoch, 100, loss.item()
        ))

    losses.append(loss.item())

plt.plot(losses)

plot


출처 : Pytorch로 시작하는 딥 러닝 입문

Pytorch

반응형