Deep Learning/혼공 머신 러닝 - 딥러닝

[DL] 비지도 학습, K-평균

KimTory 2021. 12. 19. 23:40

# 혼공 머신 러닝 인강 참고하여 내용 정리 하였습니다.

 

 

[ K-평균 알고리즘 ]

 

▶ 샘플 중, 클러스터 중심을 정하고 클러스터를 만든다. 그 이후 클러스터의 중심을 이동하고 다시 클러스터를 만드는 식으로 여러 번 반복해서 최적의 클러스터를 구성하는 알고리즘

 

▶클러스터 중심은 K-평균 알고리즘이 만든 클러스터에 속한 샘플의 특성 평균값이며, 센트로이드라고도 부름.

가장 가까운 클러스터 중심을 샘플의 또 다른 특성으로 사용하거나 새로운 샘플에 대한 예측으로 재활용 하기도 함

 

→ 엘보우 방식은 최적의 클러스터 개수를 정하는 방법 중 하나, 계산 방식은 Sample ~ Cluster Center거리의 제곱 합

→ KMeans : K- 평균 알고리즘 클래스

① n_clusters : 클러스터 개수를 지정 Default는 8

② n_init : 반복 횟수, Default는 10

③ max_iter : K-평균 알고리즘의 한 번 실행에서 최적의 센트로이드를 찾기 위해 반복할 수 있는 최대 횟수

    (Default는 200)

 

K-평균 알고리즘 구동 방식

-. 무작위로 k개의 클러스터 중심을 정함

-. 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플로 지정

-. 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경

-. 클러스터 중심에 변화가 없을 때까지 2번으로 돌아가 반복

  (클러스터 중심이 이동하지 않으면 종료 할 수 있음)

 

[ 소스 코드 ]

 

!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) # reshape

from sklearn.cluster import KMeans

km = KMeans(n_clusters=3, random_state=42) # n_clusters : 클러스터 개수
km.fit(fruits_2d) # 비지도 학습으로 target 인자 사용 안함
# KMeans(n_clusters=3, random_state=42)

print(km.labels_) # n_clusters를 3으로 지정 하였기 때문에 label은 3개가 출력됨, 랜덤

print(np.unique(km.labels_, return_counts=True)) # unique → index의 개수 반환
# return_counts 인자를 True를 주면 label과 거기에 해당하는 갯수를 출력

import matplotlib.pyplot as plt

def draw_fruits(arr, ratio=1): # 배열을 매개 변수로 받음
    n = len(arr)    # n은 샘플 개수
    # 한 줄에 10개씩 이미지를 그립니다. 샘플 개수를 10으로 나누어 전체 행 개수 계산 
    rows = int(np.ceil(n/10)) 
    print(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 개까지만 draw
                axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
            axs[i, j].axis('off')
    plt.show()
    
    draw_fruits(fruits[km.labels_==0]) # 0번 label
    draw_fruits(fruits[km.labels_==1]) # 1번 label
    draw_fruits(fruits[km.labels_==2]) # 2번 label
    
    draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3) 
# fruits_2d sample의 cluster 중심 이기 때문에 2차원 배열로 변경

print(km.transform(fruits_2d[100:101])) # 샘플이 각 레이블의 중심점까지의 거리를 출력
# fruits_2d[100:101]의 Sample은 샘플에서 클러스트 중심까지 가장 가까운 0번 레이블임
# [[3393.8136117  8837.37750892 5267.70439881]] # 3393.~~ 이 샘플에서 클러스터 중심까지 가장 가까움
print(km.predict(fruits_2d[100:101])) # 예측 알고리즘
# KMeans 클래스는 가장 가까운 클러스트 중심을 예측 클래스로 가짐
# [0] 0 번 레이블이 예측에 해당되는 클래스임

 

transform( ) 결과와 동일