k-means clustering

1. k-means clustering이란

K-means 클러스터링은 비지도학습(Unsupervised Learning)의 한 종류로, 데이터를 그룹화하는 클러스터를 생성하는 알고리즘입니다. 주어진 데이터를 유사한 특성을 가진 클러스터로 나누는 것이 목표입니다. 예를 들어, 고객 구매 패턴이나 이미지 특성 분석 등 다양한 분야에서 활용됩니다.

2. 작동 방식

K-means 알고리즘은 아래와 같은 단계로 작동

단계 1: 초기 중심점 설정

사용자가 지정한 클러스터의 개수(K)에 따라 랜덤한 중심점을 설정

단계 2: 데이터 할당

각 데이터 포인트를 가장 가까운 중심점에 할당합니다. 이를 통해 각 데이터는 가장 가까운 클러스터에 속하게 됨

단계 3: 중심점 업데이트

각 클러스터에 할당된 데이터 포인트들의 평균을 계산하여 새로운 중심점을 업데이트

단계 4: 반복

위 단계 2와 3을 반복하면서 중심점과 할당을 조정합니다. 더 이상 중심점과 할당이 변경되지 않을 때까지 반복

3. K-means의 장단점

장점:

  • 간단하고 빠른 알고리즘으로 대용량 데이터에도 적용 가능
  • 데이터의 구조를 파악하고 그룹화할 수 있어 데이터 마이닝에 유용
  • 클러스터의 개수(K)를 조정하여 원하는 결과를 얻을 수 있다

단점:

  • 초기 중심점의 설정에 따라 결과가 달라질 수 있다
  • 이상치(outlier)에 민감할 수 있다
  • 클러스터의 모양이 원형이 아닐 경우 성능이 저하될 수 있다

4. 활용 사례

K-means 클러스터링은 다양한 분야에서 활용

  • 고객 분류: 구매 패턴, 성향 등을 기반으로 고객을 그룹화하여 마케팅 전략 수립에 활용할 수 있습니다.
  • 이미지 분류: 이미지 특성을 기반으로 비슷한 특징을 가진 이미지들을 그룹화합니다.
  • 의료 데이터 분석: 환자 데이터를 분석하여 유사한 치료 결과를 가진 환자 그룹을 형성합니다.

5. 정리

  • K-means 클러스터링은 데이터 그룹화를 통해 데이터의 구조와 특성을 파악하는데 유용한 알고리즘
  • 초기 중심점 설정에 따른 결과 변동이 있을 수 있으며, 데이터의 특성에 따라 조정이 필요한 알고리즘
  • 데이터 마이닝, 고객 분류, 이미지 분류 등 다양한 분야에서 활용될 수 있어 중요한 알고리즘 중 하나로 꼽힘




Baseline

- 예시 데이터 [expanded_df]

MinMaxScaler() 처리한 데이터

  building_number 0 1 2 3 4 2034 2035 2036 2037 2038 2039
0 1 0.0726 0.0638 0.0469 0.0420 0.0496 0.4265 0.4064 0.3346 0.2407 0.1430 0.2684
1 2 0.2761 0.2671 0.2549 0.2517 0.2374 0.5766 0.5440 0.4774 0.4278 0.1909 0.3447
2 3 0.0711 0.0573 0.0566 0.0516 0.0561 0.5522 0.6666 0.6451 0.4704 0.1479 0.1038
97 98 0.1315 0.1212 0.1166 0.0984 0.1367 0.4937 0.4841 0.4510 0.4010 0.3051 0.1922
98 99 0.0887 0.0616 0.0465 0.0593 0.0563 0.5572 0.5381 0.5228 0.3756 0.2412 0.1638
99 100 0.0757 0.0402 0.0285 0.0197 0.0210 0.7710 0.5440 0.4685 0.4926 0.3224 0.2305

100 rows × 2041 columns

- K-means cluster code

cluster_df = pd.DataFrame(expanded_df)
X = cluster_df.drop('building_number', axis=1)  # building_number 열 제외한 데이터

