ML/머신러닝

신경망 구조를 이용하여 와인 분류하기[pytorch]

KAU 2020. 2. 24. 14:44

사이킷런에 포함된 와인 데이터 집합을 학습 데이터로 사용할 것이다.

 

 

2020/02/21

3.5기 3팀 최웅준,송근영,김정민

장소: 능곡역 지노스 까페

직접신경망을 구성하기에는 아직 미숙하여 'pytorch를 활용한 머신러닝,딥러닝 철저 입문' 서적에 있는 

신경망을 이용한 와인분류 부분의 코드를 직접 코랩을 이용하면서 실행해보고 분석해보았다. 

 

sklearn 라이브러리('사이킷런')에는 여러가지 데이터들을 제공해주는데 wine 데이터 집합을 활용하였다. 

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

위의 코드들로 라이브러리를 임포트하면 wine데이터를 이용할 수있다.

 

wine변수의 내용은 아래와 같다.

DESCR:데이터 집합의 상세 정보

data:와인 성분 데이터(설명변수)

feature_names:와인의 성분명

target:와인의 품종 데이터(목적변수)

target_names:와인의 품종 이름

신경망 구조

#학습 데이터 준비

#Pytorch 라이브러리 임포트

 

import torch

import numpy as np  

from torch.autograd import Variable

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim 

from torch.utils.data import DataLoader, TensorDataset 

 

# scikit-learn 라이브러리 임포트

 

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

 

 

# Pandas 라이브러리 임포트

import pandas as pd

#와인 데이터 읽어 들이기

#사이킷런에 포함된 와인 데이터 집합을 학습 데이터로 사용할 것이다.

#와인 데이터 집합을 읽어 들여 wine 변수에 저장한다.

#사이킷런에는 다양한 데이터가 저장되어 있다.

 

wine = load_wine()

wine

# 데이터프레임에 담긴 설명변수 출력

# wine.data의 타입은 Numpy 배열이므로 한번에 내용을 파악하기 어렵다. 그러므로

# 여기서 판다스에서 제공하는 데이터프레임 타입으로 변환해서 내용을 볼것이다.

pd.DataFrame(wine.data, columns=wine.feature_names)

 

 

 

 

#목적 변수 데이터 출력

#이번에는 와인 품종 데이터(목적변수)를 확인해 보자. wine.target으로 이 데이터에 접근할 수 있다.

#wine.target의 크기는 178행 1열로,0부터 3까지의 값 중 하나를 갖는 Numpy 배열이다.

 

wine.target = wine.data

#설명변수와 목적변수를 변수에 대입#목적변수의 값은 0~2 까지 3가지이지만 이번에는 0과 1로 2가지로 제한한다. 

#설명변수와 목적변수 모두 앞에서부터 130건까지만 추려낸다. 

#설명변수의 변수명은 wine_data로 하고, 목적변수의 변수명은 wine_target으로 한다.

wine_data = wine.data [0:130]

wine_target = wine.target[0:130]

 

 

#데이터 집합을 훈련 데이터와 테스트 데이터로 분할

train_X, test_X, train_Y, test_Y = train_test_split(wine_data, wine_target, test_size = 0.2)

 

#데이터 건수 확인

print(len(train_X))

print(len(test_X))

 

#데이터 집합을 훈련 데이터와 테스트 데이터로 분할한다.

#훈련 데이터는 모형을 만들 때 사용하며, 테스트 데이터는 생성한 모형을 검증하는 데 사용한다.

#테스트 데이터는 전체 데이터의 20%가 되도록 한다.

#훈련 데이터 설명변수의 변수명은 train_X, 목적 변수의 변수명은 train_Y,

#테스트 데이터 설명변수의 변수명은 test_X, 목적변수 변수명은 test_Y로 한다

# 훈련 데이터 및 테스트 데이터의 건수는 각각 104건과 26건이다.

 

 

# 텐서 생성

 

# 훈련 데이터 텐서변환

train_X = torch.from_numpy(train_X).float()

train_Y = torch.from_numpy(train_Y).long()

 

# 테스트 데이터 텐서 변환

test_X = torch.from_numpy(test_X).float()

test_Y = torch.from_numpy(test_Y).long()

 

