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 수행