기본 콘텐츠로 건너뛰기

[matplotlib] 등고선(Contour)

softmax 모델(Softmax Regression)

내용

Softmax Regression

Softmax 회귀 모델

데이터를 두 개의 클래스로 구분하기 위한 예측 방법인 로지스틱 회귀는 2개 이상의 클래스로 분류하기 위해 softmax 방법으로 일반화 할 수 있습니다. 이 방법을 softmax 회귀 또는 다중 로지스틱 회귀(multinomial Losgistic regression)이라고 합니다.

이 모델은 우선적으로 각 인스턴스에 대해 식 1을 적용합니다. 이것은 그 인스턴스의 각 클래스에 대한 점수를 나타냅니다. 다음으로 식 2의 softmax 함수를 사용하여 각 클래스에 포함될 확률을 추정합니다.

(1)sk(x)=xTθ(k)

각 클래스 k는 자신의 가중치벡터 θ(k)를 가집니다. 예를 들어 3개의 특성(독립변수)과 3개의 클래스들(A, B, C)를 가진 라벨(반응변수)에 대해 다음과 같이 각 인스턴스(샘플)의 점수를 계산할 수 있습니다.

- A or not[WA1WA2WA3][x1x2x3]=[WA1x1+WA2x2+WA3x3]=s(x)A- B or not[WB1WB2WB3][x1x2x3]=[WB1x1+WB2x2+WB3x3]=s(x)B- C or not[WC1WC2WC3][x1x2x3]=[WC1x1+WC2x2+WC3x3]=s(x)C

위 식은 다음과 같이 하나의 식으로 결합할 수 있습니다.

[WA1WA2WA3WB1WB2WB3WC1WC2WC3][x1x2x3]=[WA1x1+WA2x2+WA3x3WB1x1+WB2x2+WB3x3WC1x1+WC2x2+WC3x3]=[s(x)As(x)Bs(x)C]

식 1 즉, 위의 연산으로 부터의 각 클래스의 점수를 [0,1] 사이의 값으로 변환하기 위해 식 2와 같이 각 값들을 전체의 값으로 나누어 고려합니다. 이 결과는 인스턴스가 각 클래스와 매칭될 확률을 추정합니다. 식 2는 식 1의 각 점수를 정규화시킨 값입니다.

(2)p^=σ(s(x))k=exp(sk(x))j=1Kexp(sj(x))
  • K: 클래스의 수
  • s(x):인스턴스 x에 대한 각 클래스의 점수 벡터
  • σ(s(x))k: 인스턴스가 각 클래스에 포함될 확률

최종적으로 식 3과 같이 softmax 함수에 의해 계산된 확률들 중 가장 큰 값을 보이는 클래스를 선택합니다.

(3)y^=argmaxk(σ(s(x))k)=argmaxk((s(x))k)=argmaxk(xTθ(k))

식 3의 argment()는 가장 높은 확률을 보이는 인덱스 즉, 클래스(y)를 반환합니다.

비용함수

softmax 모델은 대상 클래스에 대한 높은 확률(결과적으로 다른 클래스에 대한 낮은 확률)을 추정하는 모델을 갖는 것입니다. 식 4의 교차 엔트로피(cross entropy)라고 비용 함수(cost function, L(θ))가 최소가 되도록 합니다. 이를 위해 대상 클래스에 대한 낮은 확률을 추정할 때 모델에 페널티를 가합니다.

(4)L(θ)=1mk=1Kyk(i)log(p^k(i))

y(i)k는 i번째 인스턴스의 관측 확률입니다. 예를 들어 y=<0,1,0>인 경우 두 개의 예측치 y1^,y2^,y3^에 대한 Cross-entropy 함수를 적용하면 다음과 같습니다.

y=[010]y1^=[100]y2^=[010]y2^=[001]L1=[010]×log([100])=[010]×[0]=[00]=L2=[010]×log([010])=[010]×[0]=[000]=0L3=[010]×log([001])=[010]×[0]=[00]=

위 결과와 같이 잘못된 예측에 의한 비용은 무한대까지 확장될 수 있지만 올바른 예측에 의한 비용은 0에 근접합니다.

비용함수의 결과를 최소화시키는 것이 궁극적인 목적이지만 식 4의 교차 엔트로피 함수의 최소화 지점을 직접적으로 확인할 수 있는 식을 유도할 수 없습니다. 대신에 경사하강법에 의해 비용에 식 5에 의해 계산된 그 변화를 반복적으로 적용하여 최소지점을 찾을 수 있습니다. 결국 이 지점에서의 가중치가 최적화된 가중치로 모델의 매개변수가 됩니다.

(5)ΔθkL(θ)=1mi=1m(p^k(i)yk(i))x(i)

모델 생성

로지스틱 회귀와 같이 sklearn.linear_model.LogisticRegression() 클래스를 사용하여 softmax 모델을 생성합니다. 이 클래스의 매개변수 중 multi_class와 solver의 설정이 필요합니다.

  • solver: 데이터 셋이 작을 경우는 'liblinear', 반면에 큰 데이터 셋의 경우는 'sag'와 'saga'에 의해 속도가 개선됩니다. 'liblinear'는 l1 penalty(l1 정규화)를 실행되는 모델에서는 작동되지 않습니다.(sklear의 solver에 대한 설명을 참조)
  • multi_class
    • 옵션 'ovr'은 이진 문제에 적합합니다.
    • 'multinomial'의 경우 이진분류와 다항 분류 모두에서 전체 확률분포에 적합한 최소손실을 계산합니다. 그러나 이 경우는 손실은 solver='liblinear'인 경우 'multinomial'을 사용할 수 없습니다.
    • 'auto'는 데이터가 이진 또는 solver='liblinear'이면 'ovr'을 선택하고, 나머지 경우는 'multinomial'을 선택합니다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
