K - 평균 군집 K -means Clustering
군집 Clustering
- 데이터를 여러개의 군집으로 묶는 분석 방법을 말하며 유사한 개체들을 군집으로 그룹화하여 각 집단의 성격을 파악한다.
- 같은 군집에 속하는 데이터는 다른 군집에 속하는 데이터 보다 유사성이 높다.
K 평균 군집화
- 군집 중심점이라는 특정한 임의의 지점을 선택해 해당 중심에서 가장 가까운 포인트들을 선택하는 군집화 기법이다.
- 거리기반 알고리즘이기 때문에 속성의 개수가 너무 많으면 군집화 정확도가 떨어진다.
KMeans 클래스 생성자 주요 속성
n_ cluster | 군집화 개수 (군집 중심점의 개수) |
init | 초기에 군집 중심점의 좌표를 설정할 방식 |
max_iter | 최대 반복 횟수, 이 횟수 이전에 모든 데이터의 중심점 이동이 없으면 종료한다. |
random_state | 중심 초기화 위한 난수 생성 seed값 |
KMeans 군집화 수행 완료 후 주요 속성
labels_ | 각 데이터가 속한 군집 중심점 레이블(클러스터 번호) |
cluster_centers_ | 각 군집 중심점 좌표 |
최적의 k 란?
k 값을 늘려가면서 최적의 군집을 찾는 방법을 말한다.
KMean 의 단점인 어떠한 k의 값이 적절한지에 대해 명확한 답이 없으므로 응집도가 완만하게 줄어드는 곳을 기점으로 군집의 수를 정해야한다.
해당 그림은 Elbow Function (팔꿈치 함수) 라고 불린다.
[실습] 최적의 K 찾기 - iris
분석하기 위한 x 값의 범위는 임의로 잡았다.
from sklearn.datasets import load_iris
x,y = load_iris(return_X_y=True)
x = x[:,2:] # 꽃잎의 길이와 넓이 데이터만 추출
해당 코드를 진행시키면 꽤나 긴 경고 메세지 창을 만나게 된다.
warning 패키지를 로드하여 경고메세지를 무시하도록 해놓는다.
import warnings
warnings.filterwarnings(action='ignore')
KMeans 클래스의 inertia 속성 사용
각 데이터에 할당된 클러스터의 중심까지의 제곱 거리 합계
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
inertia_arr = []
# 군집의 개수를 늘려가며
k_range = range(1,10)
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state= 10)
kmeans.fit(x) # 학습
inertia_arr.append(kmeans.inertia_)
# Elbow function 그리기
plt.plot(k_range, inertia_arr, marker = 'o')
plt.xlabel('Number of Clusters')
plt.ylabel('Inertia')
plt.show()
# 품종이 3개 이므로 군집에서 적절한 k 의 값 = 3
iris 데이터는 앞에서 분석함으로서 알고 있지만 종속 변수가 3가지로 이루어져 있다.
그러므로 이 함수에서 최적의 k는 3인 것을 알 수 있다.
K-Means Clustering 하기
군집화된 값을 체크
import pandas as pd
kmeans = KMeans(n_clusters = 3, random_state= 10)
kmeans.fit(x)
# 어느 군집에 있는지 군집 번호를 가지고 있다.
cluster_num = kmeans.labels_
df = pd.DataFrame(x, columns = ['꽃잎의 길이','꽃잎의 넓이'])
df['class'] = y # 정답
df['cluster'] = cluster_num
df.head()
시각화
plt.subplots 옵션을 사용하여 그래프를 두 가지로 분할하여 보게 해주었다.
fig, axes = plt.subplots(1,2,figsize = (16,8)) # 1행 2열의 그림
# 실제 정딥 그래프
axes[0].scatter(x[:,0],x[:,1], c = y, s = 100)
axes[0].set_title('Actual', fontsize = 18)
# 군집 분석 통해 예측한 결과 그래프
axes[1].scatter(x[:,0],x[:,1], c = cluster_num, s = 100)
axes[1].set_title('Predicted', fontsize = 18)
plt.show()
군집 평가
군집은 비지도학습 특성상 어떠한 지표라도 확실하게 성능을 측정하기 어렵다.
이러한 군집화의 성능을 평가하는 대표적인 방법으로 실루엣 분석이 있다.
실루엣 분석 silhouette Analysis
- 실루엣 계수 기반
두 군집간의 거리가 얼마나 효율적으로 분리되어 있는지를 나타낸다.
효율적인 분리란 다른 군집과의 거리는 떨어져있고, 동일 군집끼리의 데이터는 서로 가깝게 잘 뭉쳐있다는 것을 의미한다.
s(o) = b(o) - a(o) / max{a(o),b(o)}
s(o) = 데이터 포인트 o의 실루엣 계수
a(o): o 와 o 가 속한 클러스터의 다른 모든 데이터 포인터 사이의 평균 거리 (사진에서 파란색 군집)
b(o): o 에서부터 o가 속하지 않은 모든 군집 중 가장 가까운 군집과의 평균 거리 (파란색 군집과 빨간색 군집간의 거리)
max{a(o),b(o)} : 두 군집 간의 거리값을 정규화하기 위함이다.
x 축: 실루엣 계수 - y축: 해당 군집에 속해있는 데이터의 개수
점선 : 전체 평균 실루엣 계수 값 (적절하게 데이터들과 겹쳐야한다.)
silhouette_samples() 를 이용하여 모든 개별 데이터 별 실루엣 계수 산출하였다
kmeans (: KMeans() 를 통해 평균 군집을 학습한 모델).labels_ : 군집된 번호
from sklearn.metrics import silhouette_samples, silhouette_score
import pandas as pd
iris = load_iris()
df = pd.DataFrame(iris.data, columns= iris.feature_names)
df['cluster'] = kmeans.labels_ # 학습이 된 각 데이터의 군집 번호
# 실루엣 계수
# iris 모든 개별 데이터에 대한 실루엣 계수 산출
score_samples = silhouette_samples(iris.data, kmeans.labels_)
df['silhouette coef'] = score_samples
# 모든 데이터의 평균 실루엣 계수 산출
avg_score = silhouette_score(iris.data, kmeans.labels_)
print(f'실루엣 계수: {avg_score:.2f}')
display(df.head())
실루엣 계수: 0.52
groupby() 를 사용하여 클러스터 번호 별로 평균을 구한다.
# 클러스터 별 평균 실루엣 계수
group_by_cluster = df.groupby('cluster')['silhouette coef'].mean()
print(group_by_cluster)
cluster
0 0.416037
1 0.790033
2 0.358131
Name: silhouette coef, dtype: float64
클러스터 별 중심 좌표 보기
kmeans.cluster_centers_
# 클러스터 별 중심 좌표
array([[4.26923077, 1.34230769],
[1.462 , 0.246 ],
[5.59583333, 2.0375 ]])
실루엣 계수를 이용한 군집 계수 최적화
> 복붙한 함수 => 모듈처럼 쓰면 됨
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="--")
from sklearn.datasets import make_blobs # 클러스터링을 위한 샘플데이터 제공해주는 데이터
import numpy as np
x,y = make_blobs(n_samples= 500, n_features= 2, centers= 4, cluster_std= 1,
shuffle= True, random_state= 1) # 500개의 랜덤 샘플 데이터, 독립변수 2개, 클러스터 개수 4개
# visualize_silhouette([2,3,4,5], x) # 클러스터 수 변화
visualize_silhouette([2,3,4,5], iris.data)
make_blobs(n_samples= 500, n_features= 2, centers= 4, cluster_std= 1, shuffle= True, random_state= 1)
# 500개의 랜덤 샘플 데이터, 독립변수 2개, 클러스터 개수 4개, 표준편차는 1
최적의 군집 계수는 애매하지만 4 이다.
'국비 교육 > 머신러닝, 딥러닝' 카테고리의 다른 글
[머신러닝] 비지도 학습 알고리즘 - 주성분분석(공분산행렬) - 1 (0) | 2023.11.26 |
---|---|
[머신러닝] 비지도 학습 알고리즘 - 군집분석 : K- 평균 군집 [실습] 온라인 판매 군집분석 (0) | 2023.11.25 |
[머신러닝] [문제] 비행기 연착 추측 분류 (0) | 2023.11.23 |
[머신러닝] 분류분석 : 앙상블 러닝 - Voting, Boosting 실습문제 (0) | 2023.11.23 |