수식이 깨질 경우 새로고침을 눌러주세요.¶
Probability for Data-Science-13¶
다변수 확률 모형 ②¶
- Categorical (Multinoulli)
- Multinomial
- ✓Dirichlet
- Multivariate Gaussian Normal
Dirichlet distribution (디리클레 분포)¶
$$ \begin{eqnarray} 단,\;\; \mathrm{B}(\boldsymbol\alpha) &=& \frac{\prod_{i=1}^K \Gamma(\alpha_i)} {\Gamma\bigl(\sum_{i=1}^K \alpha_i\bigr)} \\ \\&=& \frac{\Gamma(\alpha_1)\cdots\Gamma(\alpha_K)}{\Gamma(\alpha_1+\cdots+\alpha_K)} \end{eqnarray} $$$$또한,\;\;\; (0 \leq x_i \leq 1)\;이며\;\; \sum_{i=1}^{K} x_i = 1 $$$$ 이\;\; 식에서 \;\; \boldsymbol\alpha =\; (\alpha_1, \alpha_2, \ldots, \alpha_K)는 \;\;디리클레 \;\;분포의 \;\;모수 \;\;벡터이다. $$디리클레 분포의 확률 밀도 함수 $$ f(x_1, x_2, \cdots, x_K) = \frac{1}{\mathrm{B}(\boldsymbol\alpha)} \prod_{i=1}^K x_i^{\alpha_i - 1} $$
$$(1, 0, 0), \;\;\;(0.5, 0.5, 0),\;\;\; (0.2, 0.3, 0.5)$$ex) K=3인 디리클레 분포를 따르는 확률 변수는 다음과 같은 값을 샘플로 가질 수 있다.
베타 분포와 디리클레 분포의 관계¶
베타 분포는 $K=2$ 인 디리클레 분포라고 볼 수 있다.
디리클레 분포의 모멘트 특성¶
$$ 위에서\;\; 보듯이\;\; \boldsymbol{\alpha} = \sum\alpha_k $$$$ 기대값\;\; 공식을\;\; 보면\;\; 모수인\;\; \boldsymbol\alpha \;=\; (\alpha_1,\; \alpha_2,\; \ldots,\; \alpha_K)는\\ (x_1, x_2, \ldots, x_K)\;\; 중\;\; 어느\;\; 수가\;\; 더\;\; 크게\;\; 나올\;\; 가능성이\;\; 높은\;지를\;\; 결정하는\;\; 형상\;\; 인자(shape \;factor)임을\;\; 알\;\; 수\;\; 있다.\;\;\\ 모든\;\; \alpha_i값이\;\; 동일하면\;\; 모든\;\; x_i의\;\; 분포가\;\; 같아진다. $$기대값 $$ \begin{eqnarray} E[x_k] &=& \dfrac{\alpha_k}{\boldsymbol\alpha} \\ &=& \dfrac{\alpha_k}{\sum\alpha_k} \end{eqnarray} $$
$$ \dfrac{\alpha_k - 1}{\boldsymbol\alpha - K}$$모드
$$\text{Var}[x_k] =\dfrac{\alpha_k(\boldsymbol\alpha - \alpha_k)}{\boldsymbol\alpha^2(\boldsymbol\alpha + 1)}$$분산
디리클레 분포의 응용¶
Sol
3차원 디리클레 문제는 3차원 공간 상에서 (1,0,0), (0,1,0), (0,0,1) 세 점을 연결하는 정삼각형 면위의 점을 생성하는 문제라고 볼 수 있다.
# -*- coding: utf-8 -*-
import seaborn as sns
import pandas as pd
import scipy as sp
import matplotlib as mpl
import matplotlib.pylab as plt
import numpy as np
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# 3차원 도화지를 꺼내라.
fig = plt.figure(figsize=(8,5))
ax = Axes3D(fig)
x = [1,0,0]
y = [0,1,0]
z = [0,0,1]
# x,y,z벡터의 각 원소를 zip으로 묶어서, 3차 좌표로 변환
## zip으로 좌표를 묶은 후 리스트가 두개가 있어야 그래프가 그려진다. 차원을 맞춰 주어야한다.
verts = [list(zip(x, y, z))]
ax.add_collection3d(Poly3DCollection(verts, edgecolor="k", lw=5, alpha=0.4))
ax.text(1, 0, 0, "(1,0,0)", position=(0.7,0.1))
ax.text(0, 1, 0, "(0,1,0)", position=(0,1.04))
ax.text(0, 0, 1, "(0,0,1)", position=(-0.2,0))
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.view_init(30, -20)
tmp_planes = ax.zaxis._PLANES
# set origin ( http://stackoverflow.com/questions/15042129/changing-position-of-vertical-z-axis-of-3d-plot-matplotlib )
ax.yaxis._PLANES = (tmp_planes[2], tmp_planes[3],
tmp_planes[0], tmp_planes[1],
tmp_planes[4], tmp_planes[5])
ax.zaxis._PLANES = (tmp_planes[2], tmp_planes[3],
tmp_planes[0], tmp_planes[1],
tmp_planes[4], tmp_planes[5])
plt.show()
주의!¶
x = [1,0,0]
y = [0,1,0]
z = [0,0,1]
verts_1 = [zip(x, y, z)]
verts_2 = list(zip(x, y, z))
verts_1
verts_2
위에서 보듯이 리스트와 zip은 같이 다녀야 한다!¶
x = [1,0,0]
y = [0,1,0]
z = [0,0,1]
# x,y,z벡터의 각 원소를 zip으로 묶어서, 3차 좌표로 변환
## zip으로 좌표를 묶은 후 리스트가 두개가 있어야 그래프가 그려진다. 차원을 맞춰 주어야한다.
verts_3 = [list(zip(x, y, z))]
verts_3
그래프를 그릴 때, 위 처럼 리스트가 2개가 있어야한다. 차원을 맞춰줘야 한다!¶
다음 함수는 생성된 점들을 2차원 삼각형 위에서 볼 수 있도록 그려주는 함수이다.¶
def plot_triangle(X, kind):
n1 = np.array([1, 0, 0])
n2 = np.array([0, 1, 0])
n3 = np.array([0, 0, 1])
# n1과 n2의 중점
n12 = (n1 + n2)/2
m1 = np.array([1, -1, 0])
m2 = n3 - n12
# 노말라이징해서 단위벡터로 변환
m1 = m1/np.linalg.norm(m1)
m2 = m2/np.linalg.norm(m2)
X1 = (X-n12).dot(m1)
X2 = (X-n12).dot(m2)
g = sns.jointplot(X1, X2, kind=kind, xlim=(-0.8,0.8), ylim=(-0.45,0.9))
g.ax_joint.axis("equal")
plt.show()
만약 이 문제를 단순하게 생각하여 서로 독립인 0과 1사이의 유니폼 확률 변수를 3개 생성하고 이들의 합이 1이 되도록 크기를 정규화(normalize)하면
다음 그림과 같이 삼각형의 중앙 근처에 많은 확률 분포가 집중된다. 즉, 확률 변수가 골고루 분포되지 않는다.
X1 = np.random.rand(1000, 3)
X1 = X1/X1.sum(axis=1)[:, np.newaxis]
plot_triangle(X1, kind="scatter")
plot_triangle(X1, kind="hex")
그러나 alpha=(1,1,1)인 디리클레 분포는 다음과 같이 골고루 샘플을 생성한다.¶
X2 = sp.stats.dirichlet((1,1,1)).rvs(1000)
plot_triangle(X2, kind="scatter")
plot_triangle(X2, kind="hex")
alpha가 (1,1,1) 이 아닌 경우¶
다음과 같이 특정 위치에 분포가 집중되도록 할 수 있다.
이 특성을 이용하면 다항 분포의 모수를 추정하는 베이지안 추정 문제에 응용할 수 있다.
def project(x):
n1 = np.array([1, 0, 0])
n2 = np.array([0, 1, 0])
n3 = np.array([0, 0, 1])
n12 = (n1 + n2)/2
m1 = np.array([1, -1, 0])
m2 = n3 - n12
m1 = m1/np.linalg.norm(m1)
m2 = m2/np.linalg.norm(m2)
return np.dstack([(x-n12).dot(m1), (x-n12).dot(m2)])[0]
def project_reverse(x):
n1 = np.array([1, 0, 0])
n2 = np.array([0, 1, 0])
n3 = np.array([0, 0, 1])
n12 = (n1 + n2)/2
m1 = np.array([1, -1, 0])
m2 = n3 - n12
m1 = m1/np.linalg.norm(m1)
m2 = m2/np.linalg.norm(m2)
return x[:,0][:, np.newaxis] * m1 + x[:,1][:, np.newaxis] * m2 + n12
eps = np.finfo(float).eps * 10
X = project([[1-eps,0,0], [0,1-eps,0], [0,0,1-eps]])
import matplotlib.tri as mtri
triang = mtri.Triangulation(X[:,0], X[:,1], [[0, 1, 2]])
refiner = mtri.UniformTriRefiner(triang)
triang2 = refiner.refine_triangulation(subdiv=6)
XYZ = project_reverse(np.dstack([triang2.x, triang2.y, 1-triang2.x-triang2.y])[0])
# alpha = (1,1,1) 일 때
pdf = sp.stats.dirichlet((1,1,1)).pdf(XYZ.T)
# 삼각 등고선을 그려라.
plt.tricontourf(triang2, pdf)
plt.axis("equal")
plt.show()
# (3, 4, 2) 일 때
pdf = sp.stats.dirichlet((3,4,2)).pdf(XYZ.T)
plt.tricontourf(triang2, pdf)
plt.axis("equal")
plt.show()
# (16, 24, 14) 일 때
pdf = sp.stats.dirichlet((16,24,14)).pdf(XYZ.T)
plt.tricontourf(triang2, pdf)
plt.axis("equal")
plt.show()
alpha 값에 따라 자료의 집중도가 달라진다.¶
모수의 추정¶
$$ \hat{\theta}\; : \;\;\; Hyper\;\; Parameter\;라고도\;\; 하며,\;\; 분포의\;\; 파라미터를\;\; 추정하는\;\; 파라미터이다. $$베타분포
- a = b = 1
- a, b를 조작해서 어느 부분의 값을 많이 나오게 할 수 있다.
디리클레 분포 $$ x_1 + x_2 + x_3 = K \rightarrow x_1,\;x_2가\;\; 정해지면\;\; 나머지\;\; x_3는\;\; 자동으로 \;\;정해진다. $$
Parameter가 많을 수록 비모수적 방법을 사용한다.
- seaborn histogram을 사용.
자료의 분포를 히스토그램으로 구간별로 쌓아서 그리도록 한다. 앞에서 해왔던 시뮬레이션의 방법과 동일하다.
모수적 방법(Parameteric) VS 비모수적 방법(Non-Parameteric)
- 일반적으로 파라미터가 5개, 10개가 넘어가면 비모수라고 한다.