728x90
01. K-평균 알고리즘 이해¶
- K-평균은 군집 중심점(centroid)이라는 특정한 임의의 지점을 선택해 해당 중심에 가장 가까운 포인트들을 선택하는 군집화 기법입니다.
- 군집 중심점은 선택된 포인트의 평균 지점으로 이동하고 이동된 중심점에서 다시 가까운 포인트를 선택, 다시 중심점을 평균 지점으로 이동하는 프로세스를 반복적으로 수행합니다. 모든 데이터 포인트에서 더이상 중심점의 이동이 없을 경우에 반복을 멈추고 해당 중심점에 속하는 데이터 포인트들을 군집화하는 기법입니다.
- K-평균의 장점 : 군집화에서 가장 많이 활용되는 알고리즘, 알고리즘이 쉽고 간결하다.
- K-평균의 단점 : 거리 기반 알고리즘으로 속성의 개수가 매우 많을 경우 군집화 정확도가 떨어집니다.(PCA로 차원 감소를 적용해야 할 수도 있습니다.), 반복 횟수가 많을 경우 수행 시간이 매우 느려집니다., 몇 개의 군집을 선택해야 할지 가이드하기가 어렵습니다.
◎ 사이킷런 KMeans 클래스 소개¶
- from sklearn.cluster import KMeans
- KMeans 중 가장 중요한 파라미터는 n_clusters이며, 이는 군집화할 개수
- init는 초기에 군집 중심점의 좌표를 설정할 방식을 말하며 보통은 임의로 중심을 설정하지 않고 일반적으로 init=k-means++ 방식으로 최초 설정합니다.
- max_iter는 최대 반복 횟수이며, 이 횟수 이전에 모든 데이터의 중심점 이동이 없으면 종료합니다.
- KMeans는 비지도학습 클래스이며 주요 속성에 대한 정보로는
- ⓐ labels_ : 각 데이터 포인트가 속한 군집 중심점 레이블, ⓑ clustercenters : 각 군집 중심점 좌표
◎ K-평균을 이용한 붓꽃 데이터 세트 군집화¶
In [1]:
from sklearn.preprocessing import scale
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()
# 보다 편리한 데이터 Handling을 위해 DataFrame으로 변환
irisDF = pd.DataFrame(data=iris.data, columns=['sepal_length','sepal_width','petal_length','petal_width'])
# 개정판 소스 코드 수정(2019.12.24)
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300,random_state=0)
kmeans.fit(irisDF)
# irisDF['cluster']=kmeans.labels_ 개정 소스코드 변경(2019.12.24)
irisDF['target'] = iris.target
irisDF['cluster']=kmeans.labels_
iris_result = irisDF.groupby(['target','cluster'])['sepal_length'].count()
print(iris_result)
target cluster
0 1 50
1 0 48
2 2
2 0 14
2 36
Name: sepal_length, dtype: int64
In [2]:
# PCA 진행 후 군집화
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca_transformed = pca.fit_transform(iris.data)
irisDF['pca_x'] = pca_transformed[:,0]
irisDF['pca_y'] = pca_transformed[:,1]
irisDF.head(3)
Out[2]:
sepal_length | sepal_width | petal_length | petal_width | target | cluster | pca_x | pca_y | |
---|---|---|---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | 0 | 1 | -2.684126 | 0.319397 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | 0 | 1 | -2.714142 | -0.177001 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0 | 1 | -2.888991 | -0.144949 |
In [3]:
# cluster 값이 0, 1, 2 인 경우마다 별도의 Index로 추출
marker0_ind = irisDF[irisDF['cluster']==0].index
marker1_ind = irisDF[irisDF['cluster']==1].index
marker2_ind = irisDF[irisDF['cluster']==2].index
# cluster값 0, 1, 2에 해당하는 Index로 각 cluster 레벨의 pca_x, pca_y 값 추출. o, s, ^ 로 marker 표시
plt.scatter(x=irisDF.loc[marker0_ind,'pca_x'], y=irisDF.loc[marker0_ind,'pca_y'], marker='o')
plt.scatter(x=irisDF.loc[marker1_ind,'pca_x'], y=irisDF.loc[marker1_ind,'pca_y'], marker='s')
plt.scatter(x=irisDF.loc[marker2_ind,'pca_x'], y=irisDF.loc[marker2_ind,'pca_y'], marker='^')
plt.xlabel('PCA 1')
plt.ylabel('PCA 2')
plt.title('3 Clusters Visualization by 2 PCA Components')
plt.show()
◎ 군집화 알고리즘 테스트를 위한 데이터 생성¶
- 사이킷런은 다양한 유형의 군집화 알고리즘을 테스트해 보기 위한 간단한 데이터 생성기를 제공합니다.
- 대표적인 군집화용 데이터 생성기로는 make_blobs()와 make_classification() API가 있습니다.
- make_blobs()는 개별 군집의 중심점과 표준 편차 제어 기능이 추가돼 있으며 make_classification()은 노이즈를 포함한 데이터를 만드는 데 유용하게 사용할 수 있습니다.
- 이 외에 make_circle(), make_moon() API는 중심 기반의 군집화로 해결하기 어려운 데이터 세트를 만드는 데 사용됩니다.
- make_blobs()를 호출하면 피처 데이터 세트와 타깃 데이터 세트가 튜플(Tuple)로 반환됩니다.
※ make_blobs() 파라미터
- n_samples : 생성할 총 데이터의 개수. 디폴트는 100개입니다.
- n_features : 데이터 피처 개수입니다.
- centers : int 값, 예를 들어 3으로 설정하면 군집의 개수를 나타냅니다.
- cluster_std : 생성될 군집 데이터의 표준 편차를 의미합니다. cluster_std가 작을수록 군집 중심에 데이터가 모여 있으며, 클수록 데이터가 퍼져 있음을 알 수 있습니다.
In [4]:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
%matplotlib inline
# make_blobs() 실행하기
X, y = make_blobs(n_samples=200, n_features=2, centers=3, cluster_std=0.8, random_state=0)
print(X.shape, y.shape)
# y target 값의 분포를 확인
unique, counts = np.unique(y, return_counts=True)
print(unique,counts)
(200, 2) (200,)
[0 1 2] [67 67 66]
02. 군집 평가(Cluster Evaluation)¶
- 대부분의 군집화 데이터 세트는 비교할 만한 타깃 레이블을 가지고 있지 않은 비지도학습입니다. 또한 군집화는 분류와 유사해 보일 수 있으나 성격이 많이 다릅니다.
- 군집화의 성능을 평가하는 대표적인 방법으로 실루엣 분석을 이용합니다.
◎ 실루엣 분석의 개요¶
- 군집화 펴가 방법으로 실루엣 분석(silhouette analysis)이 있습니다. 실루엣 분석은 각 군집 간의 거리가 얼마나 효율적으로 분리돼 있는지를 나타냅니다.
- 효율적으로 잘 분리됐다는 것은 다른 군집과의 거리는 떨어져 있고 동일 군집끼리의 데이터는 서로 가깝게 잘 뭉쳐 있다는 의미입니다.
- 실루엣 분석은 실루엣 계수를 기반으로 합니다. 개별 데이터가 가지는 실루엣 계수는 해당 데이터가 같은 군집 내의 데이터와 얼마나 가깝게 군집화돼 있고, 다른 군집에 있는 데이터와는 얼마나 멀리 분리돼 있는지를 나타내는 지표입니다.
- 실루엣 계수는 -1에서 1 사이의 값을 가지며, 1로 가까워질수록 근처의 군집과 더 멀리 떨어져 있다는 것이고 0에 가까울수록 근처의 군집과 가까워진다는 것입니다. - 값은 아예 다른 군집에 데이터 포인트가 할당됐음을 뜻합니다.
- 좋은 군집화는 사이킷런의 silhouette_score() 값은 0~1 사이의 값을 가지며, 1에 가까울수록 좋습니다. 또한 전체 실루엣 계수의 평균값과 더불어 개별 군집의 평균값의 편차가 크지 않아야 합니다. 만약 전체 실루엣 계수의 평균값은 높지만, 특정 군집의 실루엣 계수 평균값만 유난히 높고 다른 군집들의 실루엣 계속 평균값은 낮으면 좋은 군집화 조건이 아닙니다.
◎ 붓꽃 데이터 세트를 이용한 군집 평가¶
In [5]:
from sklearn.preprocessing import scale
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
# 실루엣 분석 metric 값을 구하기 위한 API 추가
from sklearn.metrics import silhouette_samples, silhouette_score
%matplotlib inline
iris = load_iris()
feature_names = ['sepal_length','sepal_width','petal_length','petal_width']
irisDF = pd.DataFrame(data=iris.data, columns=feature_names)
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300,random_state=0).fit(irisDF)
irisDF['cluster'] = kmeans.labels_
# iris 의 모든 개별 데이터에 실루엣 계수값을 구함.
score_samples = silhouette_samples(iris.data, irisDF['cluster'])
print('silhouette_samples( ) return 값의 shape' , score_samples.shape)
# irisDF에 실루엣 계수 컬럼 추가
irisDF['silhouette_coeff'] = score_samples
# 모든 데이터의 평균 실루엣 계수값을 구함.
average_score = silhouette_score(iris.data, irisDF['cluster'])
print('붓꽃 데이터셋 Silhouette Analysis Score:{0:.3f}'.format(average_score))
irisDF.head(3)
silhouette_samples( ) return 값의 shape (150,)
붓꽃 데이터셋 Silhouette Analysis Score:0.553
Out[5]:
sepal_length | sepal_width | petal_length | petal_width | cluster | silhouette_coeff | |
---|---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | 1 | 0.852955 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | 1 | 0.815495 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 1 | 0.829315 |
In [6]:
# 그룹별 실루엣 계수 평균 값
irisDF.groupby('cluster')['silhouette_coeff'].mean()
Out[6]:
cluster
0 0.417320
1 0.798140
2 0.451105
Name: silhouette_coeff, dtype: float64
◎ 군집별 평균 실루엣 계수의 시각화를 통한 군집 개수 최적화 방법¶
- 전체 데이터의 평균 실루엣 계수 값이 높다고 해서 반드시 최적의 군집 개수로 군집화가 잘 됐다고 볼수는 없습니다.
- 개별 군집별로 적당히 분리된 거리를 유지하면서도 군집 내의 데이터가 서로 뭉쳐 있는 경우에 K-평균의 적절한 군집 개수가 설정됐다고 판단할 수 있습니다.
In [7]:
### 여러개의 클러스터링 갯수를 List로 입력 받아 각각의 실루엣 계수를 면적으로 시각화한 함수 작성
def visualize_silhouette(cluster_lists, X_features):
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import math
# 입력값으로 클러스터링 갯수들을 리스트로 받아서, 각 갯수별로 클러스터링을 적용하고 실루엣 개수를 구함
n_cols = len(cluster_lists)
# plt.subplots()으로 리스트에 기재된 클러스터링 수만큼의 sub figures를 가지는 axs 생성
fig, axs = plt.subplots(figsize=(4*n_cols, 4), nrows=1, ncols=n_cols)
# 리스트에 기재된 클러스터링 갯수들을 차례로 iteration 수행하면서 실루엣 개수 시각화
for ind, n_cluster in enumerate(cluster_lists):
# KMeans 클러스터링 수행하고, 실루엣 스코어와 개별 데이터의 실루엣 값 계산.
clusterer = KMeans(n_clusters = n_cluster, max_iter=500, random_state=0)
cluster_labels = clusterer.fit_predict(X_features)
sil_avg = silhouette_score(X_features, cluster_labels)
sil_values = silhouette_samples(X_features, cluster_labels)
y_lower = 10
axs[ind].set_title('Number of Cluster : '+ str(n_cluster)+'\n' \
'Silhouette Score :' + str(round(sil_avg,3)) )
axs[ind].set_xlabel("The silhouette coefficient values")
axs[ind].set_ylabel("Cluster label")
axs[ind].set_xlim([-0.1, 1])
axs[ind].set_ylim([0, len(X_features) + (n_cluster + 1) * 10])
axs[ind].set_yticks([]) # Clear the yaxis labels / ticks
axs[ind].set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
# 클러스터링 갯수별로 fill_betweenx( )형태의 막대 그래프 표현.
for i in range(n_cluster):
ith_cluster_sil_values = sil_values[cluster_labels==i]
ith_cluster_sil_values.sort()
size_cluster_i = ith_cluster_sil_values.shape[0]
y_upper = y_lower + size_cluster_i
color = cm.nipy_spectral(float(i) / n_cluster)
axs[ind].fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_sil_values, \
facecolor=color, edgecolor=color, alpha=0.7)
axs[ind].text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
axs[ind].axvline(x=sil_avg, color="red", linestyle="--")
In [8]:
# make_blobs 을 통해 clustering 을 위한 4개의 클러스터 중심의 500개 2차원 데이터 셋 생성
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=500, n_features=2, centers=4, cluster_std=1, \
center_box=(-10.0, 10.0), shuffle=True, random_state=1)
# cluster 개수를 2개, 3개, 4개, 5개 일때의 클러스터별 실루엣 계수 평균값을 시각화
visualize_silhouette([ 2, 3, 4, 5], X)
- 실루엣 계수를 통한 K-평균 군집 평가 방법은 직관적으로 이해하기 쉽지만, 각 데이터별로 다른 데이터와의 거리를 반복적으로 계산해야 하므로 데이터 양이 늘어나면 수행 시간이 크게 늘어납니다.
- 시간이 오래걸릴 경우 군집별로 임의의 데이터를 샘플링해 실루엣 계수를 평가하는 방안을 고민해야 합니다.
03. 평균 이동¶
◎ 평균 이동(Mean Shift)의 개요¶
- 평균 이동은 K-평균과 유사하게 중심을 군집의 중심으로 지속적으로 움직이면서 군집화를 수행합니다.
- K-평균이 중심에 소속된 데이터의 평균 거리 중심으로 이동하는 데 반해, 평균 이동은 중심을 데이터가 모여 있는 밀도가 가장 높은 곳으로 이동시킵니다.
- 평균 이동 군집화는 데이터의 분포도를 이용해 군집 중심점을 찾습니다. 군집 중심점은 확률 밀도 함수를 이용해 찾습니다.
- 일반적으로 주어진 모델의 확률 밀도 함수를 찾기 위해서 KDE(Kernel Density Estimation)를 이용합니다.
- 평균 이동 군집화는 특정 데이터를 반경 내의 데이터 분포 확률 밀도가 가장 높은 곳으로 이동하기 위해 주변 데이터와의 거리 값을 KDE 함수 값으로 입력한 뒤 그 반환 값을 현재 위치에서 업데이트하면서 이동하는 방식을 취합니다.
- KDE는 커널 함수를 통해 어떤 변수의 확률 밀도 함수를 추정하는 대표적인 방법입니다. KDE는 개별 관측 데이터에 커널 함수를 적용한 뒤, 이 적용 값을 모두 더한 후 개별 관측 데이터의 건수로 나눠 확률 밀도 함수를 추정하며, 대표적인 커널 함수로서 가우시안 분포 함수가 사용됩니다.
- 대역폭 h는 KDE 형태를 부드러운 형태로 평활화하는 데 적용되며, 이 h를 어떻게 설정하느냐에 따라 확률 밀도 추정 성능을 크게 좌우할 수 있습니다. 작은 h 값은 과적합하기 쉬워 많은 수의 군집 중심점을 가지며 큰 h 값은 과소적합하기 쉬워 적은 수의 군집 중심점 가집니다.
- 사이킷런은 최적의 대역폭 계산을 위해 estimate_bandwidth() 함수를 제공
In [9]:
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import MeanShift
X, y = make_blobs(n_samples=200, n_features=2, centers=3,
cluster_std=0.7, random_state=0)
import pandas as pd
from sklearn.cluster import estimate_bandwidth
clusterDF = pd.DataFrame(data=X, columns=['ftr1', 'ftr2'])
clusterDF['target'] = y
# estimate_bandwidth()로 최적의 bandwidth 계산
best_bandwidth = estimate_bandwidth(X)
# 최적의 대역폭을 활용한 군집화
meanshift= MeanShift(bandwidth=best_bandwidth)
cluster_labels = meanshift.fit_predict(X)
print('cluster labels 유형:',np.unique(cluster_labels))
cluster labels 유형: [0 1 2]
- 평균 이동의 장점은 데이터 세트의 형태를 특정 형태로 가정한다든가, 특정 분포도 기반의 모델로 가정하지 않기 때문에 좀 더 유연한 군집화가 가능합니다. 또한 이상치의 영향력도 크지 않으며, 미리 군집의 개수를 정할 필요도 없습니다.
- 하지만 알고리즘의 수행 시간이 오래 걸리고 무엇보다도 bandwidth의 크기에 따른 군집화 영향도가 매우 큽니다. 이런 특징 때문에 분석 업무 기반의 데이터 세트보다는 컴퓨터 비전 영역에서 더 많이 사용됩니다.
- 이미지나 영상 데이터에서 특정 개체를 구분하거나 움직임을 추적하는 데 뛰어난 역할을 수행하는 알고리즘입니다.
04. GMM(Gaussian Mixture Model)¶
◎ GMM 소개¶
- GMM 군집화는 군집화를 적용하고자 하는 데이터가 여러 개의 가우시안 분포를 가진 데이터 집합들이 섞여서 생성된 것이라는 가정하에 군집화를 수행하는 방식입니다.
- 정규 분포로도 알려진 가우시안 분포는 좌우 대칭형의 종 형태를 가진 연속 활률 함수입니다.
- 전체 데이터 세트는 서로 다른 정규 분포 형태를 가진 여러 가지 확률 분포 곡선으로 구성됭 수 있으며, 이러한 서로 다른 정규 분포에 기반해 군집화를 수행하는 것이 GMM 군집화 방식입니다.
- 개별 데이터가 어떤 정규 분포에 속하는지 결정하는 방식이 GMM에서는 모수 추정이라고 하는데, 모수 추정은 대표적으로 2가지를 추정하는 것입니다.
-
- 개별 정규 분포의 평균과 분산, 2. 각 데이터가 어떤 정규 분포에 해당되는지의 확률
- 이러한 모수 추정을 위해 GMM은 EM(Expectation and Maximization) 방법을 적용합니다. 이를 위해 사이킷런은 GaussianMixture 클래스를 지원합니다.
◎ GMM을 이용한 붓꽃 데이터 세트 군집화¶
- GMM은 확률 기반 군집화이고 K-평균은 거리 기반 군집화입니다.
In [10]:
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
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
- 붓꽃 데이터 세트에 대한 GMM 군집화 결과가 K-평균 군집화 결과보다 더 잘 분류됐음을 알 수 있습니다. 이는 어떤 알고리즘에 더 뛰어나다는 의미가 아니라 붓꼿 데이터 세트가 GMM 군집화에 더 효과적이라는 의미입니다.
◎ GMM과 K-평균의 비교¶
- KMeans는 원형의 범위에서 군집화를 수행합니다. 데이터 세트가 원형의 범위를 가질수록 KMeans의 군집화 효율은 더욱 높아집니다.
- KMeans는 데이터가 길쭉한 타원형으로 늘어선 경우에 군집화를 잘 수행하지 못합니다.
In [11]:
### 클러스터 결과를 담은 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()
In [12]:
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)
In [13]:
# 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)
In [14]:
# 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)
In [15]:
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
05. DBSCAN¶
◎ DBSCAN 개요¶
- DBSCAN은 간단하고 직관적인 알고리즘으로 데이터의 분포가 기하학적으로 복잡한 데이터 세트에도 효과적인 군집화가 가능합니다.
- DBSCAN을 구정하는 가장 중요한 두 가지 파라미터는 입실론 주변 영역(= 개별 데이터를 중심으로 입실론 반경을 가지는 원형의 영역)과 최소 데이터 개수(= 개별 데이터의 입실론 주변 영역에 포함되는 타 데이터의 개수)입니다.
◎ DBSCAN 적용하기¶
- DBSCAN을 적용할 때는 특정 군집 개수로 군집을 강제하지 않는 것이 좋습니다. 또한 eps와 min_samples 파라미터를 통해 최적의 군집을 찾는 게 중요합니다.
- 일반적으로 eps의 값을 크게 하면 반경이 커져 포함하는 데이터가 많아지므로 노이즈 데이터 개수가 작아집니다. min_samples를 크게 하면 주어진 반경 내에서 더 많은 데이터를 포함시켜야 하므로 노이즈 데이터 개수가 커지게 됩니다. 데이터 밀도가 더 커져야 하는데, 매우 촘촘한 데이터 분포가 아닌 경우 노이즈로 인식하기 때문입니다.
06. 군집화 실습 - 고객 세그먼테이션¶
◎ 고객 세그먼테이션의 정의와 기법¶
- 고객 세그먼테이션은 다양한 기준으로 고객을 분류하는 기법을 지칭합니다.
- 기본적인 고객 분석 요소인 RFM 기법을 많이 이용합니다. RFM 기법은 Recency(= 가장 최근 상품 구입 일에서 오늘까지의 시간), Frequency(= 상품 구매 횟수), Monetary Value(= 총 구매 금액)으로 이루어져있습니다.
- 생략
In [16]:
### 여러개의 클러스터링 갯수를 List로 입력 받아 각각의 클러스터링 결과를 시각화
def visualize_kmeans_plot_multi(cluster_lists, X_features):
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
# plt.subplots()으로 리스트에 기재된 클러스터링 만큼의 sub figures를 가지는 axs 생성
n_cols = len(cluster_lists)
fig, axs = plt.subplots(figsize=(4*n_cols, 4), nrows=1, ncols=n_cols)
# 입력 데이터의 FEATURE가 여러개일 경우 2차원 데이터 시각화가 어려우므로 PCA 변환하여 2차원 시각화
pca = PCA(n_components=2)
pca_transformed = pca.fit_transform(X_features)
dataframe = pd.DataFrame(pca_transformed, columns=['PCA1','PCA2'])
# 리스트에 기재된 클러스터링 갯수들을 차례로 iteration 수행하면서 KMeans 클러스터링 수행하고 시각화
for ind, n_cluster in enumerate(cluster_lists):
# KMeans 클러스터링으로 클러스터링 결과를 dataframe에 저장.
clusterer = KMeans(n_clusters = n_cluster, max_iter=500, random_state=0)
cluster_labels = clusterer.fit_predict(pca_transformed)
dataframe['cluster']=cluster_labels
unique_labels = np.unique(clusterer.labels_)
markers=['o', 's', '^', 'x', '*']
# 클러스터링 결과값 별로 scatter plot 으로 시각화
for label in unique_labels:
label_df = dataframe[dataframe['cluster']==label]
if label == -1:
cluster_legend = 'Noise'
else :
cluster_legend = 'Cluster '+str(label)
axs[ind].scatter(x=label_df['PCA1'], y=label_df['PCA2'], s=70,\
edgecolor='k', marker=markers[label], label=cluster_legend)
axs[ind].set_title('Number of Cluster : '+ str(n_cluster))
axs[ind].legend(loc='upper right')
plt.show()
07. 정리¶
- 각 군집화 기법은 나름의 장/단점을 가지고 있으며, 군집화하려는 데이터의 특성에 맞게 선택해야 합니다.
- K-평균의 경우 거리 기반으로 군집 중심점을 이동시키면서 군집화를 수행합니다. 매우 쉽고 직관적인 알고리즘으로 많은 군집화 애플리케이션에서 애용되지만, 복잡한 구조를 가지는 데이터 세트에 적용하기에는 한계가 있으며, 군집의 개수를 최적화하기가 어렵습니다. K-평균은 군집이 잘 되었는지의 평가를 위한 실루엣 계수를 이용합니다,
- 평균 이동(Mean Shift)은 거리 중심이 아니라 데이터가 모여 있는 밀도가 가장 높은 쪽으로 군집 중심점을 이동하면서 군집화를 수행합니다. 일반 업무 기반의 정형 데이터 세트보다는 컴퓨터 비전 영역에서 이미지나 영상 데이터에서 특정 개체를 구분하거나 움직임을 추적하는 데 뛰어난 역할을 수행하는 알고리즘입니다.
- GMM 군집화는 군집화를 적용하고자 하는 데이터가 여러 개의 가우시안 분포 모델을 섞어서 생성된 모델로 가정해 수행하는 방식입니다. 전체 데이터 세트에서 서로 다른 정규 분포 형태를 추출해 이렇게 다른 정규 분포를 가진 데이터 세트를 각각 군집화하는 것입니다. GMM의 경우는 K-평균보다 유연하게 다양한 데이터 세트에 잘 적용될 수 있다는 장점과 군집화를 위한 수행 시간이 오래 걸린다는 단점이 있었습니다.
- DBSCAN은 밀도 기반 군집화의 대표적인 알고리즘입니다. DBSCAN은 입실론 주변 영역 내에 포함되는 최소 데이터 개수의 충족 여부에 따라 데이터 포인트를 핵심 포인트, 이웃 포인트, 경계 포인트, 잡음 포인트로 구분하고 특정 핵심 포인트에서 직접 접근이 가능한 다른 핵심 포인트를 서로 연결하면서 군집화를 구성하는 방식입니다. DBSCAN은 간단하고 직관적인 알고리즘으로 돼 있음에도 데이터의 분포가 기하학적으로 복잡한 데이터 세트에도 효과적인 군집화가 가능합니다.
In [17]:
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:80% !important;}</style>"))
728x90
'Book report > 파이썬 머신러닝 완벽가이드' 카테고리의 다른 글
[파이썬 머신러닝 완벽가이드] 08. 텍스트 분석(2) (1) | 2023.06.06 |
---|---|
[파이썬 머신러닝 완벽가이드] 08. 텍스트 분석(1) (0) | 2023.06.06 |
[파이썬 머신러닝 완벽가이드] 06. 차원 축소 (0) | 2022.09.12 |
[파이썬 머신러닝 완벽가이드] 05. 회귀 (0) | 2022.09.11 |
[파이썬 머신러닝 완벽가이드] 04. 분류 (0) | 2022.04.24 |