인공신경망을 이용한 분류

인공신경망을 이용하여 데이터를 분류하는 문제를 테스트해보고자합니다.

필요한 라이브러리들을 다음과 같이 로드합니다.

import numpy as np

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

분류 문제 해결을 위해 사용한 데이터는 zoo 데이터셋입니다. 해당 데이터는 동물의 16가지 특징 정보들 예를 들어 깃털이 있는지 알을 낳는지 비행이 가능한지 등을 체크해서 이 동물이 어느 분류에 들어가는지를 0-7까지의 중에 하나로 분류한 데이터 셋입니다.

xy = np.loadtxt('./zoo.csv', delimiter=',', dtype=np.float32)

해당 데이터의 shape을 보면 (101,17)로 되어 있습니다. 총 16개의 특징(1은 분류)을 가진 101개의 데이터라는 의미입니다.

x_data = xy[:,0:-1]
y_data = xy[:,-1]

x_data = torch.Tensor(x_data)
y_data = torch.Tensor(y_data).long()
x_data.size(), y_data.size() # (torch.Size([101, 16]), torch.Size([101]))

data_length = len(xy)

101개의 데이터를 모두 학습하지 않고 약 8/2정도로 나눠서 훈련용 데이터와 검증용 데이터를 만듭니다. 훈련용 데이터를 만들기 전에 데이터를 랜덤하게 섞어줍니다.

batch_size = .8

train_cnt = int(data_length * batch_size)
valid_cnt = data_length - train_cnt

idx = torch.randperm(data_length)
x = torch.index_select(x_data, dim=0, index=idx).split([train_cnt, valid_cnt], dim=0)
y = torch.index_select(y_data, dim=0, index=idx).split([train_cnt, valid_cnt], dim=0)

학습을 위한 모델을 만들어줍니다. 모델은 16개 데이터를 입력 받아서 최종적으로 7개의 데이터셋을 출력하는 형태입니다.

class ANN(nn.Module):
    
    def __init__(self, D_in, H, D_out):
        super().__init__()
        self.layers = nn.Sequential(
            nn.Linear(D_in, H),
            nn.ReLU(),
            nn.Linear(H, D_out),
        )
    
    def forward(self, x):
        return self.layers(x)

D_in, H, D_out = x_data.size(dim=-1), 100, torch.unique(y_data).size(dim=0)
model = ANN(D_in, H, D_out)

loss와 최적화를 위해 함수를 선언합니다. 또 어떻게 loss가 변화하고 그에따라 정확도가 올라가는지를 표시하기 위해서 hist_loss, hist_accr을 선언하고 학습이 완료될 때마다 데이터를 입력해줍니다.

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())

hist_loss = []
hist_accr = []

epochs = 501

for epoch in range(epochs):
    model.train()
    # loss
    y_pred = model(x[0])
    loss = criterion(y_pred, y[0])
    
    # accuracy
    predict = torch.argmax(y_pred, dim=-1).data == y[0]
    accr = predict.float().mean().item()
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    hist_loss.append(loss.item())
    hist_accr.append(accr)
    
    if epoch%10==0:
        #print(y_pred)
        print('Epoch {:4d}/{} Cost: {:.6f} Accuracy:{}'.format(
            epoch, epochs, loss.item(), accr
        ))

학습이 반복될때마다 loss가 낮아지고 정확도가 올라가는 모습을 볼 수 있습니다. loss도 완만하게 내려가는 것을 보니 learning_rate가 적절히 선언된것 같습니다.

import matplotlib.pyplot as plt

plt.plot(hist_loss)
plt.plot(hist_accr)
plt.legend(['Loss','Accuracy'])
plt.title('Loss/Legend')
plt.xlabel('Epoch')
plt.show()

이제 학습이 완료되었고 테스트용 데이터셋을 활용해서 모델의 정확도를 검증해본결과 Accuracy: 0.95238 데이터를 얻었습니다. 학습을 더 많이 진행한다면 더 높은 정확도를 얻을 수 있을 거라고 생각합니다.

model.eval()

with torch.no_grad():
    predict = model(x[1])
    
    # accuracy
    predict = torch.argmax(predict, dim=-1).data == y[1]
    accr = predict.float().mean().item()
    
    print("Accuracy: %.5f" % accr)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다