728x90
반응형
PyTorch를 활용한 로지스틱회귀¶
로지스틱회귀는 주어진 데이터를 0이나 1값으로 분류하는 선형 분류 모델이다.
In [176]:
import torch
from torch import autograd, nn, optim
import torch.nn.functional as F
import numpy as np
In [177]:
lin = lambda a, b, x : a*x + b
def gen_fake_data(n, a, b):
x = np.random.uniform(-20, 20, (n, 2))
x2_hat = lin(a,b, x[:,0])
y = x[:,1] > x2_hat
return x, y.astype(int)
# 분류문제에 맞는 가짜 데이터를 생성한다
x, y = gen_fake_data(100, 1., 0.5)
x[:5], y[:5]
Out[177]:
In [178]:
import matplotlib.pyplot as plt
%matplotlib inline
t = np.arange(-20, 20, 0.2)
plt.scatter(x[:,0],x[:,1],c=y, s=8);
plt.xlabel("x1"); plt.ylabel("x2");
plt.plot(t, t + 0.5, 'r--')
Out[178]:
선형분류 문제에서는 데이터를 두개의 그룹으로 잘 나눌 수 있는 a * x + b를 데이터 기반으로 구하는 문제이다. (이때 데이터의 레이블 즉 y값은 0이나 1값이 될것이다.)
이제 새로운 데이터셋을 사용해 PyTorch 텐서로 만들어본다.
In [179]:
from sklearn.model_selection import train_test_split
x, y = gen_fake_data(10000, 1., 0.5)
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
x_train = torch.tensor(X_train).float()
y_train = torch.tensor(y_train).float()
x_test = torch.tensor(X_test).float()
y_test = torch.tensor(y_test).float()
x_train, y_train, x_test, y_test
Out[179]:
Model 클래스¶
모델 클래스를 만들어보도록 하겠다. 선형회귀 클래스와는 다르게 이번에는 sigmoid함수가 함께 들어가있다. sigmoid함수란 실수의 값을 0~1사이의 값으로 바꿔주는 함수이다. 이 함수의 출력값이 0또는 1값에 가깝게 수렴하도록 학습하는 것이다. 아래 경사하강법 Loop의 y_hat값을 보기 좋게 출력해놓았는데, 처음엔 0과1 사이의 소수점의 값으로 시작했다가, 학습을 반복할 수록 0또는 1로 수렴하는것을 볼 수 있다. 분류문제에서는 보통 loss함수를 MSE가 아닌 Cross Entropy로 사용한다. (MSE를 사용하면 결과가 제대로 나오지 않으니 주의)
In [190]:
class LogisticRegression(nn.Module):
def __init__(self):
super().__init__()
self.lin = nn.Linear(2, 1)
self.sigmoid = F.sigmoid
def forward(self, x):
x = self.lin(x)
x = self.sigmoid(x)
return x
model = LogisticRegression()
model
Out[190]:
In [191]:
learning_rate = 0.1
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
model.train()
for t in range(len(x_train)):
y_hat = model(x_train)
loss = F.binary_cross_entropy(y_hat, y_train.unsqueeze(1))
if t %1000 == 0:
y_hat_formatted ="[{}]".format(", ".join([str(round(y[0], 4)) for y in y_hat[:5].data.numpy()]))
print(y_hat_formatted, "loss: {}".format(loss.item()))
optimizer.zero_grad()
loss.backward()
optimizer.step()
In [192]:
print([p for p in model.parameters()])
Scikit Learn에서 제공하는 accuracy_score를 사용해 모델을 평가해 보겠다. round함수는 0.9997과 같은 값이 1로 0.01과 같은 값이 0으로 잘 매핑되기 위해서 이다. 비슷한 정규분포를 사용했기 때문에 결과는 잘 나올 수 밖에 없다.
In [193]:
from sklearn.metrics import accuracy_score
with torch.no_grad():
model.eval()
x_test_unsqueezed = x_test.unsqueeze(1)
outputs = model(x_test_unsqueezed)
print(accuracy_score(y_test, outputs.squeeze().round()))
참고자료
아래의 원본 소스를 기반으로 번역 및 개인 의견을 덧붙인 코드입니다.
728x90
반응형
'데이터사이언스 > PyTorch' 카테고리의 다른 글
PyTorch 5 - 딥러닝 기반 협업필터링 (0) | 2019.07.22 |
---|---|
PyTorch 4 - 협업필터링 (0) | 2019.07.14 |
PyTorch 3 - 데이터 로더, 신경망 (0) | 2019.07.13 |
PyTorch 1 - 텐서 (0) | 2019.07.09 |