머신러닝 독학하기 - 로지스틱 회귀 구현

maintain·2020년 9월 16일
0

구현하기 전에

학습된 모델을 실전에 사용하기 위해서는 테스트 과정이 필요하고 성능이 검증된 뒤에 사용해야 합니다. 테스트 과정에 학습된 데이터를 또 사용할 수는 없습니다. 실 성능보다 낙관적으로 성능이 평가될 가능성이 높기 때문입니다. 그렇기 때문에 학습용 데이터와 테스트용 데이터를 데이터 분포가 유사하도록 분리하여 사용할 필요가 있습니다.

이 글에서는 유방암 데이터 세트를 사용합니다. 이 데이터를 학습용과 훈련용으로 나누어 보겠습니다. 우선 데이터를 가져옵시다.

from sklearn.datasets import load_breast_cancer
import matplotlib.pyplot as plt
import numpy as np
cancer = load_breast_cancer()

훈련 데이터를 나눠주기 위해서 train_test_split이라는 함수를 사용합니다. 이 함수엔 데이터와 타깃 그리고 추가 매개변수를 지정할 수 있습니다.

stratify : 데이터 비율을 균일하게 만들어줍니다. 결과들을 넘겨주면 됩니다.
test_size : 테스트 데이터의 비율입니다. 기본은 0.25입니다.
random_state : 무작위로 데이터를 섞을 때 사용하는 난수의 시드입니다.

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(
	cancer.data.shape, cancer.target.shape
	stratify = cancer.target.shape, test_size = 0.2, 	
	random_state = 42)

로지스틱 회귀 구현

# 로지스틱 회귀 유닛 구현
class LogisticUnit:
  def __init__(self):
    self.w = None
    self.b = None
    self.zmax = 0

  # 정방향 계산
  def forpass(self, x):
    z = np.sum(x * self.w) + self.b # np.sum은 행렬합을 계산함
    return z
  
  # 역방향 계산, 오차역전파
  def backprop(self, x, err):
    w_grad = x * err
    b_grad = 1 * err
    return w_grad, b_grad

  def activation(self, z):
    # a = 1 / (1 + np.exp(-z, dtype=np.float64)) 
    # np.exp는 자연상수 e의 지수함수
    # return a

    # exp에서 overflow가 발생해서 위 코드 대신
    # 데이터형의 가능한 최댓값을 대신 사용하였음
    # z < e^max
    # ln(z) < max
    z = -z
    if z > np.log(np.finfo(z.dtype).max):
      return 0.0
    else:
      return 1 / (1 + np.exp(z))
    
  # 훈련 메소드
  def fit(self, x, y, epochs=100):
    # 초기화
    self.w = np.ones(x.shape[1])
    self.b = 0

    for i in range(epochs):
      for x_i, y_i in zip(x, y):
        z = self.forpass(x_i) # 정방향 계산
        a = self.activation(z) # 활성화 함수 계산
        err = -(y_i - a) # 오차 계산
        w_grad, b_grad = self.backprop(x_i, err) # 오차역전파
        self.w -= w_grad
        self.b -= b_grad
  
  # 유닛의 예측 메소드, 데이터가 2차원 배열로 여러 케이스가 들어올 때
  def predict(self, x):
    z = [self.forpass(x_i) for x_i in x]
    a = list(map(lambda x: self.activation(x) > 0.5, z))  
    return np.array(a) # 계단 함수

테스트하기

unit.predict(x_test)
np.mean(unit.predict(x_test) == y_test)
# 0.8245614035087719

참고

정직하게 코딩하며 배우는 딥러닝 입문

이 글은 개인 공부 정리 목적으로 작성되었습니다. 오류가 있을 수도 있습니다.

0개의 댓글