[혼자 공부하는 머신러닝+딥러닝] 책의 내용을 정리한 글입니다.
개념
k-평균 알고리즘
: 랜덤 하게 클러스터 중심을 정해 클러스터를 만든 후 클러스터의 중심을 이동하는 과정을 반복하면서 최적의 클러스터를 구성하는 알고리즘
- 클러스터 중심 : k-평균 알고리즘이 만든 클러스터에 속한 샘플의 특성 평균값
- 센트로이드라고도 부름
- 가장 가까운 클러스터 중심을 샘플의 또 다른 특성으로 사용하거나 새로운 샘플에 대한 예측으로 활용 가능
k-평균 알고리즘의 단점 중 하나는 클러스터 개수를 사전에 지정해야 한다는 것이다.
적절한 k 값을 찾기 위한 완벽한 방법은 없지만, 각각 장단점이 있는 몇 가지 도구들이 있다.
엘보우 방법
: 최적의 클러스터 개수를 정하는 방법 중 하나
- 클러스터 개수를 늘려가면서 이너셔의 변화를 관찰하여 최적의 k 값을 찾는 방법
- 이너셔 - 클러스터 중심과 샘플 사이 거리의 제곱 합 (클러스터에 속한 샘플이 얼마나 가깝게 모여있는지를 나타냄)
- 이너셔가 감소하는 속도가 꺾이는 지점을 최적의 클러스터 개수로 판단
코드 작성
k-평균 군집 알고리즘을 통해 타깃 값 없이 과일 데이터를 자동으로 분류해보자.
과일 데이터 준비
!wget https://bit.ly/fruits_300_data -O fruits_300.npy
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
k-평균 알고리즘 클래스인 KMeans 사용
from sklearn.cluster import KMeans
# 우선은 클러스터 개수를 3으로 임의 지정
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_2d)
# 각 샘플이 어떤 레이블에 해당되는지 알 수 있는 배열
print(km.labels_)
# => [2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 0 2 0 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 0 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1]
# 각 레이블별 샘플 개수 확인
print(np.unique(km.labels_, return_counts=True))
# => (array([0, 1, 2], dtype=int32), array([111, 98, 91]))
각 클러스터가 모은 샘플들을 이미지로 출력
import matplotlib.pyplot as plt
def draw_fruits(arr, ratio=1):
n = len(arr) # n은 샘플 개수
# 한 줄에 10개의 이미지. 샘플 개수를 10으로 나누어 전체 행 개수를 계산.
rows = int(np.ceil(n/10))
# rows 1인 경우 샘플 개수가 10보다 작다는 뜻이므로, 열 개수는 rows가 1이면 샘플 개수이고 아니면 10개.
cols = n if rows < 2 else 10
fig, axs = plt.subplots(rows, cols,
figsize=(cols*ratio, rows*ratio), squeeze=False)
for i in range(rows):
for j in range(cols):
if i*10 + j < n: # n 개까지만 출력
axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
draw_fruits(fruits[km.labels_==0])
draw_fruits(fruits[km.labels_==1])
draw_fruits(fruits[km.labels_==2])
군집 알고리즘이 최종적으로 찾은 클러스터 중심 값 확인
# 100x100 크기의 2차원 배열로 바꾼 후 출력
draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3)
인덱스가 100인 샘플에 대한 예측 결과 확인
# 각 클러스터 중심까지의 거리를 출력
print(km.transform(fruits_2d[100:101]))
# => [[3393.8136117 8837.37750892 5267.70439881]]
# 가장 가까운 클러스터 중심을 예측 클래스로 출력
print(km.predict(fruits_2d[100:101]))
# => [0]
엘보우 방법을 사용하여 최적의 k 값(클러스터 개수) 찾기
inertia = []
# 클러스터 개수 k를 2~6까지 바꿔가며 5번 훈련
for k in range(2, 7):
km = KMeans(n_clusters=k, n_init='auto', random_state=42)
km.fit(fruits_2d)
inertia.append(km.inertia_)
plt.plot(range(2, 7), inertia)
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
이 장에서 사용된 핵심 패키지와 함수
scikit-learn
- KMeans
- k-평균 알고리즘 클래스
- n_cluster : 클러스터 개수 지정 (기본값 - 8)
- n_init : 처음에 랜덤 하게 클러스터 중심을 초기화하기 때문에 여러 번 반복하여 이너셔를 기준으로 가장 좋은 결과를 선택하는데, 이 반복 횟수를 지정 (기본값 - 10)
- max_iter : k-평균 알고리즘을 한 번 실행하는 동안 최적의 클러스터 중심을 찾기 위해 반복할 수 있는 최대 횟수 (기본값 - 200)
'Machine Learning' 카테고리의 다른 글
[혼자 공부하는 머신러닝+딥러닝] 주성분 분석 (0) | 2023.05.28 |
---|---|
[혼자 공부하는 머신러닝+딥러닝] 군집 알고리즘 (0) | 2023.05.21 |
[혼자 공부하는 머신러닝+딥러닝] 트리의 앙상블 (0) | 2023.05.14 |
[혼자 공부하는 머신러닝+딥러닝] 교차 검증과 그리드 서치 (0) | 2023.05.09 |
[혼자 공부하는 머신러닝+딥러닝] 결정 트리 (0) | 2023.05.09 |