본문 바로가기

Data Scientist

군집화(K-means clustering)

반응형

K - Means clustering

K-평균 군집 중심점(centroid)이라는 특정한 임의의 지점을 선택해 해당 중심에 가장 가까운 포인트들을 선택하는

군집화 기법이다. [각 클러스터의 거리 차이의 분산을 최소화 하는 방식으로 동작하는 비지도 학습]

 

군집 중심점은 선택된 포인트의

평균 지점으로 이동하고

②이동된 중심점에서 다시 가까운 포인트를 선택,

다시 중심점을 평균 지점으로 이동하는 프로세스를 반복적으로 수행한다. 

 

모든 데이터 포인트에서 더이상 중심점의 이동이 없을 경우에 반복을 멈추고 해당 중심점에 속하는

데이터 포인트들을 군집화하는 기법이다.

0
출처: 위키백과

♧ 군집 중심점을 설정하면 각 데이터는 가장 가까운 중심점에 소속된다. 

    중심점에 할당된 데이터들의 평균 중심으로 중심점 이동을 한다.

    각 데이터는 이동된 중심점 기준으로 가장 가까운 중심점에 소속되고,

    다시 중심점에 하랑된 데이터들의 평균 중심으로 중심점 이동이 이루어진다. 

    중심점을 이동하였지만 데이터들의 중심점 소속 변경이 없으면 군집화를 종료한다. 

 

 K-평균의 장점

일반적인 군집화에서 가장 많이 활용되는 알고리즘이며 쉽고 간결한 편이다.

 

 K-평균의 단점

    - 거리 기반 알고리즘으로 속성의 개수가 많아질수록 군집화 정확도가 떨어진다(이를 위해 PCA로 차원 감소를 

    적용해야 할 수도 있다).

    - 반복을 수행하는데, 반복 횟수가 많을 경우 수행 시간이 느려진다.

    - 몇 개의 군집(cluster)을 선택해야 할지 가이드하기가 어렵다. 

    - 이상값(outlier)에 민감하게 반응한다.

    - 구형이 아닌 군집을 찾는 데에는 적절하지 않다. -> DBSCAN 또는 mean-shift

class sklearn.cluster.KMeans(n_clusters=8, init='k-meanas++', n_init=10, max_iter=300, tol=0.0001,
                             precopute_distances='auto', verbose=0, random_state=None,
                             copy_x=True, n_jobs=1, algorithm='auto')

사이킷런 패키지 중 KMeans 클래스는 이와 같은 초기화 파라미터를 가지고 있다.

이 중 중요한 파라미터는 n_cluster, init, max_iter이다.

- n_cluster: 군집화할 개수, 즉 군집 중심점의 개수를 의미한다.

- init: 초기에 군집 중심점의 좌표를 설정한 방식을 말하며 보통은 임의로 중심을 설정하지 않고 

일반적으로 k-means++ 방식으로 최초 설정한다. 

k-평균 클러스터링은 초기 값을 어떻게 선택하는가에 성능이 크게 달라지는 성질을 갖고 있다.
이러한 성질을 줄이기 위해 k-평균++ 알고리즘을 제안하였고, 초기 값을 선택하는 데 주로 사용되고 있다.
초기 값을 설정하기 위해 추가적인 시간을 필요로 하지만, 이후 선택된 초기 값은
이후 k-평균 알고리즘이 최적 k-평균 해를 찾는 것을 보장한다.

1. 데이터 집합으로부터 임의의 데이터 하나를 선택하여 첫 번째 중심으로 설정한다.
2. k개의 중심이 선택될 때까지 다음의 단계를 반복한다. 
 - 데이터 집합의 각 데이터에 대해서, 해당 데이터와 선택된 중심점들 중 가장 가가운 중심과의 거리 D(x)를 계산
 - 확률이 D(x)^2에 비례하는 편중 확률 분포를 사용하여 임의의 데이터를 선택한 후, n번째 중심으로 설정
3. 선택된 k개의 중심들을 초기 값으로 하여 k-평균 클러스터링을 수행

- max_iter: 최대 반복 횟수이며, 이 횟수 이전에 모든 데이터의 중심점 이동이 없으면 종료한다. 

 

KMeans는 사이킷런의 비지도학습 클래스와 마찬가지로 fit(데이터 세트) 또는 fit_transform(데이터세트) 메소드를 이용해 수행하면 된다. 이렇게 수행된 KMeans 객체는 군집화 수행이 완료돼 군집화와 관련된 주요 속성을 알 수 있다.

- labels_ : 각 데이터 포인트가 속한 군집 중심점 레이블

- cluster_centers_: 각 군집 중심점 좌표(Shape는 [군집 개수, 피처개수]). 이를 이용하면 군집 중심점 좌표가 어디인지

시각화할 수 있다. 

 


import

from sklearn.preprocessing import scale
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
iris = load_iris()
iris

iris data

iris 데이터는 유명해서 내장되어 있다. import로 데이터를 가져오면 위 사진과 같이 데이터를 가져올 수 있다.

iris_df = pd.DataFrame(data=iris.data, columns=['sepal_length', 'sepal_width', 'petal_length','petal_width'])
iris_df.head()

데이터 핸들링의 편의를 위해 데이터프레임으로 변경하고 컬럼명을 할당해준다. 

이제 붓꽃 데이터셋을 3개 그룹으로 군집화 할 예정인데, 이를 위해 n_cluster는 3, 초기 중심 설정 방식은 

디폴트 값인 k-means++, 최대 반복 횟수 역시 디폴트 값인 max_iter = 300으로 설정한 KMeans 객체를 만들고,

여기에 fit( )를 수행한다. 

kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, random_state=0)
kmeans.fit(iris_df)

------------------------------------------------------------------------------

KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
       n_clusters=3, n_init=10, n_jobs=None, precompute_distances='auto',
       random_state=0, tol=0.0001, verbose=0)

iris_df 데이터에 대한 군집화 수행 결과가 kmeans 객체 변수로 반환됐다. 

 

print(kmeans.labels_)

--------------------------------------------------------------------------
[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 1 1 1 1 1 1 1 1 1 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 2 0 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 0 0 0 2 0 0 0 0
 0 0 2 2 0 0 0 0 2 0 2 0 2 0 0 2 2 0 0 0 0 0 2 0 0 0 0 2 0 0 0 2 0 0 0 2 0
 0 2]

labels_속성값이 0,1,2로 되어 있는 것을 알 수 있으며, 이는 각 레코드가 첫번째 군집, 두번재 군집, 세번째 군집에

속하는 것을 의미한다. 

 

군집화가 얼마나 효과적으로 수행되었는지 확인하기 위해,

붓꽃 데이터셋의 target 값을 'target' 컬럼으로, 앞에서 구한 labels_ 값을 'cluster' 컬럼으로 지정한다. 

데이터 프레임에 추가하고 group by연산을 실제 분류값인 target과 군집화 분류값인

cluster 레벨로 적용해 target 값 개수를 비교할 수 있다. 

iris_df['target'] = iris.target
iris_df['cluster'] = kmeans.labels_
iris_result = iris_df.groupby(['target', 'cluster'])['sepal_length'].count()
print(iris_result)

-----------------------------------------------------------------------------

target  cluster
0       1          50
1       0           2
        2          48
2       0          36
        2          14
Name: sepal_length, dtype: int64

 

반응형