로지스틱 회귀 구현 소스코드 예시

 

비교: 선형 회귀

 

선형회귀 구현 소스코드 예시

[1] 필요한 패키지 불러오기import numpy as np [2] 선형회귀 클래스 선언class LinRegression(): # 객체 초기화 메서드 __init__ def __init__(self, nDim, w=[]): # nDim: 입력 데이터의 차원 수(단순 선형회귀의 경우에는

drsuneamer.tistory.com

 

[1] 필요한 패키지 불러오기

import numpy as np

 

[2] 로지스틱 함수 및 이진 교차 엔트로피 함수

def sigmoid(x):
    return 1 / (1 + np.exp(-x)) # np.exp: exponential 함수

def binary_CE(y, y_hat):  # 이진 Cross Entropy 계산 위한 함수
    return -y * np.log(y_hat) - (1-y) * np.log(1-y_hat)

 

[3] 로지스틱 회귀 클래스 선언

class LogisticRegression():
    # 선형회귀의 __init__ 메소드와 동일
    def __init__(self, nDim, w=[]):
        self.nDim = nDim
        if len(w) > 0:
            self.w = np.array(w)
        else:
            self.w = np.random.rand(nDim+1)

    # 훈련을 하기 위한 메소드
    def fit(self, x, y, m, epochs, eta=0.01):
        cost = 0
        for i in range(m):
            y_hat = sigmoid(np.dot(self.w, x[i])) # 로지스틱 함수의 결과값을 예측값으로
            cost += binary_CE(y[i], y_hat)
        cost /= m # 평균
        print("Epochs = {:4d}".format(0), end='')
        for i in range(self.nDim+1):
            print("  w{} = {:.4f}".format(i, self.w[i]), end='')
        print("  cost = {:.6f}".format(cost))

        for j in range(1, epochs+1):
            dw = np.zeros(self.nDim + 1)    # dw 0으로 초기화
            for i in range(m):
                y_hat = sigmoid(np.dot(self.w, x[i]))
                err = y_hat - y[i]
                dw += err * x[i]  # 파라미터 업데이트, 교차 엔트로피에 해당하는 비용함수의 경사
            # 로지스틱 회귀 계수 업데이트
            self.w -= eta * dw / m
            # 20회 주기로 학습내용 출력
            if j % 20 == 0:
                cost = 0
                for i in range(m):
                    y_hat = sigmoid(np.dot(self.w, x[i]))
                    cost += binary_CE(y[i], y_hat)
                cost /= m
                print("Epochs = {:4d}".format(j), end="")
                for i in range(self.nDim+1):
                    print("  w{} = {:.4f}".format(i, self.w[i]), end="")
                print("  cost = {:.6f}".format(cost))

    def predict(self, x):
        return sigmoid(np.dot(self.w, x))

 

[4] 로지스틱 회귀를 위한 설정

nSamples = 6
nDim = 2  # 차수는 2차, x1, x2라는 축 가지므로 w0, w1, w2 세 개의 축 학습시켜야 함
nEpochs = 8000
eta = 0.01

 

[5] 독립변수와 종속변수 및 파라미터 초기화

# x : 독립변수([1, x]), y : 종속변수
x = np.array([[1,1, 1], [1, 2, 1], [1, 1, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3]])
y = np.array([0, 0, 0, 1, 1, 1])

# 로지스틱 회귀의 계수
w = np.array([0.5, -0.5, 1.0])  # 순서대로 w0, w1, w2

 

[6] 로지스틱 회귀 객체 생성 및 학습

logisticReg = LogisticRegression(2, w)  # 로지스틱 회귀 객체 생성
logisticReg.fit(x, y, nSamples, nEpochs, 0.01)

[6] 실행 결과

 

 

결과적으로 위와 같은 직선을 얻게 된다.

y_hat이 0.5보다 크면 1로, 0.5보다 작으면 0으로 예측한다.

 

[7] 학습된 모델을 이용한 예측 

# x = [2.5, 2.5]일 때의 y_hat
xx = np.array([1, 2.5, 2.5])
print("x = ({:.2f}, {:.2f}) --> y_hat = {:.3f}".format(xx[1], xx[2], logisticReg.predict(xx)))
# 1이 될 확률이 0.849

# x = [1.5, 1.5]일 때의 y_hat
xx = np.array([1, 1.5, 1.5])
print("x = ({:.2f}, {:.2f}) --> y_hat = {:.3f}".format(xx[1], xx[2], logisticReg.predict(xx)))

[7] 실행 결과