본문 바로가기

대외활동/ABC 지역주도형 청년 취업역량강화 ESG 지원산업

[ABC 220923] 지도 학습 알고리즘 - 분류형 선형 모델

반응형

분류형 선형 모델

  • 선형 모델은 분류에도 널리 사용 → ex) 이진 분류 (binary classification)
    • 분류용 선형 모델에서는 결정 경계가 입력의 선형 함수
    • (이진) 선형 분류기는 선, 평면, 초평면을 사용해서 두 개의 클래스를 구분하는 분류기
  • 선형 모델을 학습시키는 알고리즘 두 가지 방법
    • 특정 계수와 절편의 조합이 훈련 데이터에 얼마나 잘 맞는지 측정하는 방법
    • 사용할 수 있는 규제가 있는지, 있다면 어떤 방식인지
    • 불행하게도 수학적이고 기술적인 이유로, 알고리즘들이 만드는 잘못된 분류의 수를 최소화하도록 w와 b를 조정하는 것은 불가능
  • 가장 널리 알려진 두 개의 선형 분류 알고리즘
    • linear_model.LogisticRegression 구현된 로지스틱 회귀 logistic regression
    • svm.LinearSVC(SVC ; support vector classifier) 구현된 선형 서포트 벡터 머신 support vector machine
  • 분류형 선형 모델 - 로지스틱 회귀, 서포트 벡터 머신
    • forge 데이터셋을 사용하여 LogisticRegression과 LinearSVC 모델들이 만들어낸 결정 경계를 그래프로 비교
      • forge 데이터 셋의 첫 번째 특성을 x 축, 두 번째 특성 y 축
      • 회귀에서 본 Ridge와 마찬가지로 이 두 모델은 기본적으로 L2 규제를 사용

 

선형 분류 모델 로지스틱 회귀

mglearn 라이브러리 설치

pip install mglearn

한글 깨짐 방지

import matplotlib as mpl
import matplotlib.pyplot as plt
 
%config InlineBackend.figure_format = 'retina'
 
!apt -qq -y install fonts-nanum
 
import matplotlib.font_manager as fm
fontpath = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf'
font = fm.FontProperties(fname=fontpath, size=9)
plt.rc('font', family='NanumBarunGothic') 
mpl.font_manager._rebuild()

선형 분류 모델의 C(규제) 설정에 따른 결정 경계

import mglearn
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

import warnings
warnings.filterwarnings('ignore')

plt.rc('font', family ='NanumBarunGothic')
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi']  = 100

X, y = mglearn.datasets.make_forge()

fig, axes = plt.subplots(1, 2, figsize=(10, 3))

for model, ax in zip([LinearSVC(max_iter=5000), LogisticRegression()], axes):
    clf = model.fit(X, y)
    mglearn.plots.plot_2d_separator(clf, X, fill=False, eps=0.5,
                                    ax=ax, alpha=.7)
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
    ax.set_title(clf.__class__.__name__)
    ax.set_xlabel("특성 0")
    ax.set_ylabel("특성 1")
axes[0].legend()
plt.show()
# overfitting 형태의 모델일 수 있다.

# C 규제(공부를 덜 시키겠다 -> 과대 적합을 피하겠다) 설정 값, 디폴트 값은 1이다.
# C 설정 값이 낮으면 ex) 0.01, 0.001 -> 규제를 높힘 -> 일반화 -> 너무 규제하면 과소 적합될 가능성이 있음
# C 설정 값이 높으면 ex) 10, 100, 1000 -> 규제가 완화 -> 과대 적합이 될 가능성이 있다

# C 설정값에 따라서 결정 경계가 얼마나 rough하게 or tight하게 그려지는지 확인할 수 있는 코드
mglearn.plots.plot_linear_svc_regularization()

유방암 데이터셋을 사용한 로지스틱 회귀(LogisticRegression) 성능 평가

  • 규제 강도를 결정하는 C 설정에 따른 성능 비교
  • 기본 C=1, ex) 규제 완화 C=0.01, 규제를 완화 C=100

데이터 준비하기

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

# 데이터 가져오기
cancer = load_breast_cancer()

