머신 러닝 – 로지스틱 회귀

안녕하세요. 언제나휴일입니다.

앞에서 KNN 회귀, KNN 분류, 경사하강법을 이용한 회귀를 알아보았어요.

이번에는 로지스틱 회귀를 알아볼 거예요.

먼저 로지스틱 회귀가 무엇인지 소개한 후에 직접 만들어 볼게요.

사이킷 런의 로지스틱 회귀 모델을 사용하는 것은 좀 더 나은 학습하기 좋은 데이터를 가지고 다음에 알아볼게요.

로지스틱 회귀란?
로지스틱 회귀 모델 만들기
사이킷 런의 로지스틱 회귀 모델 사용하기

1. 로지스틱 회귀란?

로지스틱 회귀(Logistic Regression)는 독립 변수에 의해 종속 변수(사건)이 발생할 확률을 예측하는 통계 모델입니다.

특정 사건이 발생할 것인지 아닌지 확률을 구하는 것이죠.

전반적인 방법은 선형 회귀와 비슷하며 단지 로지스틱 회귀 함수를 통해 확률 값으로 변화를 주는 차이가 있습니다.

로지스틱 회귀 함수는 sigmoid라고도 불리는 함수로 수식은 다음과 같습니다.

f(x) =1/(1+e-x )

코드로 작성하면 다음과 같습니다.

import numpy as np
def sigmoid(x):      
  return 1 / (1 + np.e**(-x))

이를 도표로 표시하면 다음과 같습니다.

import matplotlib.pyplot as plt
xs = range(-10,10) 
ys = [sigmoid(x) for x in xs]
plt.plot(xs,ys,marker='.')
plt.axvline(x=0,color='black') 
plt.axhline(y=0,color='red') 
plt.axhline(y=1,color='green') 
plt.title('sigmoid function(logistic function)')
plt.show()
sigmoid 함수
sigmoid 함수

sigmoid 함수를 사용하면 0에서 1 사이의 값으로 회귀합니다.

0이면 발생할 확률이 없는 것이고 1이면 100%라고 볼 수 있어요.

2. 로지스틱 회귀 모델 만들기

이제 로지스틱 회귀 모델을 간단하게 만들어 봅시다.

경사하강법을 이용한 선형 회귀에서 만들었던 것과 비슷합니다.

경사(미분)를 계산할 때 sigmoid 함수를 적용하는 것에서 차이가 있어요.

def gradient(y,x,w,b):
  wd = x*(sigmoid(w*x + b) - y)
  bd = sigmoid(w*x + b) - y
  return wd,bd

경사 하강법은 선형회귀 모델과 같은 방법으로 적용합니다.

def gradient_descent(xs,ys,lr=0.001,epochs=100):
  if isinstance(xs,list): #xs 형식이 리스트일 때
    xs = np.array(xs).reshape(-1) #numpy 배열로 변경하고 1차원으로 구조 변경
  wbhl=[] #학습 과정에서의 가중치와 편향을 보관하기 위함
  
  wp = np.random.uniform(-1,1) #초기 가중치
  bp = np.random.uniform(-1,1) #초기 편향
  
  for epoch in range(epochs): 
    for i,x in enumerate(xs):    
      wd,bd = gradient(ys[i],x,wp,bp)#경사를 구함    
      wp = wp - (wd*lr) #가중치를 경사*lr만큼 빼기
      bp = bp - (bd*lr) #편향을 경사*lr만큼 빼기     
    wbhl.append([wp,bp]) #가중치와 편향을 보관
  return wp, bp, wbhl #가중치, 편향, 히스토리 반환

학습 시킨 후에 학습 과정을 도표로 표시해 봅시다.

xs = np.arange(-10,10,0.3)
ys = np.array([0 if x>0 else 1 for x in xs])

wb, bp, wbhl = gradient_descent(xs,ys,epochs=1000)
min_val = min(min(xs),min(ys))
max_val = max(max(xs),max(ys))

for wi in range(0,len(wbhl),50):
  wb = wbhl[wi]
  pre_ys = [sigmoid(wb[0]*x + wb[1]) for x in xs]
  plt.figure(figsize=(6,6))
  
  plt.plot(xs,ys,'b^',label='actual')
  plt.plot(xs,pre_ys,'r.',label=f"epoch:{wi} predict")
  plt.axvline(x=0,color='black') 
  plt.axhline(y=0,color='black') 
  
  plt.xlim(min_val,max_val)
  plt.ylim(min_val,max_val)
  plt.legend()  
  plt.show()

다음은 출력하는 도표의 일부입니다.

epoch 0
epoch 0
epoch 1
epoch 1
epoch 2
epoch2
epoch 50
epoch50
epoch final
epoch final

3. 사이킷 런의 로지스틱 회귀 모델 사용하기

독립 변수를 사이킷 런에서 사용할 수 있게 변경할게요.

xs2 = [[x] for x in xs]

학습용 데이터와 테스트 데이터로 구분합시다.

from sklearn.model_selection import train_test_split
train_xs,test_xs, train_ys,test_ys = train_test_split(xs2,ys)

사이킷 런의 로지스틱 회귀 모델은 선형 모델의 LogisticRegression으로 정의하고 있어요.

from sklearn.linear_model import LogisticRegression
lr_model = LogisticRegression(solver='liblinear')

학습에 fit 메서드를 사용합니다.

예측할 때는 predict, 평가할 때 score를 사용할 수 있어요.

여기에서는 학습 후에 평가하기로 할게요.

lr_model.fit(train_xs,train_ys)
print(f"score:{lr_model.score(test_xs,test_ys)}")

여기서 사용한 데이터는 너무나 직관적인 데이터라 평가 점수는 1.0(100점)입니다.