본문으로 바로가기

4-5 로지스틱 회귀를 위한 뉴런 만들기

category AI 2020. 11. 18. 02:38
728x90
  • 모델의 성능 평가를 위한 훈련 세트와 테스트 세트

    • 훈련된 모델의 실전 성능을 일반화 성능(generalization performance)라 명명
    • 모델을 한번 학습한 데이터 세트로 모델 성능 테스트는 부적합
    • 올바른 모델 성능 측정을 위해 훈련 데이터 세트를 두 덩어리로 나누어 하나는 훈련, 하나는 테스트에 사용
    • 이를 훈련 세트(training set)와 테스트 세트(test set)이라 함

훈련 데이터 세트를 훈련 세트와 테스트 세트로 나누는 규칙

- 훈련 데이터 세트를 나눌 때는 테스트 세트보다 훈련 세트가 더 많아야 한다.
- 훈련 데이터 세트를 나누기 전에 양성, 음성 클래스가 훈련 세트나 테스트 세트의 어느 한쪽에 몰리지 않도록 한다.

 

  • 훈련 세트와 테스트 세트 나누기

    • 양성, 음성의 클래스가 고르게 분포 하도록 한다.
    • 둘중 하나의 비율이 과도한 차이가 날경우 학습이 부족하거나, 성능 측정에 문제 발생 가능성 존재


  • train_test_split() 함수로 훈련 데이터 세트 나누기
    • sklearn.model_selection모듈에서 train_test_split() 함수를 임포트
    • train_test_split() 함수는 기본적으로 3 대 1비율로 분할 해준다.
    • 후에 입력 데이터(x), 타깃 데이터(y)와 그 밖의 설정을 매개 변수로 지정
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y, test_size=0.2, random_state=42)
매개 변수 내용
stratify=y 훈련 데이터를 나눌 때 클래스 비율을 동일하게 한다.
클래스 비율이 불균형 할 경우 y첨자를 이용해 조정
test_size=0.2 test set에게 전체적인 분배 비율을 0.2(20%)만큼 조정한다는 의미
random_state=42 train_test_split()이 무작위로 데이터 세트를 섞은 후 나누기 대문에 섞은후 결과의 일관성을 위해 난수의 초기값을 지정

 

  • 결과 확인
print(x_train.shape, x_test.shape)

 

  • unique() 함수로 훈련 세트 타깃 확인
np.unique(y_train, return_counts=True)


로지스틱 회귀 구현

- 정방향으로 데이터가 흘러가는 과정(정방향 계산)

- 역방향으로 데이터가 흘러가는 과정(역방향 계산)

- 클래스 구현

class LogisticNeuron :
    def __init__(self) :
        self.w = None
        self.b = None
    
    def forpass(self, x) :
        z = np.sum(x * self.w) + self.b     # 직선 방정식 계산
        return z

    def backprop(self, x, err) :
        w_grad = x * err            # 가중치에 대한 그레디언트 계산
        b_grad = 1 * err            # 절편에 대한 그레디언트 계산
        return w_grad, b_grad

 

  • 특징
    • __init()__은 가중치와 절편을 미리 초기화 하지않는다
      • 나중에 입력데이터를 통해 특성 개수에 맞춰 조정
    • forpass()에 넘파이 사용
      • x * self.w에서 x와 w는 1차원 넘파이 배열임으로 넘파이 배열에 사칙 연산을 통해 자동으로 배열 요소끼리 연산
      • np.sun()을 이용해 요소를 모두 더한 값을 반환

훈련하는 메서드 구현

 

  • fit() 메서드 구현
    • 활성화 함수(activation()) 추가
    • 역방향 계산에는 로지스틱 손실 함수의도 함수 적용
    • 초기화 하지않은 가중치는 np.ones()으로 1로 초기화 절편은 0으로 초기화
def fit(self, x, y, epochs=100) :
        self.w = np.ones(x.shape[1])        # 가중치 초기화
        self.b = 0                          # 절편 초기화
        for i in range(epochs) :            # 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        # 절편 업데이트

 

  • activation() 메서드 구현
    • 시그모이드 함수 사용
    • 자연 상수의 지수 함수를 계산하는 넘파이의 np.exp()사용
    def activation(self, z) :
        a = 1 / (1+np.exp(-z))      # 시그모이드 계산
        return a

예측 메서드 구현

 

  • predict() 메서드 구현
    • forpass() 메서드는 여러 샘플을 한번에 예측할 때 여러번 호출함
    • 단점을 보완하기위해 predict() 메서드 사용
    • x가 2차원 배열로 전달 된다고 가정하고 구현
    • 입력값을 선형 함수, 활성화 함수, 임계 함수 순서로 통과시켜 예측값 도달
    def predict(self, x) :
        z = [self.forpass(x_i) for x_i in x]        # 선형 함수 적용
        a = self.activation(np.array(z))            # 활성화 함수 적용
        return a > 0.5                              # 계단 함수 적용

 


로지스틱 회귀 모델 훈련

 

  • 모델 훈련
    • 객체 생성 후 fit() 메서드 호출
neuron = LogisticNeuron()
neuron.fit(x_train, y_train)

 

  • 테스트 세트 사용해 모델 정확도 평가
    • 훈련 종료 후 모델에 테스트 세트를 이용해 예측값을 부여, 적중하는지 여부 비교
np.mean(neuron.predict(x_test) == y_test)

- predict()의 반환은 True나 False로 채워진 (m, ) 크기의 배열

- y_test는 0또는 1로 채워진 (m, ) 크기의 배열

- np.mean()을 이용해 평균을 계산한다.

- 결과의 0.82.....는 평가 비율 -> 약 82%의 적중률

- 이 적중률을 정확도(accuracy)라 함

728x90