# K-means 모델 생성 및 학습
num_clusters = 4
kmeans = KMeans(n_clusters=num_clusters, n_init=10, random_state=42)
clusters = kmeans.fit_predict(X)

# 군집 결과를 데이터프레임에 추가
cluster_df['cluster'] = kmeans.labels_
  • 결과 확인

    print(cluster_df['cluster'].value_counts().sort_index())
    
    # result
    cluster
    0    16
    1    11
    2    32
    3    41
    Name: count, dtype: int64
    
  • 실루엣 스코어

    # 실루엣 스코어 계산
    silhouette_avg = silhouette_score(X, cluster_df['cluster'])
    print("실루엣 스코어:", silhouette_avg)
    
    실루엣 스코어: 0.32784045970941667
    
  • 클러스터 시각화

    import matplotlib.pyplot as plt
    import seaborn as sns
    from sklearn.decomposition import PCA
      
    # 데이터프레임에서 cluster 열을 제외한 데이터 추출
    data = cluster_df.drop(['building_number','cluster'], axis=1)
      
    # 주성분 분석을 통해 데이터 2차원으로 축소
    pca = PCA(n_components=2) # n_components: 주성분 분석(PCA)에서 생성하려는 주성분의 개수를 지정하는 매개변수
    data_2d = pca.fit_transform(data)
      
    # 시각화
    plt.figure(figsize=(5, 4))
    sns.scatterplot(x=data_2d[:, 0], y=data_2d[:, 1], hue=cluster_df['cluster'], palette='Set1')
    plt.title('K-means Clustering Visualization')
    plt.xlabel('PCA 1')
    plt.ylabel('PCA 2')
    plt.legend()
    plt.show()
    

    image-20230817220647565

  • 클러스터링 결과 시각화

    # 클러스터 별로 subplot 생성
    num_clusters = len(cluster_df['cluster'].unique())
    fig, axes = plt.subplots(num_clusters, figsize=(30, 6 * num_clusters))
      
    for cluster_num, ax in zip(range(num_clusters), axes):
        cluster_data = cluster_df[cluster_df['cluster'] == cluster_num]
        cluster_data = cluster_data.drop(['building_number', 'cluster'], axis=1)
          
        for i, row in cluster_data.iterrows():
            ax.plot(range(len(row)), row, alpha=0.5)
      
        ax.set_title(f'Cluster {cluster_num} - {list(cluster_df[cluster_df["cluster"] == cluster_num]["building_number"])}')
        ax.set_xlabel('Index')
        ax.set_ylabel('Change')
      
        for i in range(0, len(expanded_df.loc[0].to_list()[1:]), 24):
            ax.axvline(x=i, color='red', linestyle='--', linewidth=0.5)
      
    plt.tight_layout()
    plt.show()
    

    image-20230817222232786

  • 최적 매개변수 찾기

    import matplotlib.pyplot as plt
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    from sklearn.preprocessing import StandardScaler
      
    # 데이터 준비
    cluster_df = pd.DataFrame(expanded_df)
    X = cluster_df.drop('building_number', axis=1)
      
    # 표준화 [스케일링이 된 데이터라면 생략]
    # scaler = StandardScaler()
    # X_scaled = scaler.fit_transform(X)
      
    X_scaled = X # 스케이링이 된 데이터이므로 X 그대로 사용
      
    # 엘보우 메서드를 통한 최적 군집 수 탐색
    inertia_values = []
    silhouette_scores = []
    possible_k_values = range(2, 21)
      
    for k in possible_k_values:
        kmeans = KMeans(n_clusters=k, n_init=10,random_state=42)
        kmeans.fit(X_scaled)
        inertia_values.append(kmeans.inertia_)
        silhouette_scores.append(silhouette_score(X_scaled, kmeans.labels_))
      
    # 엘보우 메서드 시각화
    plt.figure(figsize=(12, 6))
    plt.subplot(1, 2, 1)
    plt.plot(possible_k_values, inertia_values, marker='o')
    plt.xlabel('Number of Clusters')
    plt.ylabel('Inertia')
    plt.title('Elbow Method - Inertia')
      
    plt.subplot(1, 2, 2)
    plt.plot(possible_k_values, silhouette_scores, marker='o')
    plt.xlabel('Number of Clusters')
    plt.ylabel('Silhouette Score')
    plt.title('Elbow Method - Silhouette Score')
      
    plt.tight_layout()
    plt.show()
    

    image-20230817221332593



