들어가며

지난 글에서는 로지스틱 함수를 사용하여 두 개의 클래스를 구별하는 이진 분류기에 대해서 다루어보았습니다. 이번에는 여러개의 클래스를 한 번에 분류할 수 있는 소프트맥스 회귀에 대해서 알아보도록 하겠습니다.

목차

1. 소프트맥스의 정의

2. 비용함수(크로스 엔트로피 비용 함수)

3. 코드 구현

1. 소프트맥스의 정의

소프트맥스 회귀 또는 다항 로지시틱 회귀는 소프트 맥스 함수(softmax function)을 사용하여 각 클래스일 확률을 추정하여 이 중 가장 높은 확률을 가진 클래스를 선택하는 것입니다. 이를 쉽게 알아보겠습니다.

 

우선 각 클래스는 자신만의 파라미터 벡터가 존재하며 새로운 샘플이 입력되었을 경우 각 클래스의 벡터와 샘플의 곱을 계산하여 이 중 가장 큰값을 선택하는 방식입니다.

출처 : https://dojinkimm.github.io/ml/2019/11/10/handson-ch4.html

따라서 위와 같은 식이 성립되고 s(x)는 대게 확률이 아니라 일정값이 출력됩니다. 따라서 이를 확률값으로 추출하기 위해서 소프트맥스 함수를 사용합니다.

결국 추정된 클래스는 확률이 가장높은 = s(x)의 값이 가장 높은 클래스가 정해지기에 사실상 클래스만 추정하고 확률은 필요없을 때 마지막에 소프트맥스 함수를 사용하는것은 생략해도됩니다.

2. 비용함수

클래스를 추정하는 방법은 간단히 알아보았으니 이번에는 모델을 학습시키기 위해서 비용함수를 구하는 방법에 대해서 알아보도록 하겠습니다.

여기서 사용할 비용함수는 크로스 엔트로피 함수(cross-entropy function)으로서 타킷 클래스와 예측확률값의 로그값을 곱하것들의 합에 부호를 바꾼것을 의미합니다.

이렇게 한다면 타킷 클래스에 대한 확률값이 감소할 수록 비용함수는 증가하는 구조를 가지고 있기에 비용함수로 적절합니다.

(y_k(i)는 해당 클래스라면 1 다른 클래스라면 0을 나타내는 one-hot 인코딩된 레이블을 의미합니다.)

 

자 이제 비용함수를 구했으니 이에 대한 gradient vector(편도함수)를 구해보도록 하겠습니다.

gradient vector를 보니 비용함수는 복잡했지만 이는 단순히 예측확률에 타깃값을 제외하고 샘플을 곱한 것입니다. 이렇게 단순해진이유는 사실 고의적으로 수학적 기교를 이용해서 의도했기 때문입니다. (안그러면 굳이 확률을 구하기위해 exp를 하거나 비용함수로 로그값을 사용하지 않아도됩니다.) 따라서 매번 학습을 진행할 때 간단한 연산을 통해 빠르게 학습이 가능합니다.

3.코드구현

마지막으로 소프트맥스 회귀를 코드로 구현해보겟습니다. 소프트맥스 회귀는 따로 모듈이 존재하지 않고 LogisticRegression에서 multi_class="multinomial', solver="lbfgs"를 설정함으로써 구현가능합니다.

y = iris["target"]

softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=42)
softmax_reg.fit(X, y)

예측값을 통해 결정경계 표시 그래프 생성

x0, x1 = np.meshgrid(
        np.linspace(0, 8, 500).reshape(-1, 1),
        np.linspace(0, 3.5, 200).reshape(-1, 1),
    )
X_new = np.c_[x0.ravel(), x1.ravel()]


y_proba = softmax_reg.predict_proba(X_new)
y_predict = softmax_reg.predict(X_new)

zz1 = y_proba[:, 1].reshape(x0.shape)
zz = y_predict.reshape(x0.shape)

plt.figure(figsize=(10, 4))
plt.plot(X[y==2, 0], X[y==2, 1], "g^", label="Iris-Virginica")
plt.plot(X[y==1, 0], X[y==1, 1], "bs", label="Iris-Versicolor")
plt.plot(X[y==0, 0], X[y==0, 1], "yo", label="Iris-Setosa")

from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0'])

plt.contourf(x0, x1, zz, cmap=custom_cmap)
contour = plt.contour(x0, x1, zz1, cmap=plt.cm.brg)
plt.clabel(contour, inline=1, fontsize=12)
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
plt.legend(loc="center left", fontsize=14)
plt.axis([0, 7, 0, 3.5])
save_fig("softmax_regression_contour_plot")
plt.show()

+ Recent posts