🙄 로지스틱 회귀
➡ 로지스틱 회귀 (Logistic Regression)
- 데이터에 가장 잘 맞는 시그모이드 함수를 찾는 것
➡ 시그모이드 함수
- S(x)=1+e−x1
- 무조건 0과 1 사이의 결과를 냄
- e는 2.718이라는 양수
- S(∞)=1+e−∞1=1+01=1
- S(−∞)=1+e∞1=1+∞1=0
- x가 엄청나게 작으면 0에 가까워지고, x가 엄청나게 크면 1에 가까워짐
- 일차 함수는 결과가 얼마든지 작아질 수 있고 커질 수 있기 때문에 분류에 부적합
- 선형 회귀는 예외적인 데이터 하나에 가설 함수가 민감하게 반응
- 시그모이드 함수는 예외적인 데이터에 크게 영향을 받지 않음
- 0과 1 사이의 연속적인 값이기 때문에 로지스틱 분류가 아닌 로지스틱 회귀
- 주로 함수의 결괏값이 0.5보다 큰지 작은지 보고 분류
🙄 가설 함수
➡ 가설 함수
- 특정 데이터에 대해서 입력 변수를 받으면 목표 변수를 예측해 주는 함수
- 선형 회귀에서 썼던 아래의 가설 함수를 발전시키면 로지스틱 회귀의 가설 함수가 됨
- 로지스틱 회귀 가설 함수를 h로 표현하기 위해 g로 표현
θ = ⎣⎢⎢⎢⎢⎢⎢⎢⎡θ0θ1θ2..θn⎦⎥⎥⎥⎥⎥⎥⎥⎤
x = ⎣⎢⎢⎢⎢⎢⎢⎢⎡1x1x2..xn⎦⎥⎥⎥⎥⎥⎥⎥⎤
gθ(x)=θ0x0+θ1x1+θ2x2+...θnxn
gθ(x)=θTx
hθ(x)=1+e−gθ(x)1
hθ(x)=1+e−θTx1
- 선형 회귀에서 썼던 가설 함수 g의 아웃풋을 시그모이드 함수의 인풋으로 사용
- 아웃풋은 0과 1 사이의 어떤 수
🙄 손실 함수
➡ 로그 손실 (log-loss, cross entropy)
- 손실의 정도를 로그 함수로 결정하기 때문에 로그 손실
- 데이터에 잘 맞는 가설 함수를 찾기 위해 손실 함수를 이용해서 가설 함수를 평가
logloss(hθ(x),y)={−log(hθ(x))−log(1−hθ(x))y=1y=0
- 한 줄로 표현하면 아래와 같다
logloss(hθ(x),y)=−ylog(hθ(x))−(1−y)log(1−hθ(x))

➡ 로그 손실 함수
- 목표는 각 데이터에 대해서 손실을 구한 후, 손실의 평균을 내는 것
- J(θ)=m1∑i=1m[(logloss(hθ(x),y))]
- J(θ)=m1∑i=1m[−y(i)log(hθ(x(i)))−(1−y(i))log(1−hθ(x(i)))]
- θ 값들을 어떻게 설정하느냐에 따라 손실이 달라지므로 손실 함수의 인풋은 θ
🙄 경사 하강법
➡ 경사 하강법
- 가설 함수와 손실 함수는 다르지만, 경사 하강법을 하는 방법은 선형 회귀랑 동일
- θ 값들을 모두 0으로 지정하거나 모두 랜덤하게 지정
- θ0, θ1, θ2 3개가 있다고 가정한다면
θ0=θ0−α∂θ0∂J(θ)
θ1=θ1−α∂θ1∂J(θ)
θ2=θ2−α∂θ2∂J(θ)
- 손실 함수를 편미분하고, 그 결과에 학습률 알파를 곱한 뒤 기존 θ에서 뺀다
- 모든 θ를 업데이트하면 경사 하강을 한 번 했다고 할 수 있음
- 차이점은 손실 함수 J가 다르다는 것
- 하지만 편미분을 하면 선형 회귀랑 똑같은 식이 나옴
θj=θj−αm1∑i=1m(hθ(x(i))−y(i))∗xj(i)
- 선형 회귀랑 거의 똑같지만 유일하게 다른 건 가설 함수 h
- 선형 회귀 가설 함수는 일차 함수지만 로지스틱 회귀 가설 함수는 시그모이드 함수
- h에 시그모이드 함수를 대입해 각 θ 값을 업데이트
➡ 경사 하강법 간단하게 표현하기
- θ=θ−αm1(XT∗error)
➡ 경사 하강법 구현하기
import numpy as np
def sigmoid(x):
"""시그모이드 함수"""
return 1 / (1 + np.exp(-x))
def prediction(X, theta):
"""로지스틱 회귀 가정 함수"""
return sigmoid(X @ theta)
def gradient_descent(X, theta, y, iterations, alpha):
"""로지스틱 회귀 경사 하강 알고리즘"""
m = len(X)
for _ in range(iterations):
error = prediction(X, theta) - y
theta = theta - alpha / m * X.T @ error
return theta
hours_studied = np.array([0.2, 0.3, 0.7, 1, 1.3, 1.8, 2, 2.1, 2.2, 3, 4, 4.2, 4, 4.7, 5.0, 5.9])
gpa_rank = np.array([0.9, 0.95, 0.8, 0.82, 0.7, 0.6, 0.55, 0.67, 0.4, 0.3, 0.2, 0.2, 0.15, 0.18, 0.15, 0.05])
number_of_tries = np.array([1, 2, 2, 2, 4, 2, 2, 2, 3, 3, 3, 3, 2, 4, 1, 2])
passed = np.array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1])
X = np.array([
np.ones(16),
hours_studied,
gpa_rank,
number_of_tries
]).T
y = passed
theta = [0, 0, 0, 0]
theta = gradient_descent(X, theta, y, 300, 0.1)
theta
🙄 정규 방정식
➡ 정규 방정식
- 선형 회귀는 손실 함수 J(MSE)가
convex
(아래로 볼록) 할 뿐만 아니라, 편미분 원소들을 모두 선형식으로 나타낼 수 있기 때문에 정규 방정식 처럼 단순 행렬 연산만으로도 최적의 θ 값들을 구할 수 있음
- 로지스틱 회귀에서도 손실 함수 J (로그 손실)가 아래로 볼록해 경사 하강법을 사용하면 항상 최적의 θ 값들을 구할 수 있음
- 하지만 J에 대한 편미분 원소들이 선형식이 아님, θ가 e의 지수에 포함되어 있는데 지수로 포함된 식은 일차식으로만 표현하기가 불가능해 단순 행렬 연산만으로 최소 지점을 찾아낼 수 없음
🙄 scikit-learn으로 로지스틱 회귀
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import pandas as pd
wine_data = datasets.load_wine()
""" 데이터 셋을 살펴보는 코드
print(wine_data.DESCR)
"""
X = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)
y = pd.DataFrame(wine_data.target, columns=['Y/N'])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 5)
y_train = y_train.values.ravel()
logistic_model = LogisticRegression(solver = 'saga', max_iter = 7500)
logistic_model.fit(X_train, y_train)
y_test_predict = logistic_model.predict(X_test)
score = logistic_model.score(X_test, y_test)
y_test_predict, score