본문 바로가기

ML with SckitLearn

Kmeans의 K값을 정하는 기준 : Elbow Method, Silhouette Score(실루엣 스코어)

반응형

K-means 알고리즘의 적정의 K값을 선택하는 어려움이 있습니다. 다양한 방법으로 최적의 K를 구하는 방법이 있습니다. 이 중 가장 보편적으로 사용하는 Elbow Method, Silhouette Score에 대해 알아보겠습니다.

 


Elbow Method

 

가장 보편적으로 이용되는 방법으로 클러스터 내의 총 변동을 설명하는 WCSS(Within Clusters Sum of Squares)를 이용합니다. 

 

WCSS= ∑Pi in Cluster1 distance (Pi C1)2 +∑Pi in Cluster2distance (Pi C2)2+∑Pi in CLuster3 distance (Pi C3)2

 

다음의 방법으로 이용합니다.

1. 사용하고자 하는 클러스터 범위를 지정한다.

2. 각 클러스터를 WCSS방법으로 계산을 합니다.

3. WCSS값과 클러스터 K 갯수에 대한 커브선을 그립니다.

4. 뾰족하게 구부러진 부분이나 특정 지점이 팔처럼 굽어지는 부분을 K로 지정합니다. 

 

 

def visualize_elbowmethod(data, param_init='random', param_n_init=10, param_max_iter=300):
    distortions = []
    for i in range(1, 10):
        km = KMeans(n_clusters=i, init=param_init, n_init=param_n_init, max_iter=param_max_iter, random_state=0)
        km.fit(data)
        distortions.append(km.inertia_)

    plt.plot(range(1, 10), distortions, marker='o')
    plt.xlabel('Number of Cluster')
    plt.ylabel('Distortion')
    plt.show()

 

 


Silhouette Score

 

실루엣 값은 개체가 다른 클러스터(seperation)에 비해 자신의 클러스터(cohesion)와 얼마나 유사한 지 측정합니다. 실루엣 범위는 -1에서 +1까지이며, 값이 높으면 객체가 자체 클러스터와 잘 일치하고 인접 클러스터와 잘 일치하지 않음을 나타냅니다. 대부분의 개체에 높은 값이 있으면 클러스터링 구성이 적합합니다. 많은 포인트의 값이 낮거나 음수이면 클러스터링 구성에 클러스터가 너무 많거나 적을 수 있습니다.

 

아래의 예시는 가장 높은 실루엣값이 있는 0.374에 매핑되는 클러스터 K=3이 적정하다는 것을 보여줍니다.

def visualize_silhouette_layer(data, param_init='random', param_n_init=10, param_max_iter=300):
    clusters_range = range(2,15)
    results = []

    for i in clusters_range:
        clusterer = KMeans(n_clusters=i, init=param_init, n_init=param_n_init, max_iter=param_max_iter, random_state=0)
        cluster_labels = clusterer.fit_predict(data)
        silhouette_avg = silhouette_score(data, cluster_labels)
        results.append([i, silhouette_avg])

    result = pd.DataFrame(results, columns=["n_clusters", "silhouette_score"])
    pivot_km = pd.pivot_table(result, index="n_clusters", values="silhouette_score")

    plt.figure()
    sns.heatmap(pivot_km, annot=True, linewidths=.5, fmt='.3f', cmap=sns.cm._rocket_lut)
    plt.tight_layout()
    plt.show()
반응형