"당신은 뭔가 더 대단한 것을 해낼 수 있다."
- 칼로스 M.구티에레즈미국 상무장관 -
4.6 로지스틱 회귀(Logistic Regression)
본래 회귀(Regression)은 값을 예측할 때 쓰이지만, Logistic Regression은 데이터가 어떤 클래스에 속하는지 분류하는데 사용됩니다. 다시 말해서 Logistic Regression은 어떤 데이터가 특정 클래스일 확률을 결과값으로 도출하기 때문에 회귀에 속하는 것입니다.
예를 들어 어떤 이메일이 스팸인지 아닌지를 분류할 때, 데이터를 Logistic Regression을 이용하여 추정할 때 결과값이 0.6이 나오면 해당 데이터가 스팸일 확률이 60%라는 것이고 이 경우 해당 메일을 스팸으로 분류하는 식입니다.
4.6.1 확률 추정
Logistic Regression의 작동 방식에 대해 알아보겠습니다. 우선 처음엔 데이터를 집어넣으면 각 feature의 가중치 합을 계산합니다. 여기까지가 일반적인 Linear Model의 결과값 도출방식입니다.
하지만 Logistic Regression에서는 이것을 시그모이드 함수(sigmoid function)으로 감싸서 0과 1사이의 값이 나오도록 바꿔줍니다. 왜일까요? 당연히 데이터를 특정 클래스로 분류해야하기 때문에 0~1사이의 확률값으로 변환해야하는 것입니다.
이 시그모이드 함수의 형태는 다음과 같으며, t에 대한 함수값이 0과 1 사이에서 존재하는 것을 확인할 수 있습니다.
이 함수를 거쳐나온 확률값으로 최종적으로 주어진 데이터가 어느 클래스에 속하는지 결정하게 됩니다. 보통 확률값이 0.5 이상이면 1 (양성 클래스), 이하면 0 (음성 클래스)라고 예측합니다.
4.6.2 훈련과 Cost 함수
Logistic Regression에서 훈련의 목적은 양성인 데이터 (y = 1)에 대해서는 높은 확률값을 도출하고 음성인 데이터(y=0)에 대해서는 낮은 확률값을 도출하는 것입니다.
Logistic Regression의 Cost 함수는 이러한 아이디어를 잘 반영하고 있습니다.
예를 들어 데이터는 음성에 가까운데 ( 확률값인 t는 0에 가깝다 ) 이를 양성 클래스로 예측하면 - log(t)는 매우 커지므로 잘못된 예측이라는 것을 알 수 있습니다. 혹은 데이터는 양성에 가까운데 ( 확률값인 t는 1에 가깝다 ) 이를 음성 클래스로 예측하면 마찬가지로 -log(1-t)는 매우 커진다는 것을 알 수 있습니다.
반대로 데이터도 양성이고 예측도 양성이라면, -log(t)는 0에 가까워지고, 데이터도 음성이고 예측도 음성이 되면 -log(1-t)는 역시 0에 가까워집니다.
방금 우리가 한 것은 하나의 데이터에 대해 Cost를 계산하는 과정이었습니다. 전체 데이터에 대한 Cost는 모든 dataset의 Cost를 평균내는 것이고 이를 로그 손실(log loss)라고 부르며 다음과 같은 식으로 표현합니다.
위 Cost 함수는 Gradient Descent Algorithm으로 최적화가 가능합니다. 특히 Cost 함수가 볼록 함수이기 때문에 거의 Global minimum(전역 최솟값)을 찾는 것을 보장합니다.
다만 아쉽게도 Normal Equation( 정규 방정식 )과 같이 단번에 최적화하는 방법은 없습니다.
다음은 최적화에 이용하는 Cost 함수의 편도함수입니다.
4.6.3 결정 경계
이제 세 가지의 서로 다른 꽃 품종을 Logistic Regression으로 분류하는 예시를 통해 설명을 계속 이어가보겠습니다. 우리가 사용할 데이터에는 꽃의 꽃잎, 꽃받침의 너비와 길이를 담고 있습니다. 여기서는 꽃잎의 너비를 기반으로 Iris-Versicolor종을 감지하는 분류기를 만들어볼 것입니다. 우선 데이터를 로드해보겠습니다.
from sklearn import datasets
iris = datasets.load_iris()
list(iris.keys())
>>
['data',
'target',
'frame',
'target_names',
'DESCR',
'feature_names',
'filename']
X = iris["data"][:, 3:] # 꽃잎 너비
y = (iris["target"] == 2).astype(np.int) # Iris virginica이면 1 아니면 0
Logistic Regression 모델을 훈련시킵니다.
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression(solver="lbfgs", random_state=42)
log_reg.fit(X, y)
이제 꽃잎의 너비가 0~3cm인 꽃들에 대해 꽃잎의 너비에 따라 모델이 어떤것을 Iris-Versicolor종으로 분류하는 살펴보겠습니다.
X_new = np.linspace(0, 3, 1000).reshape(-1, 1)
y_proba = log_reg.predict_proba(X_new)
decision_boundary = X_new[y_proba[:, 1] >= 0.5][0]
plt.figure(figsize=(8, 3))
plt.plot(X[y==0], y[y==0], "bs")
plt.plot(X[y==1], y[y==1], "g^")
plt.plot([decision_boundary, decision_boundary], [-1, 2], "k:", linewidth=2)
plt.plot(X_new, y_proba[:, 1], "g-", linewidth=2, label="Iris virginica")
plt.plot(X_new, y_proba[:, 0], "b--", linewidth=2, label="Not Iris virginica")
plt.text(decision_boundary+0.02, 0.15, "Decision boundary", fontsize=14, color="k", ha="center")
plt.arrow(decision_boundary, 0.08, -0.3, 0, head_width=0.05, head_length=0.1, fc='b', ec='b')
plt.arrow(decision_boundary, 0.92, 0.3, 0, head_width=0.05, head_length=0.1, fc='g', ec='g')
plt.xlabel("Petal width (cm)", fontsize=14)
plt.ylabel("Probability", fontsize=14)
plt.legend(loc="center left", fontsize=14)
plt.axis([0, 3, -0.02, 1.02])
save_fig("logistic_regression_plot")
plt.show()
위 그래프를 통해 알 수 있는 점은 다음과 같습니다.
- 1) Iris-Verginica의 꽃잎 너비는 1.4cm~2.5cm 사이입니다. 반면 다른 꽃들의 꽃잎 너비는 0.1 ~ 1.8cm 사이로 약간 중첩됩니다.
- 2) 꽃잎의 너비가 2cm가 넘어가면 Iris-Verginica라고 강하게 확신합니다.
- 3) 양쪽의 확률이 똑같이 50%가 되는 1.6cm 근방에서 결정 경계(decision boundary)가 생성됩니다. 바로 이 decision boundary를 기준으로 이것보다 꽃잎의 너비가 크면 Iris-Verginica라고 예측할 것입니다.
log_reg.predict([[1.7], [1.5]]) #1.7은 양성, 1.5는 음성으로 분류하였습니다.
>> array([1, 0])
이번에는 꽃잎의 너비에 꽃잎의 길이까지 더하여 두개의 feature를 이용해 클래스를 예측해보겠습니다.
from sklearn.linear_model import LogisticRegression
X = iris["data"][:, (2, 3)] # petal length, petal width
y = (iris["target"] == 2).astype(np.int)
log_reg = LogisticRegression(solver="lbfgs", C=10**10, random_state=42)
log_reg.fit(X, y)
x0, x1 = np.meshgrid(
np.linspace(2.9, 7, 500).reshape(-1, 1),
np.linspace(0.8, 2.7, 200).reshape(-1, 1),
)
X_new = np.c_[x0.ravel(), x1.ravel()]
y_proba = log_reg.predict_proba(X_new)
plt.figure(figsize=(10, 4))
plt.plot(X[y==0, 0], X[y==0, 1], "bs")
plt.plot(X[y==1, 0], X[y==1, 1], "g^")
zz = y_proba[:, 1].reshape(x0.shape)
contour = plt.contour(x0, x1, zz, cmap=plt.cm.brg)
left_right = np.array([2.9, 7])
boundary = -(log_reg.coef_[0][0] * left_right + log_reg.intercept_[0]) / log_reg.coef_[0][1]
plt.clabel(contour, inline=1, fontsize=12)
plt.plot(left_right, boundary, "k--", linewidth=3)
plt.text(3.5, 1.5, "Not Iris virginica", fontsize=14, color="b", ha="center")
plt.text(6.5, 2.3, "Iris virginica", fontsize=14, color="g", ha="center")
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
plt.axis([2.9, 7, 0.8, 2.7])
save_fig("logistic_regression_contour_plot")
plt.show()
위 그래프에서 decision boundary는 검은색 점선입니다. 이외에 주목할 점으로는 0.900이라고 명시된 초록색 선 위에 있는 데이터는 90% 이상의 확률로 Iris-Verginica로 분류된 데이입니다. 그리고 0.150이라고 명시된 파란색 선 아래에는 15% 미만으로 음성 클래스로 분류된 데이터들입니다.
4.6.4 소프트맥스 회귀(Softmax Regression)
우리가 앞서 봤던 Logistic Regression은 이진 분류(Binary Classification) 즉 1이냐 0이냐였습니다. Softmax Regression은 두 가지 이상의 클래스를 분류하는데 사용하는 Logistic Regression입니다.
데이터가 주어지면 Softmax Regression 모델은 해당 데이터가 각 클래스에 대한 점수를 계산하고,
softmax 함수를 이용하여 이 점수를 확률값으로 바꾸게 됩니다. 그리고 가장 높은 확률값을 가진 클래스로 데이터 x를 분류하게 됩니다.
이제 모델의 훈련 방법에 대해 알아보겠습니다. 우리의 목적은 타깃(정답) 클래스에 대해서는 높은 확률을, 나머지는 낮은 확률을 추정하도록 하는것이 목표입니다. 여기에 Cross-Entropy Cost 함수를 사용합니다. 그리고 이를 최적화하기 위한 Gradient Vector는 다음과 같습니다.
다음은 sklearn에서 Softmax Regression을 적용하는 코드입니다.
X = iris["data"][:, (2, 3)] # 꽃잎 길이, 꽃잎 너비
y = iris["target"]
softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=42)
softmax_reg.fit(X, y)
그리고 꽃잎의 길이가 5cm, 너비가 2cm인 꽃의 품종이 무엇인지 모델에 물어봤더니 94.2% 확률로 Iris-Verginica라고 출력하고 있습니다.
softmax_reg.predict([[5, 2]])
>> array([2])
softmax_reg.predict_proba([[5, 2]])
>> array([[6.38014896e-07, 5.74929995e-02, 9.42506362e-01]])
앞서 우리는 세개의 품종에 대해 Iris-Verginica를 감지하는 분류기에 대해서 다뤄봤습니다. 그리고 다음에서 세 개의 클래스에 대해 decision boundary를 어떻게 형성하는지 살펴보겠습니다.
- 1) class 사이의 decision boundary는 선형입니다.
- 2) 모든 결정 경계가 만나는 지점에서는 클래스가 모두 동일하게 33%의 추정 확률을 가집니다.
다음 포스팅에서는 Logistic Regression과 함께 Classification에 사용되는 대표적인 방법인 SVM (Support Vector Machine)에 대해 공부해보겠습니다.
긴 글 읽어주셔서 감사합니다. 행복한 하루 보내시길 바랍니다 :)
'AI > Hands-On Machine Learning 2판' 카테고리의 다른 글
[ 핸즈온 머신러닝 2 ] Decision Tree란? (0) | 2021.02.02 |
---|---|
[ 핸즈온 머신러닝 2판 ] SVM이란? (2) | 2021.02.02 |
[ 핸즈 온 머신러닝 2판 ] Polynomial Regression과 Learning Curve란? (0) | 2020.09.29 |
[ Tensorflow 2 / sklearn ] Linear Regression과 Gradient Descent Algorithm의 종류 (1) | 2020.07.24 |
[핸즈온 머신러닝 2판 ] MNIST를 활용한 다중 분류(Multi Class Classification)은 어떻게 하는 것일까? (0) | 2020.07.20 |