GMM(Gaussian Mixture Model), 가우시안 혼합 모델
GMM 개요
- GMM 군집화는 군집화를 적용하고자 하는 데이터가 여러 개의 가우시안 분포를 가진 데이터 집합들이 섞여서 생성된 것이라는 가정하에 군집화를 수행하는 방식이다.
- 정규 분포라고도 알려진 가우시안 분포는 좌우 대칭형의 종 형태를 가진 연속 확률 함수이다.
- 정규 분포는 평균 μ을 중심으로 높은 데이터 분포도를 가지고 있으며, 좌우 표준편차 1에 전체 데이터의 68.27%, 표준편차 2에 전체 데이터의 95.45%를 가지고 있다.
- 평균이 0, 표준편차가 1인 정규 분포를 표준 정규 분포라고 한다.
- GMM은 데이터를 여러 개의 가우시안 분포가 섞인 것으로 간주한다.
- 섞인 데이터 분포에서 개별 유형의 가우시안 분포를 추출한다.
예를 들어, 가우시안 분포 A, B, C를 가진 데이터셋이 있다고 가정하자.
- 세 개의 정규 분포를 합친 것이 있다.
- 군집화를 수행하려는 실제 데이터셋의 데이터 분포도가 세 개의 정규 분포를 합친 모양이라면, 쉽게 이 데이터셋이 정규 분포 A, B, C가 합쳐서 된 분포도임을 알 수 있다.
- 전체 데이터셋은 서로 다른 정규 분포 형태를 가진 여러 가지 확률 분포 곡선으로 구성될 수 있으며, 이런 서로 다른 정규 분포에 기반해 군집화를 수행하는 것이 GMM 군집화이다.
- 가령 1000개의 데이터셋이 있다면 이를 구성하는 여러 개의 정규 분포 곡선을 추출하고, 개별 데이터가 이 중 어떤 정규 분포에 속하는지 결정하는 것이다.
- 이와 같은 방식을 GMM에서는 모수 추정이라고 하는데, 모수 추정은 대표적으로 2가지를 추정한다
→ 1) 개별 정규 분포의 평균, 분산
→ 2) 각 데이터가 어떤 정규 분포에 해당되는지의 확률
- 이런 모수 추정을 위해 GMM에서는 EM(Expectation and Maximization) 방법을 적용한다. 사이킷런은 GMM의 EM 방식을 통한 모수 추정 군집화를 지원하는 GaussianMixture 클래스가 있다.
GMM을 이용한 iris 데이터셋 군집화
- GMM은 확률 기반 군집화, k-means는 거리 기반 군집화
- iris 데이터로 두 가지 방식으로 군집화를 수행한 후 비교해보자
In [1]:
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
iris = load_iris()
feature_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
irisdf = pd.DataFrame(data=iris.data, columns=feature_names)
irisdf['target'] = iris.target
- GaussianMixture에서 가장 중요한 파라미터는 n_components이다.
- n_components는 가우시안 혼합 모델의 총 개수이다.
In [2]:
#n_components=3으로 설정하고 군집화를 수행해보자
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
irisdf['target'] = iris.target
#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
target 0은 cluster 0으로 target 2는 cluster 1로 잘 매핑됐지만 target 1만 cluster 2로 45개, cluster 1로 5개 매핑됐다.
In [3]:
#k-means 군집화를 수행한 결과
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
Name: kmeans_cluster, dtype: int64
gmm으로 수행한 결과가 k-means 군집화보다 더 효과적인 결과를 도출됐다.
이는 어떤 알고리즘이 더 뛰어나단 얘기가 아니라 iris 데이터가 GMM 군집화에 더 효과적이라는 의미이다.
GMM과 K-평균의 비교
- KMeans는 원형의 범위에서 군집화를 수행한다. 데이터셋이 원형의 범위를 가질수록 효율이 더 높아진다.
- make_blobs의 군집 개수를 3으로 하되, cluster_std를 0.5로 설정하여 군집 내의 데이터를 뭉치게 유도한 데이터셋에 KMeans를 적용해보자
- → cluster_std를 작게 설정하면 데이터가 원형 형태로 분산될 수 있다.
In [6]:
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=300, n_features=2, centers=3, cluster_std=0.5, random_state=0)
cluster_df = pd.DataFrame(data=X, columns=['ftr1', 'ftr2'])
cluster_df['target'] = y
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=200, random_state=0)
cluster_labels = kmeans.fit_predict(X)
cluster_df['kmeans_label'] = cluster_labels
centers = kmeans.cluster_centers_
unique_labels = np.unique(cluster_labels)
markers = ['o', 's', '^', 'P', 'D', 'H', 'x']
for label in unique_labels:
label_cluster = cluster_df[cluster_df['kmeans_label']==label]
center_x_y = centers[label]
plt.scatter(x=label_cluster['ftr1'], y=label_cluster['ftr2'], edgecolor='k',
marker=markers[label])
plt.scatter(x=center_x_y[0], y=center_x_y[1], s=200, 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)
plt.show()
- KMeans는 대표적으로 데이터가 길쭉하게 타원형으로 늘어선 경우에 군집화를 잘 수행하지 못한다.
- 그러한 데이터셋을 make_blobs()의 데이터를 변환하여 만들어보자
- 군집을 시각화하기 위한 함수 visualize_cluster_plot을 만들어두자
In [4]:
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()
In [7]:
#타원형의 데이터셋을 만듬
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)
cluster_df = pd.DataFrame(data=X_aniso, columns=['ftr1', 'ftr2'])
cluster_df['target'] = y
visualize_cluster_plot(None, cluster_df, 'target', iscenter=False)
위와 같은 데이터셋에 KMeans 적용
In [8]:
kmeans = KMeans(3, random_state=0)
kmeans_label = kmeans.fit_predict(X_aniso)
cluster_df['kmeans_label'] = kmeans_label
visualize_cluster_plot(kmeans, cluster_df, 'kmeans_label', iscenter=True)
변환된 동일한 데이터셋에 이번엔 GMM 적용
In [9]:
gmm = GaussianMixture(n_components=3, random_state=0)
gmm_label = gmm.fit(X_aniso).predict(X_aniso)
cluster_df['gmm_label'] = gmm_label
visualize_cluster_plot(gmm, cluster_df, 'gmm_label', iscenter=False)
데이터가 분포된 방향에 따라 정확하게 군집화됐음을 알 수 있다.
GMM은 K-means와 다르게 군집의 중심 좌표를 구할 수 없기 때문에 군집 중심 표현이 시각화되지 않는다.
make_blobs()의 target값과 KMeans, GMM의 군집 label값을 서로 비교하여 위와 같은 데이터셋에서 얼만큼의 군집화 효율 차이가 나는지 알아보자
In [10]:
print('### KMeans Clustering ###')
print(cluster_df.groupby('target')['kmeans_label'].value_counts())
print('### Gaussian Mixture Clustering ###')
print(cluster_df.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
KMeans의 경우엔 1번 군집만 정확히 매핑됐지만, GMM의 경우는 군집이 target값과 잘 매핑되어있다.
이처럼 GMM은 KMeans보다 유연하게 다양한 데이터셋에 잘 적용될 수 있다는 장점이 있다.
하지만 군집화를 위한 수행 시간이 오래 걸리다는 단점이 있다.
'Data Science > 파이썬 머신러닝 완벽 가이드' 카테고리의 다른 글
[sklearn] (47) 군집화 실습 - 고객 세그먼테이션(Customer Segmentation) (0) | 2023.07.28 |
---|---|
[sklearn] (46) DBSCAN(밀도 기반 클러스터링), make_circles (0) | 2023.07.26 |
[sklearn] (44) 평균 이동 군집화, Mean Shift, KDE 함수 (0) | 2023.07.25 |
[sklearn] (43) 군집 평가(Cluster Evaluation), 실루엣 계수(Silhouette Score) (0) | 2023.07.19 |
[sklearn] (42) 군집화, K-평균 알고리즘, K-Means Clustering (0) | 2023.07.18 |