학습된 모델을 실전에 사용하기 위해서는 테스트 과정이 필요하고 성능이 검증된 뒤에 사용해야 합니다. 테스트 과정에 학습된 데이터를 또 사용할 수는 없습니다. 실 성능보다 낙관적으로 성능이 평가될 가능성이 높기 때문입니다. 그렇기 때문에 학습용 데이터와 테스트용 데이터를 데이터 분포가 유사하도록 분리하여 사용할 필요가 있습니다.
이 글에서는 유방암 데이터 세트를 사용합니다. 이 데이터를 학습용과 훈련용으로 나누어 보겠습니다. 우선 데이터를 가져옵시다.
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
이 글은 개인 공부 정리 목적으로 작성되었습니다. 오류가 있을 수도 있습니다.