#Logistic regression example
# 라이브러리 호출
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import pandas as pd # 데이터를 가공하기 위함
import numpy as np
import matplotlib.pyplot as plt # 그림을 그리기 위함
%matplotlib inline
#파일 업로드
data = pd.read_csv('./mba_admission.csv') # ./ --> 현재 경로를 나타낸다
data.columns # 데이터 속성을 확인함
data.shape # (40,4) --> 행 : 데이터 크기, 열 : gmat, gpa, work_experience --> 입력, admitted --> 결과
data.head()
# dataset 가공
class dataset(torch.utils.data.Dataset):
def __init__(self,data):
self.data = data
self.data['gmat'] /= self.data['gmat'].max() # max 함수를 통해 정규화, 모든 데이터가 0~1로 정규화 된다.
self.data['gpa'] /= self.data['gpa'].max()
self.data['work_experience'] /= self.data['work_experience'].max()
def __getitem__(self, idx):
X = torch.Tensor(self.data[self.data.columns[:3]].values) # self.data.columns[:3] --> gmat, gpa, work_experience
Y = torch.Tensor(self.data['admitted']) # .values --> pandas의 자체값만을 이용하겠다는 뜻
return X[idx,:], Y[idx]
def __len__(self):
return self.data.shape[0] # 전체 데이터의 개수 --> 40
train_dataset = dataset(data)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, shuffle=True, drop_last=False)
# neural network 모델 생성
# 구조: 입력(3), 은닉(10), 출력(1)
# 활성화: tanh sigmoid
class admission_model(nn.Module):
def __init__(self):
super(admission_model,self).__init__()
self.lin1 = nn.Linear(3, 10)
self.lin2 = nn.Linear(10, 1)
def forward(self,x): # 입력받은 데이터가 일련의 과정을 거치면 리턴되는 x는 y_hat
x = self.lin1(x)
x = F.tanh(x)
x = self.lin2(x)
x = F.sigmoid(x)
return x
model = admission_model()
optimizer = optim.SGD(model.parameters(),lr=0.5)
# 학습단계
# 최적화를 할 때 반복횟수가 굉장히 중요하다. 어떤 데이터를 어떤 배치만큼 잘라내어 마지막 배치까지 돌아야 epoch가 됨
for ep in range(100): # 100번 epoch
loss_buffer = [] # 각 epoch마다 loss를 확인하기 위함
for X,Y in train_loader: # epoch마다 각각의 batch 단위를 학습 # 여기에서 X,Y는 위에서 정의한 class 안의 getitem의 X,Y에 대응되는 것
optimizer.zero_grad()
y_infer = model(X) # y_infer.shape == (8,1)
Y = Y.view(-1,1) # Y.shape(8,) --> Y.view(-1,1)
loss = -torch.mean(Y*torch.log(y_infer)+(1-Y)*torch.log(1-y_infer)) # cross entropy 거리함수 이용
loss.backward()
optimizer.step()
loss_buffer.append(loss.item()) # 각 배치마다 loss_buffer의 빈 array에 loss 값 추가
if ep % 10 == 0:
print('Epoch : {}, Loss: {}'.format(ep, np.mean(loss_buffer)))
# 결과 시각화
y_infer = model(torch.Tensor(data[data.columns[:3]].values))
plt.scatter(np.arange(data.shape[0]),data['admitted'],color='red',label='True result')
plt.scatter(np.arange(data.shape[0]),y_infer.detach().numpy(),color='blue',label='Predicted result') # detach() : 기존 Tensor에서 gradient 전파가 안되는 텐서 생성
plt.hlines(0.5,-10,60,label='Admission boundary')
plt.legend(loc='upper center', fontsize='10')
plt.xlim(-1,41)
plt.ylim(-0.1,1.5)
plt.xlabel('Volunteer')
plt.ylabel('Result')
plt.title('MBA admission result included prediction')