2024. 3. 31. 15:32ㆍDATA/BIGDATA
실루엣 계수와 엘보우는 모두 군집화(clustering)에서 사용되는 평가 기준이다.
군집화 결과를 평가하고, 최적의 군집 수를 결정하기 위해 사용되며 비지도 학습 기법으로 레이블이 주어지지 않은 데이터에 대해 군집화 품질을 평가한다.
■차이점
1. 평가 기준의 종류:
- 실루엣 계수(Silhouette Coefficient): 각 데이터 포인트의 군집 내의 응집력(cohesion)과 군집 간의 분리력(separation)을 측정하여 전체 군집화의 품질을 평가한다. 값이 높을수록 군집화가 더 좋다.
- 엘보우 방법(Elbow Method): 군집 내의 분산(혹은 오차 제곱합)과 군집 간의 분산 비율을 사용하여 군집 수를 선택한다. 이 방법은 군집 수가 증가함에 따라 군집 내 분산은 계속 감소하나, 감소폭이 감소하는 지점을 찾아 최적의 군집 수를 결정한다.
2. 평가 방법:
- 실루엣 계수: 각 데이터 포인트의 실루엣 계수를 계산하고, 이를 평균하여 전체 군집화의 품질을 평가한다.
- 엘보우 방법: 군집 수를 변화시켜가며 각 군집화의 군집 내 분산을 계산하고, 이를 시각화하여 팔꿈치(elbow) 모양의 그래프를 얻는다. 이 그래프에서 군집 수가 증가함에 따라 군집 내 분산 감소폭이 가장 크게 감소하는 지점을 찾다.
실루엣 계수와 엘보우 방법은 각각 군집화 품질을 다르게 측정하고, 이에 따라 최적의 군집 수를 선택한다. 따라서 두 가지 방법을 함께 사용하여 보다 신뢰성 있는 군집 수를 결정할 수도 있다.
■ Silhouette formula
각 데이터 포인트의 실루엣 계수는 해당 포인트가 속한 군집 내의 응집력(cohesion)과 다른 군집과의 분리력(separation)을 기반으로 계산된다.
1. 군집 할당: 먼저, 주어진 데이터셋을 이용하여 군집화 알고리즘을 실행하여 각 데이터 포인트가 어떤 군집에 속하는지 결정한다.
2. 군집 내 응집력 계산: 각 데이터 포인트마다 해당 군집 내에서 다른 포인트와의 거리를 측정한다. 일반적으로 평균 거리를 사용한다. 이 값은 a(i)로 표기한다.
3. 군집 간 분리력 계산: 각 데이터 포인트마다 해당 군집과 가장 가까운 다른 군집까지의 평균 거리를 계산한다. 이 값은 b(i)로 표기한다.
4. 전체 데이터 포인트의 실루엣 계수 평균 계산: 모든 데이터 포인트의 실루엣 계수를 합산하여 데이터 포인트 수로 나누어 전체 군집화의 실루엣 계수를 계산한다.
\[ s(i) = \frac{b(i) - a(i)}{\max(a(i), b(i))} \]
여기서:
- \( s(i) \) : 데이터 포인트 \( i \)의 실루엣 계수
- \( a(i) \) : 데이터 포인트 \( i \)가 속한 군집 내의 평균 거리(cohesion)
- \( b(i) \) : 데이터 포인트 \( i \)가 속한 군집과 가장 가까운 다른 군집까지의 평균 거리(separation)
- \( \max(a(i), b(i)) \) : \( a(i) \)와 \( b(i) \) 중 큰 값
실루엣 계수는 보통 -1에서 1 사이의 값을 가지며,
- 1에 가까울수록 해당 데이터 포인트는 잘 할당된 군집 내에 위치하고 있음을 의미한다.
- 0에 가까울수록 군집 경계에 위치하거나 군집 내/외의 거리가 비슷함을 나타낸다.
- -1에 가까울수록 해당 데이터 포인트는 다른 군집에 더 가까이 있음을 의미한다.
클러스터링 품질을 게산하여 나온 실루엣 계수가 높을수록 군집화 결과가 좋다고 평가된다.
-k-means 군집화 알고리즘을 적용하여 실루엣 계수를 계산하여 출력
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.metrics import silhouette_score
#iris dataset 불러오고 데이터와 컬럼 이름 추출
iris = load_iris()
X=iris.data
columns=iris.feature_names
#데이터 프레임 변환
df = pd.DataFrame(X, columns=columns)
#군집 개수 범위 지정 및 실루엣 계수 계산
cluster_range=range(2,11)
#실루엣 계수 저장 리스트
silhouette_scores=[]
#각 군집 개수에 대해 keams 알고리즘을 실행하고 실루엣 계수를 계산하여 리스트에 저장
for k in cluster_range:
kmeans=KMeans(n_clusters=k,random_state=0,n_init=10)
cluster_labels=kmeans.fit_predict(df)
silhouette_avg=silhouette_score(df,cluster_labels)
silhouette_scores.append(silhouette_avg)
#실루엣 계수 그래프
plt.plot(cluster_range, silhouette_scores, marker='o')
plt.title('silhouette Method for iris dataset')
plt.xlabel('number of cluster')
plt.ylabel('silhouette score')
plt.xticks(cluster_range)
plt.show()
#실루엣 계수와 군집 개수 결과 데이터프레임 출력
result_df=pd.DataFrame({
'number of cluster':list(cluster_range),
'silhouette Score':silhouette_scores
})
print(results_df)
- 최적의 클러스터 개수: 실루엣 점수가 2일 때 0.65로 가장 높으며 데이터가 2개의 클러스터로 가장 잘 분리된다는 것을 의미한다.
- 클러스터 개수가 3일 때: 실루엣 점수가 0.55로 약간 낮아지지만 여전히 괜찮은 클러스터링 품질을 보인다.
- 클러스터 개수가 증가할수록: 실루엣 점수가 점진적으로 감소한다. 이는 클러스터 개수가 많아질수록 클러스터링 품질이 떨어짐을 나타낸다.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.metrics import silhouette_score, silhouette_samples
from sklearn.preprocessing import scale
iris= load_iris()
X=iris.data
y=iris.target
columns=iris.feature_names
df= pd.DataFrame(X,columns=columns)
df
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.metrics import silhouette_score, silhouette_samples
# Iris 데이터셋 불러오기
iris = load_iris()
X = iris.data
columns = iris.feature_names
# Iris 데이터를 데이터프레임으로 변환
df = pd.DataFrame(X, columns=columns)
# 클러스터 개수 리스트 지정
cluster_list = [2, 3, 4, 5, 6, 7, 8, 9, 10]
silhouette_scores = []
# 각 클러스터 개수에 대해 k-means 알고리즘 실행 및 실루엣 점수 계산
for k in cluster_list:
kmeans = KMeans(n_clusters=k, random_state=0, n_init=10)
cluster_labels = kmeans.fit_predict(df)
silhouette_avg = silhouette_score(df, cluster_labels)
silhouette_scores.append(silhouette_avg)
# 실루엣 샘플 값 계산
sample_silhouette_values = silhouette_samples(df, cluster_labels)
# 실루엣 그래프 그리기
fig, ax1 = plt.subplots(1, 1)
fig.set_size_inches(7, 5)
# y 축 시작 위치
y_lower = 10
for i in range(k):
# 현재 클러스터 i에 속한 데이터 포인트의 실루엣 값을 추출
ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
# 분포를 정렬
ith_cluster_silhouette_values.sort()
# 현재 클러스터에 속한 데이터 포인트 개수 계산
size_cluster_i = ith_cluster_silhouette_values.shape[0]
# y 축 상단 위치 설정 (현재 y 축 위치 + 클러스터 크기)
y_upper = y_lower + size_cluster_i
# 클러스터마다 고유한 색상 지정
color = plt.cm.nipy_spectral(float(i) / k)
ax1.fill_betweenx(np.arange(y_lower, y_upper),
0, ith_cluster_silhouette_values,
facecolor=color, edgecolor=color, alpha=0.7)
ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
ax1.set_title(f"Silhouette plot for {k} clusters")
ax1.set_xlabel("Silhouette coefficient values")
ax1.set_ylabel("Cluster label")
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
ax1.set_yticks([])
ax1.set_xticks(np.arange(-0.1, 1.1, 0.2))
plt.savefig(f'silhouette_{k}_clusters.png')
plt.show()
# 군집 개수와 실루엣 점수를 데이터 프레임으로 저장 후 출력
result_df = pd.DataFrame({
'Number of Clusters': cluster_list,
'Silhouette Score': silhouette_scores
})
print(result_df)
2개의 군집으로 나눴을 때 실루엣 점수가 가장 높아, 다른 개수의 군집과 비교했을 때 가장 우수한 군집화를 나타낸다.
□ eg.
클러스터링을 위해 고객들의 구매 패턴을 분석한다고 가정하면 데이터프레임 `df`에는 각 고객의 구매 이력이며 각 행은 고객을 나타내고, 열은 다양한 구매 특징을 나타낼 수 있다. K-means 클러스터링을 사용하여 각 고객에게 클러스터 번호가 지정된다. 그리고`cluster_labels`의 각 고객에게 할당된 클러스터 레이블을 사용하여 `silhouette_score` 함수를 호출하여 실루엣 점수를 계산할 수 있다. 이 점수는 클러스터링 결과의 품질을 나타내며, 이 값을 평균화하여 전체 데이터셋에 대한 평균 실루엣 점수를 얻을 수 있다. 이 값은 `silhouette_avg`에 저장된다. 결과적으로 각 고객이 속한 클러스터의 유사성과 클러스터 간의 구분이 얼마나 잘 이루어졌는지에 대한 정보를 얻을 수 있다.
■ Elbow Method formula
엘보우 방법(Elbow Method)은 군집의 개수를 결정하기 위한 방법 중 하나로, 군집 내 분산(inertia 또는 오차 제곱합)이 군집의 개수에 따라 어떻게 변하는지를 관찰하여 최적의 군집 수를 결정한다. 이를 위해 다음과 같은 공식을 사용한다:
▷ Inertia
"Inertia"는 군집화에서 군집 내 분산을 나타내는 지표이다. 군집화의 목표는 각 데이터 포인트를 서로 유사한 군집에 할당하여 군집 간 분산을 최대한 크게, 군집 내 분산을 최대한 작게 만드는 것이다. Inertia는 군집 내 분산을 측정하는 방법 중 하나로, 각 데이터 포인트와 해당 군집의 중심(centroid) 사이의 거리의 제곱을 모두 더한 값이다.
즉, inertia는 군집 내 데이터 포인트들이 군집의 중심 주변에 모여 있는 정도를 나타낸다. 이 값이 작을수록 각 군집 내 데이터 포인트들이 중심 주변에 밀집되어 있고, 군집 간 분산이 커지게 되면 군집화의 품질이 높다는 것을 의미한다.
엘보우 방법에서는 군집의 개수를 변화시키면서 inertia 값을 계산하고, inertia 값이 감소하는 속도가 둔화되는 지점을 찾아 최적의 군집 개수를 결정한다. 이 지점에서는 군집 내 분산의 감소와 군집 개수의 증가 사이의 균형을 고려하여 적절한 군집 수를 선택할 수 있다.
\[ W(k) = \sum_{i=1}^{k} \frac{1}{n_i} \sum_{x \in C_i} ||x - \mu_i||^2 \]
여기서:
- \( W(k) \) : \( k \) 개의 군집을 사용했을 때의 전체 군집 내 분산
- \( k \) : 군집의 개수
- \( n_i \) : \( i \)번째 군집에 속한 데이터 포인트의 수
- \( C_i \) : \( i \)번째 군집에 속한 데이터 포인트의 집합
- \( \mu_i \) : \( i \)번째 군집의 중심(평균)
엘보우 방법에서는 \( k \) 값을 변화시키면서 \( W(k) \) 값을 계산하고, 이를 그래프로 나타내어 군집의 개수에 따른 군집 내 분산의 변화를 시각적으로 확인한다. 그래프에서 군집 개수가 증가함에 따라 군집 내 분산이 급격히 감소하다가 변화의 폭이 감소하는 지점이 생기는데, 이 지점이 엘보우(elbow)로 볼 수 있다. 이 지점에서 군집 내 분산의 감소가 둔화되므로, 군집 수를 해당 지점의 군집 수로 선택하는 것이 일반적으로 좋은 군집화 결과를 얻을 수 있는 방법이다.
가로축(x축)에 군집의개수, 세로축(y축)에 오차제곱합(SSE, 군집 내 분산(SSE, Sum of Squared Errors) )을 그래프로 나타내어 군집의 개수에 따른 군집 내 분산의 변화를 시각적으로 확인한다.
기울기가 완만해지는 부분에 해당하는 군집의 개수를 선택한다. 팔꿈치 부분에는 평균거리가 더 이상 많이 감소하지 않는다. 추가적인 군집을 생성해도 군집 내 분산의 큰 변화를 가져오지 않는다는 것을 의미한다. 군집의 개수를 증가시키더라도 모델의 성능이 크게 향상되지 않는다는 것을 나타낸다.
- k-means 군집화 알고리즘 적용 후 엘보우 방법으로 최적화의 군집 수를 결정하는 코드
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# 가상의 데이터 생성
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
# 군집 개수 범위 지정
cluster_range = range(1, 10)
# 군집 내 분산(SSE)를 저장할 리스트
sse = []
# 각 군집 개수에 대해 k-means 알고리즘을 실행하고 SSE를 계산하여 리스트에 저장
for k in cluster_range:
kmeans = KMeans(n_clusters=k, random_state=0)
kmeans.fit(X)
sse.append(kmeans.inertia_)
# SSE 그래프 그리기
plt.plot(cluster_range, sse, marker='o')
plt.title('Elbow Method')
plt.xlabel('Number of clusters')
plt.ylabel('SSE')
plt.xticks(cluster_range)
plt.show()
*make_blobs
scikit-learn 라이브러리의 make_blobs 함수를 사용하여 가상의 데이터를 생성하는 것이다. 여기서 make_blobs 함수는 클러스터링 문제를 시뮬레이션하기 위해 사용된다.
make_blobs 매개변수
- n_samples: 생성할 샘플의 개수이다. 여기서는 300개의 샘플이 생성된다.
- centers: 클러스터의 중심 개수이다. 여기서는 4개의 중심을 가진 클러스터 생성
데이터 포인트가 4개의 그룹 또는 군집으로 분할되어 있음을 의미한다. 클러스터링은 주어진 데이터를 서로 비슷한 속성을 가진 그룹으로 나누는 비지도 학습 기법이다. 각 클러스터는 해당 그룹에 속하는 데이터 포인트들의 중심을 나타내는 하나의 포인트(중심)로 표현된다. 데이터를 4개의 그룹으로 나누는 클러스터링 작업을 수행하면 각 중심은 해당 클러스터의 중심으로 사용되며, 클러스터링 알고리즘이 데이터를 이 중심 주변에 가장 가까운 클러스터로 할당한다.
- cluster_std: 클러스터의 표준 편차이다. 클러스터 내의 점들이 얼마나 밀집되어 있는지를 제어한다. 여기서는 0.60의 표준 편차를 가지는 클러스터가 생성된다.
- random_state: 데이터를 생성하는 데 사용되는 난수 발생기의 시드를 통해 생성된 데이터를 재현할 수 있다.
- make_blobs 함수가 생성한 데이터를 변수 X에 할당하고, 두 번째 반환 값은 사용하지 않으므로 언더스코어 _로 표시되어 무시된다.
따라서, X에는 300개의 데이터 포인트가 포함되어 있고, 각각은 4개의 클러스터 중 하나에 속하는데, 클러스터들은 표준 편차가 0.60인 가우시안 분포를 따른다.
'DATA > BIGDATA' 카테고리의 다른 글
특징 공학(feature engineering)을 통한 교호작용 (0) | 2024.03.31 |
---|---|
선형 회귀 모델에서 교호작용 (0) | 2024.03.31 |
BIAS (0) | 2024.03.30 |
Jaccard Distance (0) | 2024.03.28 |
t 통계량과 F 통계량을 분석함으로써 알고자하는 결과 (0) | 2024.03.27 |