[PyTorch] Logistic Regression 실습 : 모두를 위한 딥러닝 시즌2
2024. 9. 5. 15:14ㆍArtificial Intelligence/모두를 위한 딥러닝 (PyTorch)
Logistic Regression 이론 요약

Logistic Regression 구현 코드
라이브러리 import & 시드값 고정
# Library import
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
# To ensure experiment reproducibility
torch.manual_seed(1)
데이터 정의
# Data definition
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) # (6, 2)
y_train = torch.FloatTensor(y_data) # (6,)
print(x_train.shape)
print(y_train.shape)
지수 함수로 Hypothesis 계산
# torch.exp function resembles the exponential function
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)))
print(hypothesis)
print(hypothesis.shape)
시그모이드 함수로 Hypothesis 계산
print('1 / (1+e^{-1}) equals: ', torch.sigmoid(torch.FloatTensor([1])))
hypothesis = torch.sigmoid(x_train.matmul(W) + b)
print(hypothesis)
print(hypothesis.shape)
Cost 계산 :
1. 하나의 Element에 대해 직접 계산
2. 전체 Batch에 대해 직접 계산
3. BCE 함수로 계산
print(hypothesis)
print(y_train)
## Computing the Cost function
# 1. Calculate Cost for one element
-(y_train[0] * torch.log(hypothesis[0]) +
(1 - y_train[0]) * torch.log(1 - hypothesis[0]))
# 2. Calculate Cost for the entire batch
losses = -(y_train * torch.log(hypothesis) +
(1 - y_train) * torch.log(1 - hypothesis))
print(losses)
cost = losses.mean()
print(cost)
# 3. Calculate Cost with BCE function
F.binary_cross_entropy(hypothesis, y_train)
Sigmoid 함수와 BCE 함수를 활용한 학습
# Initialize model
W = torch.zeros((2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# Optimizer definition
optimizer = optim.SGD([W, b], lr=1)
nb_epochs = 1000
for epoch in range(nb_epochs + 1):
# Calculate Cost
hypothesis = torch.sigmoid(x_train.matmul(W) + b) # or .mm or @
cost = F.binary_cross_entropy(hypothesis, y_train)
# Gradient Descent
optimizer.zero_grad()
cost.backward()
optimizer.step()
# Log every 100 iterations
if epoch % 100 == 0:
print('Epoch {:4d}/{} Cost: {:.6f}'.format(
epoch, nb_epochs, cost.item()
))
모델 평가: 예측값과 실제값 비교 & Accuracy 계산
import numpy as np
# Evaluation of the model
hypothesis = torch.sigmoid(x_train.matmul(W) + b)
# # TypeError: set_printoptions() got an unexpected keyword argument 'sci_mode'
# torch.set_printoptions(precision=4, sci_mode=False)
# print(hypothesis[:5])
hypothesis_np = hypothesis[:5].detach().numpy()
np.set_printoptions(precision=4, suppress=True) # suppress=True는 지수 표기법 비활성화
print(hypothesis_np)
# Compare Predicted value and Real value
prediction = hypothesis >= torch.FloatTensor([0.5])
print(prediction[:5]) # Predicted value
print(y_train[:5]) # Real value
# Accuracy
correct_prediction = prediction.float() == y_train
print(correct_prediction[:5])
BinaryClassifier(Rogistic Regression) 클래스를 활용한 전체 코드
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()
optimizer = optim.SGD(model.parameters(), lr=1)
nb_epochs = 100
for epoch in range(nb_epochs + 1):
# Calculate H(x)
hypothesis = model(x_train)
# Calculate Cost
cost = F.binary_cross_entropy(hypothesis, y_train)
# Gradient Descent
optimizer.zero_grad()
cost.backward()
optimizer.step()
# Log every 100 iterations
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
))
실행 결과 분석
우선 첫 번째 학습 결과는 1000번의 iteration을 거쳐, Cost가 약 0.02로 감소했다. 두 번째 학습 결과는 100번의 iteration을 거쳐 약 0.129로 감소했으며, 예측 정확도는 점점 증가하다가 100%를 달성했다.


느낀 점
- 매번 다른 랜덤 값을 생성하지 않도록 시드값을 고정함으로써, 재현이 가능하게 함을 알게 되었다.
- 이전 강의에서는 가설과 비용 계산을 중심으로 다루었다면, 이번 강의에서는 모델에 대한 성능 평가를 추가로 배울 수 있어서 좋았다. 실제값과 예측값을 출력해서 직접 비교해 보니, 정확도를 계산하는 이유가 더 와닿았다.
- 강의에 나온 코드를 분명히 똑같이 작성했는데, 내 코드의 텐서 출력 형태가 지수 표기법을 따르고 있었다. 그래서 set_printoptions로 지수 표기법을 비활성화하는 방법을 사용했다. torch의 sci_mode 옵션에서 에러가 발생하여, 텐서를 numpy로 변환한 후 'suppress=True' 옵션으로 지수 표기법을 비활성화했다. 파이토치 공식 문서는 torch의 sci_mode를 사용할 수 있다는데, 왜 에러가 발생했는지 너무 궁금하다.
*참고 자료
모두를 위한 딥러닝 시즌2 - [PyTorch] Lab-05 Logistic Regression
https://youtu.be/HgPWRqtg254?feature=shared