머신러닝

[군집화] #4. 평균이동

가뿡 2022. 7. 19. 10:23

* "파이썬 머신러닝 완벽 가이드" 서적, 여러 개인 블로그들을 참고한 개인 공부용입니다

 

평균 이동

평균 이동(Mean Shift)는 K-Means와 유사하게 중심을 군집의 중심으로 지속적으로 움직이며 군집화한다.

두 방법의 차이점은 중심을 이동하는 방법이다.

  • K-Means: 중심에 소속된 데이터의 평균 거리 중심으로 이동한다.
  • 평균 이동: 중심을 데이터가 모여 있는 밀도가 가장 높은 곳으로 이동한다.

과정

  1. 평균 이동은 KDE(Kernerl Density Estimation)를 이용해서 확률 밀도 함수를 구한다.
  2. 데이터가 집중적으로 모여있어 확률 밀도 함수가 피크인 점을 군집 중심점으로 선정한다.
  3. 이러한 방식을 전체 데이터에 반복적으로 적용하면서 데이터의 군집 중심점을 찾는다.

KDE(커널 밀도 추정)

KDE는 커널 함수를 통해 어떤 변수의 확률 밀도 함수를 추정하는 대표적인 방법이다.

개별 관측 데이터에 커널 함수를 적용한 뒤, 이 적용 값을 모두 더한 후 데이터의 건수로 나눠 확률 밀도 함수를 추정한다.

  • 대표적인 커널함수로 가우시안 분포 함수 사용
    • 대역폭 h: 값이 작은면 뾰족, 과적합 가능성. 값이 크면 완만, 과소적합 가능성

http://jun.hansung.ac.kr/PR/10%20Non-parametric%20Density%20Estimation.pdf

=>일반적으로 평균 이동 군집화는 대역폭이 클수록 적은 군집 중심점을 가지고, 작을수록 많은 군집 중심점을 가진다.

 

장점

  • K-Means와 달리 군집의 개수를 지정하지 않고 대역폭에 따라 군집화를 수행한다.
  • 데이터를 특정 형태로 가정하거나, 특정 분포 기반 모델로 가정하지 않으므로 유연한 군집화가 가능하다.
  • 이상치 영향이 크지 않다

단점

  • 알고리즘 수행 시간이 오래 걸리고 대역폭(bandwidth)의 크기에 따른 군집화 영향이 매우 크다.

 

from sklearn.datasets import make_blobs
from sklearn.cluster import MeanShift

# 클러스터 3개인 가상데이터
X, y = make_blobs(n_samples=200, n_features=2, centers=3, cluster_std=0.7, random_state=0)

# Mean Shift
meanshift = MeanShift(bandwidth=0.8)
cluster_labels = meanshift.fit_predict(X)

print(f"Mean Shift Cluster 유형: {np.unique(cluster_labels)}")
Mean Shift Cluster 유형: [0 1 2 3 4 5]
  • 군집이 3개인 데이터로 평균 이동을 했는데 군집이 6개로 지나치게 세분화되어 군집화되었다. => 대역폭 증가시킴

 

# Mean Shift
meanshift = MeanShift(bandwidth=1)
cluster_labels = meanshift.fit_predict(X)

print(f"Mean Shift Cluster 유형: {np.unique(cluster_labels)}")
Mean Shift Cluster 유형: [0 1 2]
  • 3개의 군집으로 이상적인 군집화
  • 대역폭에 따라 군집의 개수는 큰 영향을 받으므로 최적의 대역폭을 찾는 것이 중요하다.

 

from sklearn.cluster import estimate_bandwidth

bandwidth = estimate_bandwidth(X) # 최적의 대역폭 반환
print('bandwidth 값:', round(bandwidth,3))

meanshift = MeanShift(bandwidth = bandwidth)
cluster_labels = meanshift.fit_predict(X)
print('best bandwidth cluster labels 유형:',np.unique(cluster_labels))
bandwidth 값: 1.816 best bandwidth cluster labels 유형: [0 1 2]

 

 

# 데이터 프레임 생성
cluster_df = pd.DataFrame(data=X, columns=['ftr1', 'ftr2'])
cluster_df['target'] = y
cluster_df["meanshift_label"] = cluster_labels

# 클러스터별 중심 위치 좌표
centers = meanshift.cluster_centers_

# cluster 값 종류
unique_labels = np.unique(cluster_labels)

markers=['o', 's', '^', 'P','D','H','x']

for cluster in unique_labels:
    
    # 각 군집 시각화
    cluster_v = cluster_df[cluster_df['meanshift_label'] == cluster]    
    plt.scatter(x=cluster_v['ftr1'], y=cluster_v['ftr2'], edgecolor='k', marker=markers[cluster] )
    
    # 군집별 중심 위치 시각화
    center_xy = centers[cluster]
    
    plt.scatter(x = center_xy[0], y = center_xy[1], s=300, color='white',
                alpha=0.9, edgecolor='k', marker = markers[cluster])
    
    plt.scatter(x = center_xy[0], y = center_xy[1], s=70, color='k', 
                edgecolor='k', marker = f"${cluster}$")
    
    
plt.show()

 

cluster_df.groupby(['target','meanshift_label']).size()
target        meanshift_label
0                0                              67 
1                1                              67
2                2                              66
dtype: int64