#!/usr/bin/env python3


Logistic Regression[1]


Logistic Regression의 공식은 아래와 같습니다.

formula = ŷ = w[0] * x[0] + w[1] * x[1] + … + w[p] * x[p] + b > 0


Linear Regression와 매우 비슷하지만 가중치(w) 합을 사용하는 대신 예측한 값을 critical value 0 과 비교합니다.

함수에서 계산한 값이 0보다 작으면 class를 -1, 0보다 크면 +1이라고 예측합니다.


이 규칙은 Classifier에 쓰이는 모든 Linear model에서 동일합니다.


가장 널리 알려진 두 개의 linear classifier algorithm은

1. Logistic Regression

2. Support Vector Classifier의 Linear SVC입니다.


이해를 돕기 위해 LogisticRegression과 LinearSVC model를 인위적 데이터인 forge 데이터셋을 분석해보겠습니다.

from mglearn.plots import plot_2d_separator

from mglearn.datasets import make_forge

import matplotlib.pyplot as plt

from sklearn.linear_model import LogisticRegression

from sklearn.svm import LinearSVC

import numpy as np


x, y = make_forge()


_, axes = plt.subplots(1, 2)

models = [LogisticRegression(), LinearSVC()]


for model, axe in zip(models, axes.ravel()):

    clf = model.fit(x, y)

    plot_2d_separator(clf, x, fill=True, eps=0.5, ax=axe, alpha=0.5) # eps: epsilon, ax:그림객체


    idx_set = []

    for i in np.unique(y):

        idx = np.where(y==i)[0] # np.where는 array의 index를 출력결과를 tuple형태로 리턴합니다.

        idx_set.append(idx)


    axe.scatter(x[idx_set[0]][:, 0], x[idx_set[0]][:, 1],

                label='class {}'.format(1), s=40, marker='^', edgecolors='k')

    axe.scatter(x[idx_set[1]][:, 0], x[idx_set[1]][:, 1],

                label='class {}'.format(2), s=40, edgecolors='k')

    axe.set_title('{}'.format(clf.__class__.__name__))

    axe.set_xlabel('feature 0')

    axe.set_ylabel('feature 1')

axes[0].legend(loc=1)

plt.show()

forge 데이터셋에 기본 매개변수를 사용해 만든LinearSVC와 Logistic Regression model의 경계

첫 번째 특성을 x축, 두번째 특성을 y축에 표현했습니다.

LinearSVC와 LogisticRegression으로 만든 결정 경계가 직선으로 표현되었고 위쪽은 class1, 아래쪽은 class0입니다.

즉 새로운 데이터가 직선 위쪽에 놓이면 class1, 아래쪽에 놓이면 class0으로 분류됩니다.



LinearSVC와 LogisticRegression은 모두 L2 Regularization(0으로 근사)를 사용합니다.

Regularization의 강도를 결정하는 parameter는 C입니다. C값이 낮을수록 계수를 0으로 근사하므로 regularization이 강화됩니다.


다음은 C값에 따른 LogisticRegression의 decision boundary를 보여주는 코드입니다.

c_set = [0.001, 1, 1000]

_, axes = plt.subplots(1, 3)


for c_arg, axe in zip(c_set, axes.ravel()):

    params = {'C':c_arg}

    clf = LogisticRegression(**params).fit(x, y)


    plot_2d_separator(clf, x, fill=True, ax=axe, eps=0.5, alpha=0.5)


    idx_set = []

    for i in np.unique(y): # np.unique: 유일한 값만 리턴

        idx = np.where(y==i)[0]

        idx_set.append(idx)


    axe.scatter(x[idx_set[0]][:, 0], x[idx_set[0]][:, 1], s=40, edgecolors='k'# edgecolors='k' : 'k'=black

                label='class 0', marker='^')

    axe.scatter(x[idx_set[1]][:, 0], x[idx_set[1]][:, 1], s=40, edgecolors='k',

                label='class 1', marker='o')

    axe.set_title('{}, C={}'.format(clf.__class__.__name__, c_arg))

    axe.set_xlabel('feature 0')

    axe.set_ylabel('feature 1')

axes[0].legend(loc=3)

plt.show()

forge 데이터셋에 다른 C값으로 만든 LogisticRegression의 decision boundary

왼쪽 그림은 작은 C 값으로 regularization이 많이 적용되었습니다.

Regularization이 강할수록 수평적으로 그려지고

Regularization C값이 클수록 decision boundary는 최대한 train data를 맞추려고 합니다. 즉 overfitting의 가능성이 증가합니다.



LogisticRegression은 linear_model과 성격이 비슷하므로 마찬가지로 coefficient를 가지고 있습니다.

다음은 C값에 따른 coefficient를 시각화하는 코드입니다.

C_set = [0.01, 1, 100]

n_feature = cancer.data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)

marker_set = ['o', '^', 'v']


for c_args, m in zip(C_set, marker_set):

    params = {'C':c_args}

    logreg = LogisticRegression(**params).fit(x_train, y_train)

    plt.scatter(line, logreg.coef_, marker=m, label='C={}'.format(c_args))


plt.hlines(0, xmin=np.min(line), xmax=n_feature, lw=2, color='k')

plt.xticks(np.arange(n_feature), cancer.feature_names, rotation=90, ha='center') # ha: horizon alignment

plt.ylim(-5, 5)

plt.xlabel('feature', size=15)

plt.ylabel('coef_ size', size=15)

plt.legend(loc=1)

plt.show()

breast cancer 데이터셋에 다른 C 값을 사용하여 만든 LogisticRegression coef_



이번엔 Logistic Regression에서 L1 regularization(계수를 0으로)를 사용하여 시각화해보겠습니다.

C_set = [0.01, 1, 100]

n_feature = cancer.data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)

marker_set = ['o', '^', 'v']


for c_args, m in zip(C_set, marker_set):

    params = {'C':c_args, 'penalty':'l1'}

    logreg = LogisticRegression(**params).fit(x_train, y_train)

    plt.scatter(line, logreg.coef_, marker=m, label='C={}'.format(c_args))


plt.hlines(0, xmin=np.min(line), xmax=n_feature, lw=2, color='k')

plt.xticks(np.arange(n_feature), cancer.feature_names, rotation=90, ha='center')

plt.ylim(-5, 5)

plt.xlabel('feature', size=15)

plt.ylabel('coef_ size', size=15)

plt.legend(loc=1)

plt.show()

breast cancer 데이터와 L1 Regularization을 사용하여, 다른 C값을 적용한 LogisticRegression coef_

Regularization에서 모든 특성을 이용할지 일부 특성만을 사용할지 결정하는 주요 parameter는 'penalty'입니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12
k_NN(k-최근접 이웃) Classifier[1]  (0) 2018.03.11

+ Recent posts