font1={'size':11, 'weight':'bold'}
from sklearn import datasets
iris=datasets.load_iris()
iris.keys()
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
iris['feature_names'], iris['target_names']
(['sepal length (cm)',
      'sepal width (cm)',
      'petal length (cm)',
      'petal width (cm)'],
     array(['setosa', 'versicolor', 'virginica'], dtype='< U10'))
X=iris['data'][:,[2,3]]
y=iris['target']
from sklearn.linear_model import LogisticRegression
softmax_reg=LogisticRegression(multi_class="multinomial", solver="lbfgs").fit(X,y)
pre=softmax_reg.predict(X)
pre
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
           1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
           2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
           2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
softmax_reg.score(X, y)
0.9666666666666667
W=softmax_reg.coef_
W0=softmax_reg.intercept_
W,W0
(array([[-2.74866104, -1.16890756],
            [ 0.08356447, -0.90803047],
            [ 2.66509657,  2.07693804]]),
     array([ 11.12767979,   3.22717485, -14.35485463]))

생성된 softmax 모델에 의한 각 결정경계는 다음과 같이 나타낼 수 있습니다.

이 모델에서는 세개의 클래스에 대한 회귀선을 생성합니다. 다음 결과와 같이 첫번째와 세번째 클래스의 선에 의해 각 클래스의 구분이 가능합니다.

def col(x):
    if x==0:
        return("blue")
    elif x==1:
        return("red")
    else:
        return("green")
x=X[:,0].reshape(-1,1)
y1=(-np.dot(x,W[:,0].reshape(1,-1))-W0)/W[:,1]
plt.figure(figsize=(10, 4), dpi=100)
plt.subplot(1,2,1)
plt.scatter(X[:,0],X[:,1], s=y+5, color=[col(i) for i in y],label='data')
for i in range(y1.shape[1]):
    plt.plot(x, y1[:,i], label=i)
plt.xlabel('petal length', fontdict=font1)
plt.ylabel('petal width', fontdict=font1)
plt.subplot(1,2,2)
plt.scatter(X[:,0],X[:,1], s=y+5, color=[col(i) for i in y],label='data')
for i in range(y1.shape[1]):
    plt.plot(x, y1[:,i], label=i)
plt.legend(bbox_to_anchor=(1,1), prop=font1)
plt.xlabel('petal length', fontdict=font1)
plt.ylim(0, 3.5)
plt.show()

위 결과와 같이 클래스 2에 대응하는 회귀선은 분류에 도움이 되지 않습니다. 그러나 세개의 클래스 분류에 사용되는 것은 두 개의 경계만이 필요한 것으로 이 모델의 경우 첫번째와 세번째 회귀선이 결정 경계가 됩니다.

이 결과는 .decision_function() 메서드에 의한 점수로 확인할 수 있습니다. 이 점수는 각 데이터 포인트와 위에서 나타낸 각 클래스의 회귀선 사이의 거리를 나타낸 것으로 이들이 최소가 되는 지점이 클래스를 결정하는 경계가 됩니다.

deci=softmax_reg.decision_function(X)
idxMn=np.argmin(np.abs(deci), axis=0)
X[idxMn, :]
array([[3.7, 1. ],
           [5.7, 2.5],
           [4.2, 1.5]])
x=X[:,0].reshape(-1,1)
y1=(-np.dot(x,W[:,0].reshape(1,-1))-W0)/W[:,1]
plt.scatter(X[:,0],X[:,1], s=y+5, color=[col(i) for i in y],label='data')
col1=['blue', 'red', 'green']
n=0
for i,j in X[idxMn, :]:
    plt.scatter(i, j, s=100, color="none", edgecolor=col1[n], label=i)
    n +=1
plt.legend(bbox_to_anchor=(1,1), prop=font1)
plt.ylim(0, 3.5)
plt.show()

위 결정경계 지점에서의 예측확률은 .predict_proba()에 의해 확인할 수 있습니다.

pre_prob=softmax_reg.predict_proba(X)
np.around(pre_prob[np.argmin(np.abs(deci), axis=0), :], 3)
array([[0.055, 0.939, 0.006],
           [0.   , 0.01 , 0.99 ],
           [0.011, 0.896, 0.093]])

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. (1)A=PBP1P1AP=B 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. (식 2)BλI=P1APλP1P=P1(APλP)=P1(AλI)P 식 2의 행렬식은 식 3과 같이 정리됩니다. det(BλI)=det(P1(APλP))=det(P1)det((AλI))det(P)=det(P1)det(P)det((AλI))=det(AλI)det(P1)det(P)=det(P1P)=det(I) 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a sin2(x)+cos2(x) simplify(a) 1 simplify(b) x3+x2x1x2+2x+1 simplify(b) x - 1 c=gamma(x)/gamma(x-2) c Γ(x)Γ(x2) simplify(c) (x2)(x1) 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. (식 1)Γ(n)={(n1)!n:자연수0xn1exdxn:부동소수 x=symbols('x') gamma(x).subs(x,4) 6 factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 x2=1의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. x21=0 import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. x21=0(x+1)(x1)=0x=1or1x4=1의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. x41=(x2+1)(x+1)(x1)=0x=±1,±1=±i,±1 실수...