이전의 두 포스트에서는 데이터와 잘 맞는 직선을 찾는 linear regression을 했는데
예측 값이 떨어져 있다면 이 모델로는 예측이 어려울 것이다.
가장 대표적인 것이 binary classification인데 예측값이 0 또는 1이다.
이때 이 예측값을 확률로 표현한 다음 특정 값 이상이면 1 아니면 0으로 분류한다.
이러한 문제에 적용하는 방법이 Logistic Regression이다.
이론
logistic regression을 진행하기 위해서는 출력 값을 0과 1로 맞춰주어야 한다.
이를 위해 다음과 같은 logistic function을 사용한다.
입력 데이터를 x, 실제 class 값을 y, 예측된 출력 값을 y_hat이라 하면 x는 다음의 두 가지 변환을 거쳐 y_hat이 된다.
여기서 목표는 y와 y_hat을 가깝게 하는 w와 b를 찾는 것이다.
Logistic Function
logistic function을 그래프로 보면 다음과 같다.

z=0일 때 출력 값이 0.5이고, 양수일 때 1, 음수일 때 0으로 가까워지게 된다.
이렇게 z값을 0과 1 사이로 표현할 수 있게 되었다.
Data Making
이제 직접 데이터를 만들어서 진행해 보겠다.
x_data = numpy.linspace(-5, 5, 100)
w = 2
b = 1
#y = 2*x_data+1
numpy.random.seed(0) #시드를 고정하여 매번 같은 결과를 내도록
z_data = w * x_data + b + numpy.random.normal(size=len(x_data))#데이터에 noise 추가
y_data = 1 / (1+ numpy.exp(-z_data))
pyplot.scatter(x_data, y_data, alpha=0.4);

이제 실제 class 값을 정해주기 위해 where함수로 0.5보다 큰 값을 1, 작은 값을 0으로 변환하겠다.
y_data = numpy.where(y_data >= 0.5, 1, 0)
pyplot.scatter(x_data, y_data, alpha=0.4);

Cost Function
이제 y_hat과 실제 y가 가깝게 되도록 하는 w와 b를 찾으려면 cost function을 정의해야 한다.
전의 linear regression에는 MSE를 사용했지만 해당 함수는 convex(볼록함)한 형태기 때문에
아래와 같이 sigmoid function을 사용해서 convex하지 않게 만들어 준다.

하지만 이 함수의 최솟값을 gradient descent를 이용해 구하면 기울기가 0인 지점에서 멈추고
local minimum에 도달하게 된다.
그럼 cost function을 다시 생각해보아야 한다.
y=1인 경우 예측값이 1에 가깝길 바라지만 0에 가깝게 나왔다면 cost function의 값이 매우 커야 한다.
이를 만족시킬 수 있는 함수는 log를 이용해 만들 수 있다.
y값이 0 또는 1이기 때문에 다음과 같이 정리할 수 있다.
이 식이 logistic function에서 cost function이 된다.
Code
이제 이 전체 프로세스를 코드로 구현해보겠다.
우선 cost function을 정의하겠다.
w, b, x, y = sympy.symbols('w b x y')
logistic = 1/(1+ sympy.exp(-w*x-b)) # x를 0에서 1사이로 표현
Loss = -y*sympy.log(logistic) - (1-y)*sympy.log(1-logistic) # cost function
x변환, logistic 모델, cost function을 정의해보겠다.
from autograd import numpy
from autograd import grad
def logistic(z):
return 1 / (1 + numpy.exp(-z))
def logistic_model(params, x):
w = params[0]
b = params[1]
z = w * x + b
y = logistic(z)
return y
def log_loss(params, model, x, y):
y_pred = model(params, x)
return -numpy.mean(y * numpy.log(y_pred) + (1-y) * numpy.log(1 - y_pred))
기울기 계산을 위해서는 autograd를 통해서 gradient값을 구해보겠다.
numpy.random.seed(0)
params = numpy.random.rand(2) #parameter 초기화
gradient = grad(log_loss) # logistic loss 기울기를 계산하는 함수 정의
gradient(params, logistic_model, x_data, y_data) # 기울기 계산
# array([-0.42734877, 0.08274066])
w와 b에 대해 기울기를 구한다.
새로운 조건을 추가해서 5000번의 반복 수 외에 기울기 값이 0.001보다 작아지면 멈추도록 설정하겠다.
max_iter = 5000
i = 0
descent = numpy.ones(len(params))
while numpy.linalg.norm(descent) > 0.001 and i < max_iter:
descent = gradient(params, logistic_model, x_data, y_data)
params = params - descent * 0.01
i += 1
print('Optimized value of w is {} vs. true value: 2'.format(params[0]))
print('Optimized value of b is {} vs. true value: 1'.format(params[1]))
#evaluation metrics used in real world dataset
print('Exited after {} iterations'.format(i))
예측된 값을 plot 해보면 다음과 같다.

여기서 기준값을 0.5로 정하고 이것보다 크면 1, 작으면 0으로 분류를 하는 함수를 만들겠다.
def decision_boundary(y):
return 1 if y >= .5 else 0
모든 점을 함수에 넣어서 판단해야 하는데 오래 걸리기 때문에 numpy의 vectorize함수를 사용하겠다.
decision_boundary = numpy.vectorize(decision_boundary)
그래프로 데이터를 확인해보겠다.
def classify(predictions):
return decision_boundary(predictions)
final_predictions = classify(logistic_model(params, x_data))
pyplot.scatter(x_data, y_data, alpha=0.4,
label='true value')
pyplot.scatter(x_data, final_predictions, alpha=0.4,
label='prediciton')
pyplot.title('Score: [{}] / [{}]'.format(sum(final_predictions == y_data), len(y_data)))
pyplot.legend()
pyplot.show()

98퍼센트의 정확도로 예측을 했다.
다음 포스트에서는 실제의 데이터로 logistic regression을 해보겠다.
'Studying > Machine Learning' 카테고리의 다른 글
[머신러닝] Overfitting & Regularization (with Polynomial function) (0) | 2022.07.12 |
---|---|
[머신러닝] Logistic Regression - 타이타닉 탑승자 사망여부 예측 (0) | 2022.07.11 |
[머신러닝] Multiple Linear Regression - 연비(MPG) 예측 (0) | 2022.07.07 |
[머신러닝] Linear Regression - 지구 온도 변화 분석 (0) | 2022.07.05 |
[머신러닝] Linear regression(선형 회귀) 구현 (0) | 2022.07.05 |
댓글