QDA(quadratic discriminant analysis)는 Y 클래스에 대한 독립 변수 X의 조건부 확률 분포가 다변수 가우시안 정규 분포(multivariate Gaussian normal distribution)이라는 가정을 한다.
$$ p(x \mid y = k) = \dfrac{1}{(2\pi)^{D/2} |\Sigma_k|^{1/2}} \exp \left( -\dfrac{1}{2} (x-\mu_k)^T \Sigma_k^{-1} (x-\mu_k) \right) $$이 분포들을 알고 있으면 독립 변수 X에 대한 Y 클래스의 조건부 확률 분포는 다음과 같이 베이즈 규칙으로부터 구할 수 있다.
$$ P(y=k \mid x) = \dfrac{p(x \mid y = k)P(y=k)}{p(x)} = \dfrac{p(x \mid y = k)P(y=k)}{\sum_l p(x \mid y = l)P(y=l) } $$예를 들어 Y 가 1, 2, 3 이라는 3개의 클래스를 가지고 각 클래스에서의 X 의 확률 변수가 다음과 같은 기대값 및 공분산 행렬을 가진다고 가정하자.
$$ \mu_1 = \begin{bmatrix} 0 \\ 0 \end{bmatrix}, \;\; \mu_2 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}, \;\; \mu_3 = \begin{bmatrix}-1 \\ 1 \end{bmatrix} $$$$ \Sigma_1 = \begin{bmatrix} 0.7 & 0 \\ 0 & 0.7 \end{bmatrix}, \;\; \Sigma_2 = \begin{bmatrix} 0.8 & 0.2 \\ 0.2 & 0.8 \end{bmatrix}, \;\; \Sigma_3 = \begin{bmatrix} 0.8 & 0.2 \\ 0.2 & 0.8 \end{bmatrix} $$Y의 사전 확률은 다음과 같이 동일하다
$$ P(Y=1) = P(Y=2) = P(Y=3) = \dfrac{1}{3} $$이번에는 각 학생간 관련이 있다?
In [1]:
N = 100
np.random.seed(0)
X1 = sp.stats.multivariate_normal([ 0, 0], [[0.7, 0],[0, 0.7]]).rvs(100)
X2 = sp.stats.multivariate_normal([ 1, 1], [[0.8, 0.2],[0.2, 0.8]]).rvs(100)
X3 = sp.stats.multivariate_normal([-1, 1], [[0.8, 0.2],[0.2, 0.8]]).rvs(100)
y1 = np.zeros(N)
y2 = np.ones(N)
y3 = 2*np.ones(N)
X = np.vstack([X1, X2, X3])
y = np.hstack([y1, y2, y3])
In [4]:
len(X1), X1.shape
Out[4]:
In [5]:
plt.scatter(X1[:, 0], X1[:, 1], alpha=0.8, s=50, color='r', label='class1')
plt.scatter(X2[:, 0], X2[:, 1], alpha=0.8, s=50, color='g', label='class2')
plt.scatter(X3[:, 0], X3[:, 1], alpha=0.8, s=50, color='b', label='class3')
sns.kdeplot(X1[:, 0], X1[:, 1], alpha=0.3, cmap=mpl.cm.hot)
sns.kdeplot(X2[:, 0], X2[:, 1], alpha=0.3, cmap=mpl.cm.summer)
sns.kdeplot(X3[:, 0], X3[:, 1], alpha=0.3, cmap=mpl.cm.cool)
plt.xlim(-5, 5)
plt.ylim(-4, 5)
plt.legend()
plt.show()
In [7]:
from sklearn.naive_bayes import GaussianNB
model = GaussianNB().fit(X,y)
In [8]:
from sklearn.metrics import confusion_matrix, classification_report
In [9]:
confusion_matrix(y, model.predict(X))
Out[9]:
In [10]:
print(classification_report(y, model.predict(X)))
In [11]:
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
qda = QuadraticDiscriminantAnalysis(store_covariances=True).fit(X, y)
#True 한 것의 의미는? 그러면 밑에 값들이 안 생길 수 있다. 공분산 값들
In [ ]:
In [12]:
qda.means_
Out[12]:
In [13]:
qda.covariances_[0]
Out[13]:
In [14]:
qda.covariances_[1]
Out[14]:
In [15]:
qda.covariances_[2]
Out[15]:
In [16]:
confusion_matrix(y, qda.predict(X))
Out[16]:
In [17]:
print(classification_report(y, qda.predict(X)))
In [18]:
xmin, xmax = -5, 5
ymin, ymax = -4, 5
XX, YY = np.meshgrid(np.arange(xmin, xmax, (xmax-xmin)/1000), np.arange(ymin, ymax, (ymax-ymin)/1000))
ZZ = np.reshape(qda.predict(np.array([XX.ravel(), YY.ravel()]).T), XX.shape) # predict 안에서 1차원으로 플어야 한다. ravel = flatten
cmap = mpl.colors.ListedColormap(sns.color_palette("Set3")) #reshape을 한 이유는?
plt.contourf(XX, YY, ZZ, cmap=cmap, alpha=0.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=cmap)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.show()
LDA(linear discriminant analysis)에서는 각 Y 클래스에 대한 독립 변수 X의 조건부 확률 분포가 공통된 공분산 행렬을 가지는 다변수 가우시안 정규 분포(multivariate Gaussian normal distribution)이라고 가정한다. 즉
$$ \Sigma_k = \Sigma \;\;\; \text{ for all } k $$이다.
이 때는 조건부 확률 분포를 다음과 같이 정리할 수 있다.
$$ \begin{eqnarray} \log p(x \mid y = k) &=& \log \dfrac{1}{(2\pi)^{D/2} |\Sigma|^{1/2}} - \dfrac{1}{2} (x-\mu_k)^T \Sigma^{-1} (x-\mu_k) \\ &=& \log \pi + \dfrac{1}{2} (x-\mu_k)^T \Sigma^{-1} (x-\mu_k) \\ &=& \log \pi + \dfrac{1}{2} \left( x^T\Sigma^{-1}x - 2\mu_k^T \Sigma^{-1}x + \mu_k^T \Sigma^{-1}\mu_k \right) \\ \end{eqnarray} $$
In [ ]:
즉, 조건부 확률 변수가 x에 대한 선형 방정식이 된다.
In [20]:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=3, solver="svd", store_covariance=True).fit(X, y)
In [21]:
lda.means_
Out[21]:
In [22]:
lda.covariance_
Out[22]:
In [23]:
confusion_matrix(y, lda.predict(X))
Out[23]:
In [24]:
print(classification_report(y, qda.predict(X)))
In [25]:
xmin, xmax = -5, 5
ymin, ymax = -4, 5
XX, YY = np.meshgrid(np.arange(xmin, xmax, (xmax-xmin)/1000), np.arange(ymin, ymax, (ymax-ymin)/1000))
ZZ = np.reshape(lda.predict(np.array([XX.ravel(), YY.ravel()]).T), XX.shape)
cmap = mpl.colors.ListedColormap(sns.color_palette("Set3"))
plt.contourf(XX, YY, ZZ, cmap=cmap, alpha=0.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=cmap)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.show()
Pipeline?
파이프라인이 없을 경우에는 이러한 순서로 전개한다. 그런데 있다면?