#!/usr/bin/env python3


k-평균 군집 알고리즘


0. 살펴보기

데이터셋을 클러스터cluster라는 그룹으로 나누는 작업

다른 클러스터의 데이터 포인트와는 구분되도록 데이터를 나누는 것이 목표


k-평균k-mean 군집은 가장 간단하고 널리 사용됨

이 알고리즘은 데이터의 어떤 영역을 대표하는 클러스터 중심cluster center를 찾음

1. 데이터 포인트를 가장 가까운 클러스터 영역에 할당

2. 클러스터에 할당된 데이터 포인트의 평균으로 클러스터 중심을 다시 지정

3. 클러스터에 할당되는 데이터 포인트에 변화가 없을 때 알고리즘 종료


# library import

import mglearn

import matplotlib

import matplotlib.pyplot as plt


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic'# 한글 출력

plt.rcParams['axes.unicode_minus'] = False #  축 -


mglearn.plots.plot_kmeans_algorithm()

plt.show()

입력 데이터와 k-평균 군집 알고리즘이 세번 진행되기가지의 과정


# 경계선 그리기

mglearn.plots.plot_kmeans_boundaries()

plt.show() 

k-평균 알고리즘으로 찾은 클러스터 중심과 클러스터 경계




1. make_blobs(인위적 데이터셋)에 k-평균 알고리즘을 적용

# library import

from sklearn.datasets import make_blobs

from sklearn.cluster import KMeans

import numpy as np


# 데이터 만들기

x, y = make_blobs(random_state=1)


# 모델 생성 및 학습

kmean = KMeans(n_clusters=3) # 클러스터 수

kmean.fit(x)


print('클러스터 레이블: \n{}'.format(kmean.labels_)) 

3개의 클러스터를 지정했으므로 각 클러스터는 0 ~ 2까지 번호가 붙음


### predict메소드를 통해 새로운 데이터 클러스터 레이블을 예측할 수 있음

### 예측은 각 포인트에 가장 가까운 클러스터 영역으로 할당하는 것이며 기존 모델을 변경하지 않음

### 훈련 세트에 대해 predict 메소드를 실행하면 labels_와 같은 결과를 얻게 됨


print('예측 레이블: \n{}'.format(kmean.predict(x)))


### 클러스터는 각 데이터 포인트가 레이블을 가진다는 면에서 분류와 비슷함

### 그러나 정답을 모르고 있으며 레이블 자체에 의미가 없음

### 알고리즘이 우리에게 주는 정보는 각 레이블에 속한 데이터는 서로 비슷하다는 것





2. make_blobs 데이터로 그래프 그리기

mglearn.discrete_scatter(x[:, 0], x[:, 1], kmean.labels_, markers= 'o') # x, y, group, marker

mglearn.discrete_scatter(

    kmean.cluster_centers_[:, 0], kmean.cluster_centers_[:, 1], y=np.unique(kmean.labels_),# x, y, group

    markers='^', markeredgewidth=2) # marker, 두께

plt.show()

k-평균 알고리즘으로 찾은 세 개의 클러스터 중심과 클러스터 할당




3. 클러스터수를 변경하여 비교

fig, axes = plt.subplots(2, 2, gridspec_kw={'hspace':0.5}) # gridspec_kw: 그래프 수평간격

n_clusters_set = [2, 4, 5, 6] 

for n, ax in zip(n_clusters_set, axes.ravel()):

    kmeans = KMeans(n_clusters=n) # 클러스터 갯수

    kmeans.fit(x)

    mglearn.discrete_scatter(x[:, 0], x[:, 1], y=kmeans.labels_, ax=ax) # x, y, group, ax = plot객체

    mglearn.discrete_scatter(

        kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], y=np.unique(kmeans.labels_), # x, y, group

        markeredgewidth=3, ax=ax, s=15) # 두께, 그림객체, 사이즈

    ax.set_title('n_cluster: {}'.format(n)) # title

    ax.set_xlabel('feature 0')

    ax.set_ylabel('feature 1')

plt.show()

k-평균 알고리즘으로 클러스터를 여러개 사용했을 때의 중심과 클러스터 할당




4. k-평균 알고리즘이 실패하는 경우

데이터셋의 클러스터 갯수를 알고있더라도 k-평균 알고리즘이 항상 이를 구분해낼 수 있는 것은 아님

각 클러스터를 정의하는 것이 중심 하나뿐이므로 클러스터는 둥근 형태로 나타남

이런 이유로 k-평균 알고리즘은 비교적 간단한 형태를 구분할 수 있음

또한 k-평균은 모든 클러스터의 반경이 똑같다고 가정 ==> 클러스터 중심 사이에 정확히 중간에 경계를 그림


4-1 클러스터의 밀도가 다를 때

x1, y1 = make_blobs(n_samples=200, cluster_std=[1, 2.5, 0.5], random_state=170) # 샘플수, 밀도, 랜덤상태

y_pred = KMeans(n_clusters=3, random_state=0).fit_predict(x1) # 모델 생성 및 훈련 후 예측


mglearn.discrete_scatter(x1[:, 0], x1[:, 1], y=y_pred) # x, y, group

plt.legend(['cluster 0', 'cluster 1', 'cluster 2']) # 범례

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.show()

클러스터의 밀도가 다를 때 k-평균으로 찾은 클러스터 할당


4-2 클러스터가 원형이 아닐  때

x2, y2 = make_blobs(n_samples=600, random_state=170) # 샘플 갯수, 램덤상태

rng = np.random.RandomState(74).normal(size=(2,2)) # 랜덤상태, (2,2)size로 normal분포의 숫자 무작위추출

x2_reshape = np.dot(x2, rng) # np.dot 행렬곱


kmeans = KMeans(n_clusters=3).fit(x2_reshape) # 모델 생성

y2_pred = kmeans.predict(x2_reshape) # 예측


mglearn.discrete_scatter(x2_reshape[:, 0], x2_reshape[:, 1], y=kmeans.labels_, alpha=0.7) # x, y , group, 투명도

mglearn.discrete_scatter(

    kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1], y=np.unique(kmeans.labels_), # x, y, group

    markeredgewidth=3, s=15) # 두께, size

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.show()

원형이 아닌 클러스터를 구분하지 못하는 k-평균 알고리즘


4-3 클러스터의 구조가 복합형태를 나타낼 때

from sklearn.datasets import make_moons


x3, y3 = make_moons(n_samples=200, noise=0.05, random_state=0) # 갯수, 퍼짐정도, 랜덤상태

kmeans = KMeans(n_clusters=2).fit(x3) # 모델 객체 생성 및 학습

y3_pred = kmeans.predict(x3) # 모델 적용


plt.scatter(x3[:, 0], x3[:, 1], c=y3_pred, s=60, edgecolors='black', cmap=mglearn.cm2) # x, y, group, 점크기 60%, 테두리색 black, palette

plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], # x, y

            marker='^', s=120, linewidth=2, edgecolors='k', c=[mglearn.cm2(0), mglearn.cm2(1)]) # marker,  점크기 120%, 두께, 테두리색, 색상 

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.show()

반달 모양의 클러스터를 구분하지 못하는 k-평균 알고리즘


k-평균 알고리즘이 2개의 반달모양을 구분하지 못하고 원형으로 데이터를 비교






+ Recent posts