Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Tags
more
Archives
Today
Total
관리 메뉴

kang's study

13일차 : k-평균 본문

[학습 공간]/[혼공머신러닝]

13일차 : k-평균

보끔밥0302 2022. 3. 3. 06:56

 

 

 

 

 

k-평균

 

 

KMeans 클래스

In [1]:
# !wget https://bit.ly/fruits_300_data -O fruits_300.npy
In [2]:
import numpy as np

fruits = np.load('fruits_300_data')
# 2차원 배열로 만든다. (샘플개수, 너비×높이)
fruits_2d = fruits.reshape(-1, 100*100)
 
 
 

모델 훈련

In [3]:
from sklearn.cluster import KMeans

km = KMeans(n_clusters = 3, random_state = 42) # 10번 수행 n_iter
km.fit(fruits_2d) # 타깃이 없다
Out[3]:
KMeans(n_clusters=3, random_state=42)
In [4]:
print(km.labels_) # 군집된 결과 n=3이라 배열의 값은 0,1,2 중 하나
 
[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]
In [5]:
print(np.unique(km.labels_, return_counts=True))
 
(array([0, 1, 2]), array([111,  98,  91], dtype=int64))
 

이미지 출력 함수

실제는 데이터셋이 커서 확인하기 힘듬
In [6]:
import matplotlib.pyplot as plt

def draw_fruits(arr, ratio=1): # 출력할 이미지의 배열
    n = len(arr)    # n은 샘플 개수입니다
    # 한 줄에 10개씩 이미지를 그립니다. 
    # 샘플 개수를 10으로 나누어 전체 행 개수를 계산합니다. 
    rows = int(np.ceil(n/10))
    # 행이 1개 이면 열 개수는 샘플 개수입니다. 그렇지 않으면 10개입니다.
    cols = n if rows < 2 else 10
    fig, axs = plt.subplots(rows, cols, 
                            figsize=(cols*ratio, rows*ratio), squeeze=False)
    # for 문 안에서 axs를 항상 2차원 배열로 다루기 위해서 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()
In [7]:
draw_fruits(fruits[km.labels_==0])
 
In [8]:
draw_fruits(fruits[km.labels_==1])
 
In [9]:
draw_fruits(fruits[km.labels_==2])
 
 

클러스터 중심

In [10]:
draw_fruits(km.cluster_centers_.reshape(-1, 100, 100), ratio=3)
 
 
원본 이미지를 다른 테이터 형태로 바꾸어준다
3개의 특성이 있는 벡터로 바꿀 수 있다
In [11]:
print(km.transform(fruits_2d[100:101])) 
# transform() 메서드에 2차원 배열을 입력해야 한다.
# 훈련 데이터 샘플에서 클러스터 중심까지 거리
 
[[3393.8136117  8837.37750892 5267.70439881]]
In [12]:
print(km.predict(fruits_2d[100:101])) # 가장 가까운 클러스터를 할당해줌
 
[0]
In [13]:
draw_fruits(fruits[100:101])
 
In [14]:
print(km.n_iter_) # 중심이동 반복 횟수
 
4
 

최적의 k 찾기

 

엘보우 메소드

이너셔 : 클러스터 중심과 클러스터에 속한 샘플 사이의 거리의 제곱합
클러스터의 샘플이 얼마나 가깝게 있는지에 대한 값
In [15]:
inertia = []
for k in range(2, 7):
    km = KMeans(n_clusters=k, 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()
#이너셔의 감소 정도가 꺾이는 클러스터 개수를 찾는다
 
 
원형의 데이터에서 잘 동작한다. (특성간의 거리가 비슷하게 분포)

출처 : 박해선, 『혼자공부하는머신러닝+딥러닝』, 한빛미디어(2021), p303-315

Comments