# 데이터셋 분리하기
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, 
                                                    stratify=cancer.target, # target을 기준으로 비율이 동등하게 나누라는 명령어(비율 보정)
                                                    random_state=7)
# 569건 -> 75% -> 426건
X_train.shape

# 569건 -> 25% -> 143건
X_test.shape

모델 설정하기

from sklearn.linear_model import LogisticRegression

# C=1
logreg = LogisticRegression()

모델 학습하기

logreg.fit(X_train, y_train)

LogisticRegression C=1(기본), 규제 L2 모델 성능 평가

print('logreg 훈련 세트 점수 : {:.8f}'.format(logreg.score(X_train, y_train)))
print('logreg 테스트 세트 점수 : {:.8f}'.format(logreg.score(X_test, y_test)))

# 기본
logreg = LogisticRegression().fit(X_train, y_train)
print('logreg 훈련 세트 점수 : {:.8f}'.format(logreg.score(X_train, y_train)))
print('logreg 테스트 세트 점수 : {:.8f}'.format(logreg.score(X_test, y_test)))
print('----------------------------------------------')
# 규제 강화
logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print('logreg001 훈련 세트 점수 : {:.8f}'.format(logreg001.score(X_train, y_train)))
print('logreg001 테스트 세트 점수 : {:.8f}'.format(logreg001.score(X_test, y_test)))
print('----------------------------------------------')
# 규제 완화
logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print('logreg100 훈련 세트 점수 : {:.8f}'.format(logreg100.score(X_train, y_train)))
print('logreg100 테스트 세트 점수 : {:.8f}'.format(logreg100.score(X_test, y_test)))
# 완화시킨 모델을 사용해야한다
# 일반화된 모델을 만든다는 것은 훈련 셋과 테스트 셋의 격차가 가장 조금인 모델이 일반화가 되었다는 의미이다.
# 훈련할때나 테스트 할 때의 격차가 가장 적은 (언제나 잘하는 애) 모델을 선택해야 한다.

# L2 규제에 대한 feature들의 가중치를 확인

plt.plot(logreg100.coef_.T, '^', label="C=100")
plt.plot(logreg.coef_.T, 'o', label="C=1")
plt.plot(logreg001.coef_.T, 'v', label="C=0.01")
plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
xlims = plt.xlim()
plt.hlines(0, xlims[0], xlims[1])
plt.xlim(xlims)
plt.ylim(-5, 5)
plt.xlabel("특성")
plt.ylabel("계수 크기")
plt.legend()
plt.show()

L1 규제에 따른 성능 평가

# 기본
logreg= LogisticRegression(penalty='l1', solver='liblinear').fit(X_train, y_train)
print('logreg 훈련 세트 점수 : {:.8f}'.format(logreg.score(X_train, y_train)))
print('logreg 테스트 세트 점수 : {:.8f}'.format(logreg.score(X_test, y_test)))
print('----------------------------------------------')
# 규제 강화
logreg001 = LogisticRegression(C=0.01, penalty='l1', solver='liblinear').fit(X_train, y_train)
print('logreg001 훈련 세트 점수 : {:.8f}'.format(logreg001.score(X_train, y_train)))
print('logreg001 테스트 세트 점수 : {:.8f}'.format(logreg001.score(X_test, y_test)))
print('----------------------------------------------')
# 규제 완화
logreg100 = LogisticRegression(C=100, penalty='l1', solver='liblinear').fit(X_train, y_train)
print('logreg100 훈련 세트 점수 : {:.8f}'.format(logreg100.score(X_train, y_train)))
print('logreg100 테스트 세트 점수 : {:.8f}'.format(logreg100.score(X_test, y_test)))

# L1에 대한 feature들의 가중치를 확인

plt.plot(logreg100.coef_.T, '^', label="C=100")
plt.plot(logreg.coef_.T, 'o', label="C=1")
plt.plot(logreg001.coef_.T, 'v', label="C=0.01")
plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
xlims = plt.xlim()
plt.hlines(0, xlims[0], xlims[1])
plt.xlim(xlims)
plt.ylim(-5, 5)
plt.xlabel("특성")
plt.ylabel("계수 크기")
plt.legend()
plt.show()

LIST