반응형

로지스틱 회귀 ( Logistic Regression)

* 선형 방적식을 사용한 분류 알고리즘

* 선형 회귀와 달리 시그모이드 함수나 소프트 맥스 함수를 사용하여 클래스 확률을 출력

* 로지스틱 회귀는 다중 분류를 위해 소프트맥스 함수를 사용하여 클래스를 예측

 

로지스틱 회귀에서 이진 분류 확률을 출력하기

로지스틱 회귀에서 이진 분류 확률을 출력하기 위해서는 시그모이드 함수(Sigmoid function)을 사용해야한다.

 

샘플 데이터를 사용하여 로지스틱 회귀를 위한 시그모이드 함수를 사용해보겠습니다.

 

 

"""# 데이터 준비 """

import pandas as pd

fish = pd.read_csv('https://bit.ly/fish_csv_data')
fish.head()

 

샘플 csv 파일을 불러와서 데이터 프레임으로 변환 후 처음 5개 행을 출력

 

시그 모이드 함수 식

시그모이드 함수 그래프

 

시그모이드 선형 방정식의 출력 z의 음수를 사용해 자연상수  e를 거듭제곱하고 1을 더한 값의 역수를 취함

시그모이드 함수가 이렇게 복잡하게 계산한 이유는 아래 시그 모이드 함수 그래프를 만들 수 있기 때문이다.

 

z가 무한하게 큰 음수일 경우 이 함수는 0에 가까워지고, z가 무한하게 큰 양수가 될 때는 1에 가까워진다. z가 0일 경우 0.5이다. z가 어떤 값이 되더라도 결과는 전대로 0~1 사이의 범위를 벗어날수 없다. 그렇다면 0~100%까지 확률로 해석할 수 있다. 

import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-5, 5, 0.1)
phi = 1 / (1 + np.exp(-z))

plt.plot(z, phi)
plt.xlabel('z')
plt.ylabel('phi')
plt.show()

 

준비한 샘플 데이터를 가지고 로지스틱 회귀로 이진 분류를 수행

 

불리언 인덱싱을 적용해서 훈련 세트에서 도미와 빙어의 행만 골라내기

bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_target[bream_smelt_indexes]

 

분리한 도미와 빙어 데이터로 로지스틱 회귀 모델을 훈련

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)

 

훈련한 모델을 사용해서 train_bream_smelt에 있는 처음 5개의 샘플을 예측

print(lr.predict(train_bream_smelt[:5]))
==> result : ['Bream' 'Smelt' 'Bream' 'Bream' 'Bream']

predict_proba() 메서드를 사용하여 처음 5개 샘플의 예측 확률을 출력

print(lr.predict_proba(train_bream_smelt[:5]))
==> result : 
[[0.99759855 0.00240145]
 [0.02735183 0.97264817]
 [0.99486072 0.00513928]
 [0.98584202 0.01415798]
 [0.99767269 0.00232731]]

첫번째 열이 음성 클래스에 대한 확률이고, 두번째 열이 양성 클래스에 대한 확률

 

어떤것이 음성 클래스이고 어떤것이 양성 클래스인지 확인

print(lr.classes_)
==> result : 
['Bream' 'Smelt']

도미가 음성, 빙어가 양성 클래스

 

 

에포크와 과대/과소적합

확률적 경사 하강법을 사용한 모델은 에포크 횟수에 따라 과소적합이나 과대적합이 될 수 있다.

 

* 이런 현상이 발생하는 이유

** 적은 에포크 횟수 동안에 훈련한 모델은 훈련 세트와 테스트 세트에 잘 맞지 않는 과소적합된 모델일 가능성이 높음

** 많은 에포크 횟수 동안에 훈련한 모델은 훈련 세트에 너무 잘 맞아 테스트 세트에는 오히려 점수가 나쁜 과대적합된 모델일 가능성이 높음

 

과대 / 과소 적합을 위한 데이터 준비

import pandas as pd

fish = pd.read_csv('https://bit.ly/fish_csv_data')

fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_target = fish['Species'].to_numpy()

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(
    fish_input, fish_target, random_state=42)

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)

 

 

* 훈련이 진행되는 동안 fit() 메서드가 아닌 partial_fit() 메서드만 사용

* np.unique() 함수로 train_target에 있는 7개의 생선의 목록을 생성

* 에포크마다 훈련 세트와 테스트 세트에 대한 점수를 기록하기 위해 2개의 리스트를 준비

from sklearn.linear_model import SGDClassifier
import numpy as np

sc = SGDClassifier(loss='log', random_state=42)

train_score = []
test_score = []

classes = np.unique(train_target)

 

 

* 300번의 에포크 동안 훈련을 반복 진행

* 매 반복마다 훈련 세트와 테스트 세트의 점수를 계산하여 train_score, test_score에 추가

* 300번의 에포크 동안 기록한 훈련 세트와 테스트 세트의 점수를 그래프로 표시

for _ in range(0, 300):
    sc.partial_fit(train_scaled, train_target, classes=classes)
    train_score.append(sc.score(train_scaled, train_target))
    test_score.append(sc.score(test_scaled, test_target))

import matplotlib.pyplot as plt

plt.plot(train_score)
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()

 

백번째 에포크 이후에 훈련 세트와 테스트 세트의 점수가 조금씩 벌어짐

에포크 초기에는 과소적합되어 훈련세트와 테스트 세트의 점수가 낮음

해당 모델의 경우 백번째 에포크가 적절한 반복횟수로 보임

 

* SGDClassifier의 반복 횟수를 100에 맞추고 모델을 다시 훈련

* 최종적으로 테스트 세트와 훈련세트에서 점수를 출력

sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
sc.fit(train_scaled, train_target)

print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))

==> result : 
0.957983193277311
0.925

SGDClassifier는 일정 에포크 동안 성능이 향상되지 않으면 더 훈련하지 않고 자동으로 멈춤

 

tol 매개변수에서 향상될 최소값을 지정. None으로 지정하여 자동으로 멈추지 않고 max_iter=100 만큼 무조건 반복

 

 

** 추가 **

SGDClassifier의 loss 매개변수의 기본값은 hinge이다.

힌지 손실은 서포트 벡터 머신이라 불리는 또 다른 머신러닝 알고리즘을 위한 손실 함수

 

반응형

+ Recent posts