본문 바로가기

[Pytorch] Logistic Regression (로지스틱 회귀)

Derrick 발행일 : 2022-04-20
728x90
반응형

1. Logistic Regression 간략 설명 및 구현

 Logistic Regression은 2가지 중 하나를 결정하는 문제인 ' Binary Classification (이진 분류) '
 풀기 위한 대표적인 알고리즘 중에 하나이다. ex) 스팸 메일 분류, 합격/불합격 분류 등

 

1-1. Hypothesis ( ex, Sigmoid function )

 Sigmoid function은 입력값이 커질수록 1에 수렴하고, 작아질수록 0에 수렴한다.
 이 함수의 출력값은 0 ~ 1 사이의 값을 가지는데, 이 특성을 이용하여 Classification 작업에 사용
 ex) 임계값(=0.5) 이상이면 1(True), 이하이면 0(False)로 판단

 

[ Hypothesis of Logistic Regression ]

 

[ Sigmoid function / W=2(r), W=1(g), W=0.5(b) ]

 

1-2. Cost function

 Linear regression에서 사용했던 MSE 수식을 cost function으로 사용하게 되면, Global Minimum
 를 구하기 어렵기 때문에 y = 0.5 지점에서 대칭하는 두 개의 로그 함수를 사용한다.

 

[ MSE formula ]

 
 실제값(y)이 1이면 좌측(주황색), 0이면 우측(초록색)으로 나타나며, 아래의 수식처럼 모든 오차의 평
 균을 구함으로써 cost function이 나온다.
 → 이를 통해 Gradient Descent를 수행하면서 최적의 가중치(W)값을 찾는 과정을 거친다.

 

[ Cost function graph ]

 

[ Cost function formula of Logistic Regression ]

 

1-3. 기본 모델 구현하기

 → 여러 x들 중에서 y를 예측하는 다중 logistic regression 구현

 

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)

# Training Dataset 정의
x_data = [[1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1]]
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)       # 행렬곱에 의해 bias size = (2,1)
b = torch.zeros(1, requires_grad=True)

# optimizer tjfwjd
optimizer = optim.SGD([W, b], lr=0.1)

# Training
nb_epochs = 1000
for epoch in range(nb_epochs + 1):

  # Cost 계산
  hypothesis = torch.sigmoid(x_train.matmul(W) + b)
  cost = -(y_train * torch.log(hypothesis) +
           (1 - y_train) * torch.log(1 - hypothesis)).mean()

  # cost로 H(x) 개선
  optimizer.zero_grad()
  cost.backward()
  optimizer.step()

  # 100번마다 결과 로그 출력
  if epoch % 100 == 0:
    print('Epoch {:4d}/{} Cost: {:.6f}'.format(
        epoch, nb_epochs, cost.item()
    ))

 

>>
Epoch    0/1000 Cost: 0.693147
Epoch  100/1000 Cost: 0.090324
Epoch  200/1000 Cost: 0.060941
Epoch  300/1000 Cost: 0.046890
Epoch  400/1000 Cost: 0.038272
Epoch  500/1000 Cost: 0.032367
Epoch  600/1000 Cost: 0.028045
Epoch  700/1000 Cost: 0.024738
Epoch  800/1000 Cost: 0.022125
Epoch  900/1000 Cost: 0.020007
Epoch 1000/1000 Cost: 0.018255                # Cost 값이 점점 줄어드는 것(0에 가까워짐) 확인. 학습 잘 됨

 

2. nn.Module로 모델 구현하기

 Pytorch에서는 nn.Sigmoid( )를 통해서 함수 구현하므로
 nn.Linear( )의 결과를 nn.Sigmoid( )를 거치게하면 Logisitic의 H(x)가 된다.

 

... Training Dataset까지 동일

# 모델 선언
model = nn.Sequential(        # nn.module의 층을 차례대로 쌓을 수 있도록 한다
    nn.Linear(2, 1),          # input(dim) = 2, ouput(dim) = 1
    nn.Sigmoid()              # 출력은 시그모이드 함수를 거친다
)

# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=1)

nb_epochs = 100
for epoch in range(nb_epochs + 1):

  # H(x) 계산
  hypothesis = model(x_train)       # train 데이터를 넣은 예측값

  # cost 계산 - 파이토치에서 기본 제공
  cost = F.binary_cross_entropy(hypothesis, y_train)
  # classification 문제이기 때문에 cross_entropy 사용
  # prediction과 y_train가 얼마나 같은지 계산!

  # cost로 H(x) 계산
  optimizer.zero_grad()
  cost.backward()
  optimizer.step()

  # 10번마다 결과 로그 출력
  if epoch % 10 == 0:
    prediction = hypothesis >= torch.FloatTensor([0.5])   # 예측값이 0.5를 넘으면 True
    correct_prediction = prediction.float() == y_train    # 실제값과 일치하는 경우만 True
    accuracy = correct_prediction.sum().item() / len(correct_prediction)    # 정확도 측정
    print('Epoch {:4d}/{} Cost: {:.6f} Accuracy: {:2.2f}%'.format(
        epoch, nb_epochs, cost.item(), accuracy * 100
    ))

 → nn.Sequential : nn.Module의 층을 차례대로 쌓을 수 있도록! 신경망 구현에 용이

 

>>
Epoch    0/100 Cost: 0.293817 Accuracy: 83.33%
Epoch   10/100 Cost: 0.053051 Accuracy: 100.00%
Epoch   20/100 Cost: 0.042111 Accuracy: 100.00%
Epoch   30/100 Cost: 0.035006 Accuracy: 100.00%
Epoch   40/100 Cost: 0.029974 Accuracy: 100.00%
Epoch   50/100 Cost: 0.026210 Accuracy: 100.00%
Epoch   60/100 Cost: 0.023283 Accuracy: 100.00%
Epoch   70/100 Cost: 0.020941 Accuracy: 100.00%
Epoch   80/100 Cost: 0.019024 Accuracy: 100.00%
Epoch   90/100 Cost: 0.017426 Accuracy: 100.00%
Epoch  100/100 Cost: 0.016073 Accuracy: 100.00%                    # Cost값이 줄어들고, 정확도 : 100%

 

3. Class로 모델 구현하기

 → 위와 다른 점은 모델을 클래스로 구현했다는 점!

 

... Training Dataset까지 동일

# 클래스 선언
class BinaryClassifier(nn.Module):                
  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))

# 생성한 클래스를 모델로 선언
model = BinaryClassifier()

... Training Part 위와 동일

 
 Class 형태의 모델은 nn.Module을 상속받는다.
 → _ init_( ) : 모델의 구조와 동적을 의미하는 생성자를 정의한다. (객체 생성되면 자동 호출)
 → super( ) : 이를 통해 만든 클래스는 nn.Module 클래스의 속성들을 가지고 초기화됨
 → forward( ) : 모델이 학습데이터를 입력받아서 forward 연산을 진행시키는 함수
        (model과 데이터를 함께 호출 시 실행)
   > forward 연산 : H(x) 수식에서 입력 x로부터 예측된 y를 얻어내는 과정

댓글