Python/[코칭스터디 9기] 인공지능 AI 기초 다지기

[인공지능(AI) 기초 다지기] 5. 딥러닝 핵심 기초 (7)

김초송 2023. 3. 9. 18:20

5) Logistic Regression (Logistic/Binary Classification)

 

- Computing Hypothesis

  • 어떤 값이 1일 확률 : P(x=1) = 1 - P(x=0)
  • 시그모이드 함수 : -는 0, +는 1에 가깝게 해주는 함수
  • 시그모이드 함수를 이용해서 H(x)가 0 과 1에 근사하도록 
    = P(x=1) 
  • H(x) = P(x=1;W) : H(x) 는 logistic regression 모델 parameter W가 주어졌을 때 x의 값이 1일 확률
    = 1 - P(x=0;W) : 1에서 W라는 weight parameter가 주어졌을 때 x가 0일 확률을 뺌

 

- Weight Update via Gradient Descent

  • weight parameter W에 대해서 미분한 것, gradient에 learning rate를 곱한 것을 W에서 뺌
    = gradient descent
  • gradient descent 가 최소화되는 방향으로 update

 

- Evaluation

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

# for reproducibility
torch.manual_seed(1)

# Training Data
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)

print(x_train.shape)
print(y_train.shape)
  • |x_data| = (6, 2) : m = 6, d = 2
    |y_data| = (6, )

# Hypothesis
print('e^1 equals: ', torch.exp(torch.FloatTensor([1])))

W = torch.zeros((2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

hypothesis = 1 / (1 + torch.exp(-(x_train.matmul(W) + b)))
  • W = torch.zeros((2, 1), requires_grad=True)
    : d = 2, gradient를 배울거라고 선언
  • hypothesis 는 위의 수식을 그대로 구현
    : x.matmul(W) = x * W = matmul(torch.matmul(x, W)
# 시그모이드 내장 함수
print('1/(1+e^{-1}): ', torch.sigmoid(torch.FloatTensor([1])))

hypothesis = torch.sigmoid(x_train.matmul(W) + b)

# Cost Function
losses = -(y_train * torch.log(hypothesis) + 
           (1 - y_train) * torch.log(1 - hypothesis))
print(losses)

cost = losses.mean()
print(cost)

# bce : 위에꺼 한 줄로
F.binary_cross_entropy(hypothesis, y_train)
  • H(x) = P(x=1;W) : W가 주어졌을 때 x가 1일 확률

# Whole Training Procedure

# 모델 초기화
W = torch.zeros((2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# optimizer 설정
optimizer = optim.SGD([W, b], lr=1)

nb_epochs = 1000
for epoch in range(nb_epochs+1):
    # cost 계산
    hypothesis = torch.sigmoid(x_train.matmul(W) + b)
    cost = F.binary_cross_entropy(hypothesis, y_train)
    
    # 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()
        ))
  • m >> 6 (6보다 훨씬 많음), d = 2
  • SGD를 가지고 W, b를 학습, learning rate 는 1
  • optimizer.zero_grad() : gradient 를 구해놓은게 있으면 0 으로 초기화 (중요!!)
  • cost.backward() : backpropagation 수행
  • optimizer.step() : gradient 를 사용하여 cost 를 minimize 하는 방향으로 W, b 업데이트
  • 결과 : cost 값 점점 감소

# Evaluation
hypothesis = torch.sigmoid(x_train.matmul(W) + b) # x_text
print(hypothesis[:5]) # P(x = 1)

prediction = hypothesis >= torch.FloatTensor([0.5])
print(prediction) # type : ByteTensor

# compare it with the correct labels
print(prediction)
print(y_train)

correct_prediction = prediction.float() == y_train
print(correct_prediction[:5])
  • hypothesis : i번째 x가 1일 확률들
  • 예측값의 정확도 측정
    : correct_prediction의 평균 = accuracy
  • prediction과 correct_prediction이 int(0 / 1)이 아니라 True / False 값으로 나옴

 

- Higher Implementation

class BinaryClassifier(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(8, 1) # W, b
        self.sigmoid = nn.Sigmoid() 
        
    def forward(self, x):
        return self.sigmoid(self.linear(x))
        
model = BinaryClassifier()
  • 8개 element 를 가진 1 dim -> 0인지 1인지 예측하는 모델

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

nb_epochs = 100
for epoch in range(nb_epochs + 1):
    hypothesis = model(x_train)
    
    cost = F.binary_cross_entropy(hypothesis, y_train)
    
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()
    
    if epoch % 10 == 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
        ))
  • model.parameters() : [W, b] = self.linear parameter 가 iteration 형태로 들어옴
  • SGD 로 optimizer 수행