05. Logistic Regression
๋ณธ ๊ธ์ '๋ชจ๋๋ฅผ ์ํ ๋ฅ๋ฌ๋ ์์ฆ 2'์ 'pytorch๋ก ์์ํ๋ ๋ฅ ๋ฌ๋ ์ ๋ฌธ'์ ๋ณด๋ฉฐ ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
ํ์์ ์๊ฒฌ์ด ์์ฌ ๋ค์ด๊ฐ ๋ถ์ ํํ ๋ด์ฉ์ด ์กด์ฌํ ์ ์์ต๋๋ค.
๋ก์ง์คํฑ ํ๊ท : ์ด์ง ๋ถ๋ฅ!
0. binary classification
- ์ด์ง ๋ถ๋ฅ, 0 ๋๋ 1๋ก ๋ถ๋ฅํ๋ ํํ.
0๋๋ 1๋ก ๋ถ๋ฅ๋ฅผ ํ ๋๋ 0์ผ๋ก ์ญ ๊ฐ๋ค๊ฐ ํน์ ํ ์ ์์ ๊ฐ์๊ธฐ 1์ด๋๊ณ , ์ดํ์ ์ญ 1์ด ๋๋ ๊ณ๋จ ํจ์, step function์ด ์ ์ผ ์ด์์ ์ด๋ค. ๊ทธ๋ฌ๋ ๋ฏธ๋ถ์ ํ ๋ ๋ฑ๋ฑ ๊ณ์ฐ์ ๋ถํธํจ์ด ๋ง๋ค. ๊ทธ๋์ ๊ณ๋จ๊ณผ ์ ์ฌํ S์ ํํ๋ฅผ ํํ ํ ์ ์๋ ํจ์๊ฐ ํ์ํ๋ค. S์ ํํ๋ฅผ ํํํ๊ธฐ ์ํด์๋ ํน์ ํจ์ f๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํด์ ์๋์ ํํ๋ฅผ ์ด๋ค์ผ ํ๋ค.
์ฌ๊ธฐ์ f ์ ์ ํฉํ ํจ์๊ฐ ๋ฐ๋ก ์๊ทธ๋ชจ์ด๋!
1. Sigmoid function
์๊ทธ๋ชจ์ด๋ ํจ์์ ๋ฐฉ์ ์์ ๋ค์๊ณผ ๊ฐ๋ค.
์๊ทธ๋ชจ์ด๋ ํจ์๋ W์ ๊ฐ์ด ์ปค์ง๋ฉด ๊ฒฝ์ฌ๊ฐ ์ปค์ง๊ณ W์ ๊ฐ์ด ์์์ง๋ฉด ๊ฒฝ์ฌ๊ฐ ์์์ง๋ฉฐ, b์ ๊ฐ์ ์ํด ๊ทธ๋ํ๊ฐ ์ข์ฐ๋ก ์ด๋ํ๋ค. ์ ํ ํ๊ท์ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ฌ๊ธฐ์๋ ์ต์ ์ W์ b๋ฅผ ์ฐพ๋ ๊ฒ์ด ๋ชฉํ๊ฐ ๋๋ค.
๋ํ, ์๊ทธ๋ชจ์ด๋๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์๊ณ๊ฐ์ ์กฐ์ ํด์ 0๊ณผ 1์ ๋ถ๋ฅ๊ฐ ๊ฐ๋ฅํ๋ค. ๋ง์ฝ 0.5๋ฅผ ์๊ณ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ค๋ฉด, ์ด๋ฅผ ๋์ผ๋ฉด 1, ์๋๋ฉด 0์ผ๋ก ์ฒ๋ฆฌํด์ ๋ถ๋ฅํ ์ ์๋ค.
2. Cost function
์ ํ ํ๊ท ๋ ์ฌ์ฉํ๋ ๊ฒ ์ฒ๋ผ MSE๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด, non-convexํํ์ ๋ฏธ๋ถ๊ฐ์ด ๋์ค๊ฒ ๋๋ค. ์ด๋ฐ ๊ทธ๋ํ์๋ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ฌ์ฉํ๊ธฐ ๋ถ์ ์ ํด์ง๋ค. ๊ทธ๋ผ, convexํ๊ฒ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๋ ค๋ฉด ์ด๋ค cost function์ ์ฌ์ฉํด์ผ ํ ๊น?
์๊ทธ๋ชจ์ด๋ ํจ์์ ํน์ง์ ํจ์์ ์ถ๋ ฅ๊ฐ์ด 0๊ณผ 1์ฌ์ด์ ๊ฐ์ด๋ผ๋ ์ ์ด๋ค. ์ฆ, ์ค์ ๊ฐ์ด 1์ผ ๋ ์์ธก๊ฐ์ด 0์ ๊ฐ๊น์์ง๋ฉด ์ค์ฐจ๊ฐ ์ปค์ ธ์ผ ํ๋ฉฐ, ์ค์ ๊ฐ์ด 0์ผ ๋, ์์ธก๊ฐ์ด 1์ ๊ฐ๊น์์ง๋ฉด ์ค์ฐจ๊ฐ ์ปค์ ธ์ผ ํ๋ค. ์ด๋ฅผ ์ถฉ์กฑํ๋ ํจ์๊ฐ ๋ฐ๋ก ๋ก๊ทธ ํจ์๋ค! ๋๊ฐ์ ๋ก๊ทธํจ์๋ฅผ 0.5๋ฅผ ๋์นญ์ผ๋ก ๊ฒน์น๋ค๋ฉด, ์ ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ cost function์ ๋ง๋ค ์ ์๋ค. ๋ค์์ y=0.5์ ๋์นญํ๋ ๋ ๊ฐ์ ๋ก๊ทธ ํจ์ ๊ทธ๋ํ์ด๋ค.
์์ผ๋ก ํํํ๋ค๋ฉด, ์๋์ ๊ฐ๋ค.
์ด ๋์์ ํ๋๋ก ํฉ์น ์๋ ์๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์ด ์์ ์ฌ์ฉํด์ sigmoid์ "๋ชจ๋ ์ค์ฐจ์ ํ๊ท "์ ๊ตฌํ ์ ์๋ค.
์ด ๋น์ฉ ํจ์๋ฅผ ์ฝ๋๋ก ๊ตฌํํ ๋, pytorch๋ฅผ ์ด์ฉํด์ ๋ค์์ ๊ฐ์ด ํ ์ ์๋ค.
F.binary_cross_entropy(H(x), y)
binary cross entropy, BCE ๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋ฉฐ, 0์๋๋ฉด 1์ ๋ฆฌํดํ๋ค.
3. Full code
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
x_data = [[1, 2], [2, 3], [3, 1], [4, 3], [5, 3], [6, 2]]
y_data = [[0], [0], [0], [1], [1], [1]] #๋ถ๋ฅ๋๊น 0 ์๋๋ฉด 1
x_train = torch.FloatTensor(x_data) # ๋ฐ์ดํฐ๋ฅผ ํ
์๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ
y_train = torch.FloatTensor(y_data)
W = torch.zeros((2, 1), requires_grad=True) # ํฌ๊ธฐ๋ 2 x 1
b = torch.zeros(1, requires_grad=True)
# hypothesis = 1 / (1 + torch.exp(-(x_train.matmul(W) + b))) #์๊ทธ๋ชจ์ด๋ ํจ์
hypothesis = torch.sigmoid(x_train.matmul(W) + b) #์๋ ๊ฐ์ ๋ป์ธ๋ฐ ๋ ๊ฐ๋จํ๊ฒ ์ฐ์ฐ
#cost function - ์์ผ๋ก ํํํ ๊ฒ
# losses = -(y_train * torch.log(hypothesis) + (1 - y_train) * torch.log(1 - hypothesis))
# cost = losses.mean()
F.binary_cross_entropy(hypothesis, y_train) #์์ ๋์ค๊ณผ ๊ฐ์ ๋ป์ธ๋ฐ ๋ ๊ฐ๋จํ๊ฒ!
#---------------------------------------------------------
#์ง์ ๋๋ ค๋ณด์!
x_data = [[1, 2], [2, 3], [3, 1], [4, 3], [5, 3], [6, 2]]
y_data = [[0], [0], [0], [1], [1], [1]]
x_train = torch.FloatTensor(x_data)
y_train = torch.FloatTensor(y_data)
W = torch.zeros((2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# optimizer ์ค์ - sgd๋ฅผ ์ฌ์ฉ, ํ์ต๋ฅ ์ 1
optimizer = optim.SGD([W, b], lr=1)
nb_epochs = 1000
for epoch in range(nb_epochs + 1):
#์๊ทธ๋ชจ์ด๋ ๊ณ์ฐ(๊ฐ์ค)
hypothesis = torch.sigmoid(x_train.matmul(W) + b)
# Cost ๊ณ์ฐ
cost = F.binary_cross_entropy(hypothesis, y_train)
# cost๋ก H(x) ๊ฐ์
optimizer.zero_grad()
cost.backward() # ๋ฏธ๋ถํ๊ธฐ
# ๊ตฌํ loss๋ก๋ถํฐ back propagation์ ํตํด ๊ฐ ๋ณ์๋ง๋ค loss์ ๋ํ gradient ๋ฅผ ๊ตฌํด์ฃผ๊ธฐ
optimizer.step() #model์ ํ๋ผ๋ฏธํฐ๋ค์ด ์
๋ฐ์ดํธ ๋จ
# 100๋ฒ๋ง๋ค ๋ก๊ทธ ์ถ๋ ฅ
if epoch % 100 == 0:
print('Epoch {:4d}/{} Cost: {:.6f}'.format(
epoch, nb_epochs, cost.item()
))
prediction = hypothesis >= torch.FloatTensor([0.5]) #์๊ณ๊ฐ์ ์ฃผ๊ณ 0, 1๋ก ๊ตฌ๋ถ
4. Full code with nn.Module
#import, data๋ ์์ ๋์ผ
class BinaryClassifier(nn.Module): #class ๋ง๋ค์ด์ฃผ๊ธฐ
def __init__(self):
super().__init__()
self.linear = nn.Linear(2, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
return self.sigmoid(self.linear(x)) #linear๋ฅผ sigmoidํ์์ค
model = BinaryClassifier() #model์์ฑ
# optimizer ์ค์
optimizer = optim.SGD(model.parameters(), lr=1)
nb_epochs = 10000
for epoch in range(nb_epochs + 1):
# H(x) ๊ณ์ฐ
hypothesis = model(x_train)
# cost ๊ณ์ฐ
cost = F.binary_cross_entropy(hypothesis, y_train)
# cost๋ก H(x) ๊ฐ์
optimizer.zero_grad()
cost.backward()
optimizer.step()
# 20๋ฒ๋ง๋ค ๋ก๊ทธ ์ถ๋ ฅ
if epoch % 100 == 0:
prediction = hypothesis >= torch.FloatTensor([0.5])
correct_prediction = prediction.float() == y_train
accuracy = correct_prediction.sum().item() / len(correct_prediction)
print('Epoch {:4d}/{} Cost: {:.6f} Accuracy {:2.2f}%'.format(
epoch, nb_epochs, cost.item(), accuracy * 100,
))
etc. regression, classification
regression์ ํ๊ท๋ผ๊ณ ํ๋๋ฐ, ์ผ๋ฐ์ ์ผ๋ก ํํํ์๋ฉด fitting์ด๋ผ๊ณ ํ ์ ์๋ค.
์ฆ, lienar regression์ด๋ ์ด๋ค data์ ๋ถํฌ๊ฐ linearํ๋ค๊ณ ๊ฐ์ ํ๊ณ , ์ด linear ํจ์๋ฅผ ์ฐพ๋ ๊ฒ์ด๋ค.
1์ฐจ ํจ์๋ฅผ ๋ง๋๊ธฐ๋ก ํํ ํ์ง๋ฉด data์ ๋ถํฌ๋ฅผ ๊ฐ์ฅ ์ ๋ํ๋ผ ์ ์๋ ๋ง๋๊ธฐ์ ์์น์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ฐพ๋ ๊ฒ์ด๋ค.
๋ค๋ฅด๊ฒ ๋งํ์๋ฉด data๋ผ ์ด linear ํจ์๋ฅผ ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์, ๊ทธ๋ฌํ ๋ชจ์์ผ๋ก ๋ถํฌ๋์ด ์๋ค๊ณ ๋ ํ ์ ์๋ค.
์ฆ, data์ ๋ถํฌ๋ฅผ ์ด๋ฃจ๋ ํจ์์ ์ํ์ ์ฐพ์๊ฐ๋ ๊ฒ์ด ํ๊ท๋ผ๊ณ ํ ์ ์๋ค.
logstic regression์ ๋ฐ์ดํฐ์ cost funtion์ ์ต์ํ ํ๋๋ก logistic function์ regressionํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
๋ณดํต continuous ํ ๊ฐ์ ๋ํด์๋ linear regression์ ์ฌ์ฉํ๊ณ , 0 ๋๋ 1์ classification์ logistic regression์ ์ฌ์ฉํ๋ค.
classification์ 0์ด๋ 1์ด๋ ๊ฐ์ ๋งค๊ธฐ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ logistic function์ ์ด์ฉํ regression์ด ๋ ์ ํฉํ๋ค.
<Reference>
https://deeplearningzerotoall.github.io/season2/lec_pytorch.html