Metrics

- Silhouette Score

실루엣 스코어(Silhouette Score)는 군집화의 품질을 평가하는 지표 중 하나로, 각 데이터 포인트가 자신의 군집 내부의 거리와 다른 군집과의 거리를 얼마나 잘 반영하는지를 나타내는 값
이 스코어는 -1에서 1 사이의 값을 가지며, 높을수록 군집화의 품질이 좋다고 판단

실루엣 스코어는 다음과 같은 방식으로 계산:

  1. 개별 데이터 포인트에 대해 군집 내부 평균 거리(a)와 가장 가까운 다른 군집의 평균 거리(b)를 계산합니다. 이 때, a는 해당 포인트가 속한 군집 내의 다른 모든 포인트 간의 평균 거리를 의미하며, b는 해당 포인트와 가장 가까운 다른 군집 내의 모든 포인트 간의 평균 거리를 의미
  2. 실루엣 스코어는 (b - a)를 더 큰 값인 b와 나눈 후, max(a, b)와의 차이를 계산

따라서, 스코어가 높을수록 해당 포인트가 자신의 군집 내부의 거리는 가깝고 다른 군집과의 거리는 먼 것이므로 군집화의 품질이 좋다고 볼 수 있다. 반대로, 스코어가 낮을수록 군집화의 품질이 나쁘다고 판단

전체 데이터셋의 실루엣 스코어는 각 데이터 포인트의 실루엣 스코어의 평균으로 계산

- 1에 가까운 값: 클러스터가 잘 구분되어 있음을 나타낸다
- 0에 가까운 값: 클러스터링 결과가 중첩되거나, 클러스터링이 잘 이루어지지 않은 상태를 나타낸다
- 음수 값: 잘못된 클러스터링을 나타낸다

일반적으로 0.5 이상의 스코어는 좋은 군집화 품질을 나타내며, 그 이하의 경우 군집화가 잘못되었거나 데이터가 겹치는 영역이 있을 수 있다

- Inertia

Inertia는 클러스터 내 데이터들과 해당 클러스터의 중심 간의 거리의 합을 나타내는 지표

K-means 알고리즘에서 클러스터 내 데이터들이 중심에 얼마나 가깝게 모여있는지를 나타내는 값
Inertia가 작을수록 클러스터 내 데이터들이 중심에 가깝게 모여있으며, 클러스터링이 잘 이루어졌다고 볼 수 있다

엘보우 메서드를 사용할 때, Inertia는 클러스터 수가 증가함에 따라 계속해서 감소
이는 클러스터 수가 늘어나면 각 클러스터의 중심과의 거리가 더욱 줄어들기 때문이다.

그러나 클러스터 수가 증가하면 모든 데이터가 개별적인 클러스터로 할당될 수 있으므로, Inertia가 0에 가까워질 수 있다.
따라서 적절한 군집 수를 찾기 위해서는 Inertia의 변화를 보면서 기울기가 급격히 감소하는 지점인 ‘엘보우 포인트’를 찾게 되며, 엘보우 포인트에서 Inertia의 변화가 감소하는 속도가 둔해지며, 클러스터 수를 선택하는데 도움을 준다.

Reference


[scikit-learn Clustering] - https://scikit-learn.org/stable/modules/clustering.html
[sklearn.cluster.KMeans] - https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html

+ ChatGPT


태그:

카테고리:

업데이트:

댓글남기기