728x90
1. GMM (Gaussian Mixture Model)
Mixture Model
- 표본이 할당된 군집의 특정 분포에서 생성되었다고 가정
Gaussian Mixture Model
- K-Means의 일반화 or Soft - Clustering
- 표본이 할당된 군집의 정규 분포에서 생성되었다고 가정
GMM Process
- Label이 주어진 경우
- Label이 주어지지 않은 경우
- 결론
거리기반 K - Means의 문제점
- K - Means는 특정 중심점을 기반으로 거리적으로 퍼져있는 데이터 세트에 군집화를 적용하면 효율적
- K - Means는 이러한 데이터 분포를 가지지 않는 데이터 세트에 대해서는 효율적인 군집화가 어려움
K - Means vs GMM
- Covariance
- K - Means: Covariance 고려하지 않음
- GMM: Covariance를 고려함 (How much X and Y vary together)
- Update 방식
- K - Means: $\mu_{k}$ only update + WCV 최소화
- GMM: $\mu_{k}, \sigma_{k}, \pi_{k}$ update + Log - Likelihood 최소화
- Scaling
- K - Means: 영향 받음
- GMM: 영향을 받지 않음 ($\sigma_{k}$고려하기 때문)
- Clustering 방식
- K - Means: 군집만 할당 (Cluster만 형성)
- GMM: 군집별로 확률 계산 후 군집 할당
2. Mathematical Modeling
Mathematical Modeling
- 표본 i를 관측할 확률 = $\sum$(표본 i가 각 군집에 속하고, 관측될 확률)
- $ Pr[x_{i}] = \sum_{k=1}^{K}Pr[x_{i} | x_{i}\in C_{k}] \times Pr[x_{i}\in C_{k}]$
- $\pi_{k} = Pr[x_{i}\in C_{k}]$: 표본이 군집 $C_{k}$에 할당될 확률
- $Pr[x_{i} | x_{i}\in C_{k}] = \frac{1}{\sigma_{k}\sqrt{2\pi}}exp\left [ - \frac{(x_{i}-\mu_{k})^{2}}{2\sigma_{k}^{2}} \right ] \sim N(\mu_{i}, \sigma_{i}^{2})$: 표본이 할당된 군집의 특정 분포에서 관측될 확률
K개의 군집에 대하여 표본 i를 관측할 확률은 다음과 같다
$ Pr[x_{i}] = \sum_{k=1}^{K}Pr[x_{i} | x_{i}\in C_{k}] \times Pr[x_{i}\in C_{k}] = \sum_{k=1}^{K}\frac{1}{\sigma_{k}\sqrt{2\pi}}exp\left [ - \frac{(x_{i}-\mu_{k})^{2}}{2\sigma_{k}^{2}} \right ] \times \pi_{k}$
각 군집에 대해 $\mu_{k}, \sigma_{k}, \pi_{k}$를 찾는 것이 목표
최대 우도 (Maximum Likelihood)를 사용
우도(likelihood): 현재 데이터를 관측할 확률
$ l = \prod_{i=1}^{n}Pr[x_{i}] = \prod_{i=1}^{n}\sum_{k=1}^{K}\frac{1}{\sigma_{k}\sqrt{2\pi}}exp\left [ - \frac{(x_{i}-\mu_{k})^{2}}{2\sigma_{k}^{2}} \right ] \times \pi_{k}$
실제로는 로그의 우도값(log - likelihood)을 최대화
- 보통은 EM (Expectation and Maximization) 기법을 이용
- Gradient Descent 등을 이용하는 것이 가능
3. Expectation - Maximization (EM) 알고리즘
1) $\mu_{k}, \sigma_{k}, \pi_{k}$ Parameter 초기화
2) Expectation - Step: 주어진 Parameter로 할당 확률을 계산하여 군집화
- $ Pr[x_{i}] = \sum_{k=1}^{K}Pr[x_{i} | x_{i}\in C_{k}] \times Pr[x_{i}\in C_{k}] = \sum_{k=1}^{K}\frac{1}{\sigma_{k}\sqrt{2\pi}}exp\left [ - \frac{(x_{i}-\mu_{k})^{2}}{2\sigma_{k}^{2}} \right ] \times \pi_{k}$
3) Maximization - Step: 현재의 군집으로 우도를 최대화하는 Parameter 계산
- $max_{\mu_{k}, \sigma_{k}, \pi_{k}} \sum_{i=1}^{n} log \left [ \frac{1}{\sigma_{k}\sqrt{2\pi}}exp\left [ - \frac{(x_{i}-\mu_{k})^{2}}{2\sigma_{k}^{2}} \right ] \times \pi_{k} \right ]_{x_{i} \in C_{k}}$
- $\mu_{k} = \frac {1} {\left| C_{k} \right|} \sum_{i\in C_{k}}^{}x_{i}$
- $\sigma_{k}^{2} = \frac{1}{\left| C_{k}\right| - 1}\sum_{i\in C_k}^{} (x_{i} - \mu_{k})^{2}$
- $\pi_{k} = \frac{\left| C_{k}\right|}{n}$
4) 수렴할 때까지 2)와 3)을 반복
4. Gaussian Mixture @ Scikit - Learn & 실습
GaussianMixture Class
- Scikit - Learn은 GMM 군집화를 위해 GaussianMixture 클래스를 제공
- GaussianMixture Class의 주요 생성자 파라미터는 n_components 이며 이는 Mixture Model의 개수, 군집화 개수를 의미한다
실습 - GMM을 이용한 붓꽃 데이터 셋 Clustering
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
iris = load_iris()
feature_names = ['sepal_length','sepal_width','petal_length','petal_width']
# 보다 편리한 데이타 Handling을 위해 DataFrame으로 변환
irisDF = pd.DataFrame(data=iris.data, columns=feature_names)
irisDF['target'] = iris.target
- GaussianMixture을 이용하여 붓꽃 데이터 군집화
from sklearn.mixture import GaussianMixture
gmm = GaussianMixture(n_components=3, random_state=0).fit(iris.data)
gmm_cluster_labels = gmm.predict(iris.data)
# 클러스터링 결과를 irisDF 의 'gmm_cluster' 컬럼명으로 저장
irisDF["gmm_cluster"] = gmm_cluster_labels
# target 값에 따라서 gmm_cluster 값이 어떻게 매핑되었는지 확인.
iris_result = irisDF.groupby(["target"])["gmm_cluster"].value_counts()
print(iris_result)
target gmm_cluster
0 0 50
1 2 45
1 5
2 1 50
Name: gmm_cluster, dtype: int64
- 붓꽃 데이터 K-Means 군집화 결과: iris dataset의 특성상 2개의 cluster가 겹치는 부분이 있음
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300,random_state=0).fit(iris.data)
kmeans_cluster_labels = kmeans.predict(iris.data)
irisDF['kmeans_cluster'] = kmeans_cluster_labels
iris_result = irisDF.groupby(['target'])['kmeans_cluster'].value_counts()
print(iris_result)
target kmeans_cluster
0 1 50
1 0 48
2 2
2 2 36
0 14
- Clustering 결과를 시각화하는 함수 생성
- GMM은 군집 중심점 좌표가 없기 때문에 iscenter=False
- K - Means는 군집 중심점 좌표가 있으므로 iscenter=True: Centroid의 좌표를 시각화
- label == -1일 경우는 DBSCAN을 처리하기 위해 생성
### 클러스터 결과를 담은 DataFrame과 사이킷런의 Cluster 객체등을 인자로 받아 클러스터링 결과를 시각화하는 함수
def visualize_cluster_plot(clusterobj, dataframe, label_name, iscenter=True):
if iscenter:
centers = clusterobj.cluster_centers_
unique_labels = np.unique(dataframe[label_name].values)
markers = ["o", "s", "^", "x", "*"]
isNoise = False
for label in unique_labels:
label_cluster = dataframe[dataframe[label_name] == label]
if label == -1:
cluster_legend = "Noise"
isNoise = True
else:
cluster_legend = "Cluster " + str(label)
plt.scatter(
x=label_cluster["ftr1"],
y=label_cluster["ftr2"],
s=70,
edgecolor="k",
marker=markers[label],
label=cluster_legend,
)
if iscenter:
center_x_y = centers[label]
plt.scatter(
x=center_x_y[0],
y=center_x_y[1],
s=250,
color="white",
alpha=0.9,
edgecolor="k",
marker=markers[label],
)
plt.scatter(
x=center_x_y[0],
y=center_x_y[1],
s=70,
color="k",
edgecolor="k",
marker="$%d$" % label,
)
if isNoise:
legend_loc = "upper center"
else:
legend_loc = "upper right"
plt.legend(loc=legend_loc)
plt.show()
- GMM 군집화와 K - Means 군집화를 비교하기 위해 타원형으로 늘어선 임의의 데이터 세트를 형성
from sklearn.datasets import make_blobs
# make_blobs() 로 300개의 데이터 셋, 3개의 cluster 셋, cluster_std=0.5 을 만듬.
X, y = make_blobs(
n_samples=300, n_features=2, centers=3, cluster_std=0.5, random_state=0
)
# 길게 늘어난 타원형의 데이터 셋을 생성하기 위해 변환함.
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X_aniso = np.dot(X, transformation)
# feature 데이터 셋과 make_blobs( ) 의 y 결과 값을 DataFrame으로 저장
clusterDF = pd.DataFrame(data=X_aniso, columns=["ftr1", "ftr2"])
clusterDF["target"] = y
# 생성된 데이터 셋을 target 별로 다른 marker 로 표시하여 시각화 함.
visualize_cluster_plot(None, clusterDF, "target", iscenter=False)
- K - Means 군집화 수행
# 3개의 Cluster 기반 Kmeans 를 X_aniso 데이터 셋에 적용
kmeans = KMeans(3, random_state=0)
kmeans_label = kmeans.fit_predict(X_aniso)
clusterDF["kmeans_label"] = kmeans_label
visualize_cluster_plot(kmeans, clusterDF, "kmeans_label", iscenter=True)
- GMM 군집화 수행
# 3개의 n_components기반 GMM을 X_aniso 데이터 셋에 적용
gmm = GaussianMixture(n_components=3, random_state=0)
gmm_label = gmm.fit(X_aniso).predict(X_aniso)
clusterDF["gmm_label"] = gmm_label
# GaussianMixture는 cluster_centers_ 속성이 없으므로 iscenter를 False로 설정.
visualize_cluster_plot(gmm, clusterDF, "gmm_label", iscenter=False)
- GMM과 K - Means 군집화 결과 비교
print('### KMeans Clustering ###')
print(clusterDF.groupby('target')['kmeans_label'].value_counts())
print('\n### Gaussian Mixture Clustering ###')
print(clusterDF.groupby('target')['gmm_label'].value_counts())
### KMeans Clustering ###
target kmeans_label
0 2 73
0 27
1 1 100
2 0 86
2 14
Name: kmeans_label, dtype: int64
### Gaussian Mixture Clustering ###
target gmm_label
0 2 100
1 1 100
2 0 100
Name: gmm_label, dtype: int64
728x90