Data Analysis/Python for DA

[Machine Learning] 비지도학습(군집화 중 K-Means)

Jiyeon's Desk 2025. 4. 10. 13:11

 

 

 

1. K-Means 이론 설명

Random Initialization Trap 문제로 K-Means++ 방법을 씀

최적의 K를 찾기 위해 Elbow Method를 사용함

 

 

 

 

 

2. K-Means 코드 흐름

1) 비지도 학습은 정답이 없는 데이터이기 때문에 데이터셋에 있는 열들을 모두 독립변수 X로 가져온다

X = dataset.iloc[:, :].values
# X = dataset.values
# X = dataset.to_numpy() # 공식 홈페이지 권장

 

2) 전체 데이터 분포를 확인한다.

plt.scatter(X[:, 0], X[:, 1]) # x축 : hour, y축 : score
plt.title('Score by hours')
plt.xlabel('hours')
plt.ylabel('score')
plt.show()

3) 피쳐 스케일링(Feature Scaling)을 한 후 스케일링된 데이터를 시각화한다.

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X = sc.fit_transform(X)

plt.figure(figsize=(5, 5))
plt.scatter(X[:, 0], X[:, 1])
plt.title('Score by hours')
plt.xlabel('hours')
plt.ylabel('score')
plt.show()

 

4) 최적의 k값을 찾기 위해 엘보우 방식을 사용한다

from sklearn.cluster import KMeans
inertia_list = []
for i in range(1, 11):
    kmeans = KMeans(n_clusters=i, init='k-means++', random_state=0)
    kmeans.fit(X)
    inertia_list.append(kmeans.inertia_) # 각 지점으로부터 클러스터의 중심(centroid) 까지의 거리의 제곱의 합
    
plt.plot(range(1, 11), inertia_list)
plt.title('Elbow Method')
plt.xlabel('n_clusters')
plt.ylabel('inertia')
plt.show()

k=4 를 선택한다

 

5) 최적의 k(=4) 값으로 KMeans 학습시킨다.

kmeans = KMeans(n_clusters=4, random_state=0)
y_kmeans = kmeans.fit_predict(X)

결과값 :  0부터 3까지 4개의 집단으로 나누어짐

array([2, 3, 3, 0, 0, 1, 1, 0, 2, 0, 0, 3, 1, 3, 3, 0, 1, 2, 3, 0, 1, 0,
       3, 1, 2, 2, 3, 3, 3, 3, 1, 1, 3, 0, 2, 2, 3, 0, 0, 0, 3, 1, 2, 3,
       3, 2, 1, 0, 1, 1, 2, 0, 1, 1, 0, 0, 0, 0, 3, 1, 1, 2, 2, 2, 2, 1,
       1, 0, 1, 2, 3, 2, 2, 2, 3, 3, 3, 3, 0, 2, 1, 2, 1, 1, 2, 0, 3, 1,
       2, 3, 0, 1, 0, 2, 3, 2, 2, 0, 1, 3])
centers = kmeans.cluster_centers_ # 클러스터의 중심점 (centroid) 좌표
centers

결과값: 4개의 좌표가 주어짐

array([[-0.57163957,  0.85415973],
       [ 0.8837666 , -1.26929779],
       [ 0.94107583,  0.93569782],
       [-1.22698889, -0.46768593]])

 

6) 데이터 시각화 

X_org = sc.inverse_transform(X) # Feature Scaling 된 데이터를 다시 원복
centers_org = sc.inverse_transform(centers)

for cluster in range(K):
    plt.scatter(X_org[y_kmeans == cluster, 0], X_org[y_kmeans == cluster, 1], s=100, edgecolor='black') # 각 데이터
    plt.scatter(centers_org[cluster, 0], centers_org[cluster, 1], s=300, edgecolor='black', color='yellow', marker='s') # 중심점 네모
    plt.text(centers_org[cluster, 0], centers_org[cluster, 1], cluster, va='center', ha='center') # 클러스터 텍스트 출력
    
plt.title('Score by hours')
plt.xlabel('hours')
plt.ylabel('score')
plt.show()