# 텐서로 변환한 데이터 건수 확인

print(train_X.shape)

print(train_Y.shape)

 

# 훈련 데이터의 설명변수 train_X와 목적변수 train_Y, 테스트 데이터의 설명변수 test_X와 목적변수 test_Y를 각각 텐서로 변환하고

# 변수명과 같은 이름으로 저장한다. 이때 설명변수의 타입은 Float,목적변수의 타입은 Long으로 한다.

# 텐서라는 용어는 다차원 배열이라는 의미로 보면 된다.

 

 

# 신경망 구성

class Net(nn.Module):

  def __init__(self):

    super(Net,self).__init__()

    self.fc1 = nn.Linear(13,96)

    self.fc2 = nn.Linear(96,2)

 

  def forward(self,x):

    x= F.relu(self.fc1(x))

    x = self.fc2(x)

    return F.log_softmax(x)

 

 

model=Net()

 

# 모형학습하기

criterion = nn.CrossEntropyLoss()

 

optimizer = optim.SGD(model.parameters(),lr=0.01)

 

for epoch in range(300):

  total_loss = 0

 

  for train_X, train_Y in train_loader:

    

    train_X, train_Y = Variable(train_X), Variable(train_Y)

    optimizer.zero_grad()

    output = model(train_X)

    loss = criterion(output, train_Y)

    loss.backward()

    optimizer.step()

    total_loss += loss.data

 

    if (epoch+1) % 50 == 0:

      print(epoch+1,total_loss)

 

결과 값

 

 

#계산 그래프 구성

test_x,test_y = Variable(test_X), Variable(test_Y)

 

#출력이 0 혹은 1이 되게 함

result = torch.max(model(test_x).data,1)[1]

#모형의 정확도 측정

accuracy=sum(test_y.data.numpy()==result.numpy())/len(test_y.data.numpy())

#모형의 정확도 출력

accuracy

 

정확도 65퍼센트가 나오는것을 확인 할 수 있다.

<전체 코드>

import torch

import numpy as np

from torch.autograd import Variable

import torch.nn as nn

import torch.nn.functional as F

import torch.optim as optim 

from torch.utils.data import DataLoader, TensorDataset 

 

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

 

import pandas as pd

 

wine = load_wine()

wine

 

pd.DataFrame(wine.data, columns=wine.feature_names)

 

wine.target

 

wine_data = wine.data [0:130]

wine_target = wine.target[0:130]

 

train_X, test_X, train_Y, test_Y = train_test_split(wine_data, wine_target, test_size = 0.2)

 

print(len(train_X))

print(len(test_X))

 

train_X = torch.from_numpy(train_X).float()

train_Y = torch.from_numpy(train_Y).long()

 

 

test_X = torch.from_numpy(test_X).float()

test_Y = torch.from_numpy(test_Y).long()

 

print(train_X.shape)

print(train_Y.shape)

 

train = TensorDataset(train_X, train_Y)

 

print(train[0])

 

train_loader = DataLoader(train, batch_size= 16, shuffle=True)

 

 

 

 

class Net(nn.Module):

  def __init__(self):

    super(Net,self).__init__()

    self.fc1 = nn.Linear(13,96)

    self.fc2 = nn.Linear(96,2)

 

  def forward(self,x):

    x= F.relu(self.fc1(x))

    x = self.fc2(x)

    return F.log_softmax(x)

 

 

 

model=Net()

 

 

criterion = nn.CrossEntropyLoss()

 

optimizer = optim.SGD(model.parameters(),lr=0.01)

 

for epoch in range(300):

  total_loss = 0

 

  for train_X, train_Y in train_loader:

    

    train_X, train_Y = Variable(train_X), Variable(train_Y)

    optimizer.zero_grad()

    output = model(train_X)

    loss = criterion(output, train_Y)

    loss.backward()

    optimizer.step()

    total_loss += loss.data

 

    if (epoch+1) % 50 == 0:

      print(epoch+1,total_loss)

 

test_x,test_y = Variable(test_X), Variable(test_Y)

 

result = torch.max(model(test_x).data,1)[1]

accuracy=sum(test_y.data.numpy()==result.numpy())/len(test_y.data.numpy())

 

accuracy