회귀분석을 이용해 출력값이 확률(0~1 사이)로 주어지는 분류를 수행할 수는 없을까?
우선, '로짓 변환(Logit Function)'을 활용하면, '확률()'의 개념을 들이면서도 좌변과 우변의 범위를 동일하게 구간으로 맞출 수 있겠구나!
# 로짓 변환 실습
import numpy as np
def logit(prob):
return np.log(prob / (1-prob))
prob = np.linspace(0, 1, 10)
z = logit(prob)
print(z)
## 출력 결과
# [-inf -2.07944154 -1.25276297 -0.69314718 -0.22314355 0.22314355 0.69314718 1.25276297 2.07944154 inf]
그리고, 회귀분석식에 대응되는 확률()을 구해내려면 '시그모이드 함수(Sigmoid Function)'도 함께 활용하면 되겠구나!
# 시그모이드 함수 실습
def sigmoid(z):
return 1 / (1 + np.exp(-z))
prob_recovered = sigmoid(z)
print(prob_recovered)
## 출력 결과
# [0. 0.11111111 0.22222222 0.33333333 0.44444444 0.55555556 0.66666667 0.77777778 0.88888889 1.]
손실함수인 '음의 로그-우도 함수(Negative Log-Likelihood; NLL)'를 최소화하는 를 효율적으로 찾기위해 경사하강법을 사용함
초기화: 을 임의의 값으로 초기화(통상적으로 0)
편미분 계산: 손실 함수 의 각 계수에 대한 편미분 계산
업데이트: 각 계수를 업데이트하며 손실함수가 충분히 작아질 때까지'편미분 계산-업데이트' 과정 반복
, (=학습률)
import numpy as np
# 시그모이드 함수
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 손실 함수
def loss_function(y, y_pred):
return -np.mean(y * np.log(y_pred) + (1 - y) * np.log(1 - y_pred))
# 경사하강법 구현
def logistic_regression(X, y, lr=0.01, epochs=1000):
# 최초 초기화(0으로 초기화)
m, n = X.shape
beta = np.zeros(n)
for _ in range(epochs):
# 예측
z = np.dot(X, beta)
y_pred = sigmoid(z)
# 편미분
gradient = np.dot(X.T, (y_pred - y)) / m
# 계수 업데이트
beta -= lr * gradient
# 100 단위마다 손실함수 값 출력
if _ % 100 == 0:
print(f"Epoch {_}: Loss = {loss_function(y, y_pred):.4f}")
return beta
# 독립변수(첫 열은 절편)
X = np.array([[1, 2], [1, 3], [1, 4], [1, 5]])
# 종속변수
y = np.array([0, 0, 1, 1])
# 로지스틱 회귀 분석 실시
coefficients = logistic_regression(X, y)
print("회귀 계수:", coefficients)
## 출력 결과
# Epoch 0: Loss = 0.6931
# Epoch 100: Loss = 0.6445
# Epoch 200: Loss = 0.6294
# Epoch 300: Loss = 0.6150
# Epoch 400: Loss = 0.6011
# Epoch 500: Loss = 0.5878
# Epoch 600: Loss = 0.5750
# Epoch 700: Loss = 0.5627
# Epoch 800: Loss = 0.5509
# Epoch 900: Loss = 0.5396
# 회귀 계수: [-1.07106719 0.42792742]
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 가상 데이터 생성
df = pd.DataFrame({
"X1": [2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2.7, 1.6],
"X2": [1, 0, 1, 0, 1, 1, 0, 1],
"y": [1, 0, 1, 0, 1, 1, 0, 0]
})
X = df[["X1", "X2"]]
y = df["y"]
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 계수 정보 확인 (기능 한정)
print(model.intercept_)
print(model.coef_)
import statsmodels.api as sm
# 데이터 재생성
X = df[["X1", "X2"]]
X = sm.add_constant(X) # Statsmodels는 절편 추가작업 필요
y = df["y"]
# 모델 생성 및 학습
model = sm.Logit(y, X)
result = model.fit()
# 상세 결과 확인
print(result.summary())
*이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.