군집분석 중에서 k-means clustering, k-median clustering, k-medoid clustering, fuzzy k-means clustering, Gaussian mixture model clustering 등의 알고리즘은 군집의 개수 k를 미리 정해주어야 합니다.


그런데 군집분석이 정답 Y가 없는 상태에서 데이터 구조/군집을 탐색하고 마이닝하는 비지도학습(unsupervised learning)이다 보니 최적의 군집의 개수 k를 결정하고 군집 결과를 평가하는 것이 다분히 주관적인 편입니다. 해당 업과 데이터에 대해서 잘 아는 SME(Subject Matter Expert)의 지식과 경험, 그리고 활용 목적을 고려한 주관적인 의견을 반영하여 최종결정하는 것이 필요하고 중요합니다.


단, 이때 주관적인 경험과 지식에만 의존하는 것이 아니라, 군집의 개수 k를 선택하는데 있어 계량적인 데이터 분석 수치와 시각화의 도움을 받을 수 있다면 좀더 쉽고 또 보다 데이터 구조와 특성을 잘 반영한 의사결정을 할 수 있을 것입니다. (물론, 이마저도 정답이 없다보니 분석가의 주관적인 평가와 판단이 들어가게 되고, 명확한 판단을 내리기가 애매한 경우도 생길 수 있습니다.)


이번 포스팅에서는 군집의 개수 k 를 미리 정해주어야 하는 알고리즘에서 군집의 개수 k를 결정하고 선택하는데 도움을 받을 수 있는 3가지 방법(Determining the number of clusters)대해서 알아보겠습니다.


(1) 계층적 군집분석의 덴드로그램 시각화를 이용한 군집의 개수 결정
     (Hierarchical Clustering: Dendrogram)

(2) 팔꿈치 방법을 이용한 군집의 개수 결정 (The Elbow Method)

(3) 실루엣 방법을 이용한 군집의 개수 결정 (The Silhouette Method)






  0. 샘플 데이터 USArrests {datasets} 불러오기 및 전처리


예제로 사용할 데이터는 R의 datasets 패키지에 내장되어 있는, 미국 주별 폭력적인 범죄 비율("Violent Crime Rates by US State)의 통계를 포함한 USArrests 데이터셋입니다. 이 데이터셋은 1973년 미국의 50개 주 별로 10만 명당 살인(Murder), 폭행(Assault), 강간(Rape) 체포 건수와 도시 인구 비율 (Percent Urban Population)의 네 개의 변수로 구성되어 있습니다.


## importing USArrests dataset from {datasets}
data(USArrests)

dim(USArrests)
# [1] 50  4

head(USArrests)
# Murder Assault UrbanPop Rape
# Alabama      13.2     236       58 21.2
# Alaska       10.0     263       48 44.5
# Arizona       8.1     294       80 31.0
# Arkansas      8.8     190       50 19.5
# California    9.0     276       91 40.6
# Colorado      7.9     204       78 38.7




군집분석을 할 때 변수별 척도가 다를 경우 큰 척도의 변수 값에 군집의 결과가 휘둘릴 수 있으므로, 먼저 scale() 함수를 이용해서 표준화(standardization)를 해주었습니다.



## standardization (scaling)
USArrests_scaled <- data.frame(scale(USArrests))

head(USArrests_scaled)
# Murder   Assault   UrbanPop         Rape
# Alabama    1.24256408 0.7828393 -0.5209066 -0.003416473
# Alaska     0.50786248 1.1068225 -1.2117642  2.484202941
# Arizona    0.07163341 1.4788032  0.9989801  1.042878388
# Arkansas   0.23234938 0.2308680 -1.0735927 -0.184916602
# California 0.27826823 1.2628144  1.7589234  2.067820292
# Colorado   0.02571456 0.3988593  0.8608085  1.864967207

 



다음으로, 표준화한 데이터에 대해서 50개의 각 주별 쌍의 유사도 행렬 (proximity matrix)로서 유클리드 거리 행렬 (Euclidean distance matrix) 을 dist(method = "euclidean") 함수를 사용해서 계산하였습니다. 자, 이제 군집분석을 위한 데이터셋 준비가 다 되었네요.



# calculating the euclidean diatance matrix
dist_eucl <- dist(USArrests_scaled, method = "euclidean")

dist_eucl
# Alabama    Alaska   Arizona  Arkansas California  Colorado Connecticut
# Alaska         2.7037541                                                               
# Arizona        2.2935197 2.7006429                                                     
# Arkansas       1.2898102 2.8260386 2.7177583                                           
# California     3.2631104 3.0125415 1.3104842 3.7636409                                 
# Colorado       2.6510673 2.3265187 1.3650307 2.8310512  1.2876185                      
# Connecticut    3.2152975 4.7399125 3.2628575 2.6076395  4.0663898 3.3279920            
# Delaware       2.0192927 3.6213633 1.9093696 1.8003239  3.0737852 2.5547456   1.7568475
# Florida        2.2981353 2.9967642 1.7493928 3.3721968  2.0250039 2.4458600   4.4700701
# Georgia        1.1314351 2.8194388 2.7871963 2.2117614  3.3780585 2.8649105   3.9738227
# Hawaii         3.3885300 4.5301340 3.2621208 2.9723097  3.6589083 2.8233524   1.3843291
# Idaho          2.9146623 4.0580555 3.5210071 1.7687255  4.4879436 3.4767685   1.6354214
# Illinois       1.8734993 3.2670626 1.0825512 2.4626424  1.9117469 1.7898322   2.7400560

-- 이하 생략함 --

 




  (1) 계층적 군집분석의 덴드로그램 시각화를 이용한 군집의 개수 결정
     (Hierarchical Clustering: Dendrogram)


계층적 군집분석(hierarchical clustering)에는 군집과 군집 간의 거리를 측정하는 다양한 연결법(linkage method)으로서, 단일연결법, 완전연결법, 평균연결법, 중심연결법, Ward연결법 등이 있습니다. 그중에서 Ward 연결법(Ward Linkage Method)에 의한 계층적 군집분석을 해보고, 이 결과를 덴드로그램(Dendrogram)으로 시각화를 해보겠습니다.


덴드로그램을 시각화 한 후에 왼쪽의 높이(Height) 축을 기준으로, 위에서 아래로 높이를 이동하면 군집의 개수가 1개, 2개, 4개, 6개, 8개, ..., 50개, 이런 식으로 변하게 됩니다.


이때 군집 간 높이의 차이가 큰 군집의 개수를 선택하면 군집 내 응집력은 높고, 군집간 이질성이 큰 적절한 군집을 구할 수 있습니다. 아래의 예의 경우 군집의 개수가 2개 또는 4개가 적당해 보이네요.


다만, 이 방법은 (a) 데이터 개수가 많을 경우 (가령, 수십만개, 수백만개) 군집화 시간이 오래걸리고, 덴드로그램으로 시각화가 거의 불가능할 수 있습니다. (b) 통계량을 산출하는게 아니고 덴드로그램 시각화 결과를 보고 분석가의 판단에 의지하다보니 다분히 주관적입니다.



set.seed(1004) # for reproducibility
hc_ward <- hclust(dist_eucl, method="ward.D")

# 덴드로그램
plot(hc_ward)





  (2) 팔꿈치 방법을 이용한 군집의 개수 결정 (The Elbow Method)


다음으로는 비계층적 군집분석(nonhierarchical clustering, partitioning clustering) 중에서 k-means 군집분석(또는 k-median, k-medoids 등)의 k를 다르게 바꾸어가면서 군집화를 했을 때, 군집의 수 k별 "군집 내 군집과 개체 간 거리 제곱합의 총합 (tot.withinss: Total within-cluster sum of squares)" 의 그래프가 팔꿈치 모양으로 꺽이는 지점의 k 를 최적 군집의 개수를 선택하는 방법이 팔꿈치 방법(The Elbow Method) 입니다.


군집 Gi의 중심 측도가 평균인 경우,


Total Within-Cluster Sum of Squares

tot.withinss =



아래의 USArrests 데이터셋 예의 경우 군집의 개수가 4개일 때 Total within-cluster sum of squares 가 팔꿈치 모양으로 꺽이고, 군집 k가 5개 이상일 때부터는 tot.withinss의 변화가 매우 작으므로, 군집의 개수를 4개로 하는 것이 가장 좋아보이네요. (분석가의 주관적인 요소가 들어가긴 합니다. ^^;)



# find the optimal number of clusters using Total within-cluster sum of squares
tot_withinss <- c()

for (i in 1:20){
  set.seed(1004) # for reproducibility
  kmeans_cluster <- kmeans(USArrests_scaled, centers = i, iter.max = 1000)
  tot_withinss[i] <- kmeans_cluster$tot.withinss
}

plot(c(1:20), tot_withinss, type="b",
     main="Optimal number of clusters",
     xlab="Number of clusters",
     ylab="Total within-cluster sum of squares")






또는, 군집의 개수 k 별로 전체 분산(Total Variance) 중에서 그룹 간 분산(Between-Group Variance)의 비율로 계산(F-test 라고도 함)하는 "설명된 분산의 비율(the Percentage of Variance Explained)"을 계산하여 시각화한 후에, 팔꿈치 모양으로 꺽이는 지점의 군집의 개수 k를 선택하는 방법을 사용할 수 도 있습니다. (이 경우 위의 그룹 내 분산(Within-cluster Sum of Squares)을 사용했을 때와는 그래프 모양이 반대가 됩니다.)





## the percentage of variance explained as a function of the number of clusters
## Percentage of variance explained is the ratio of the between-group variance to the total variance,
## also known as an F-test.
r2 <- c()

for (i in 1:20){
  set.seed(1004) # for reproducibility
  kmeans_cluster <- kmeans(USArrests_scaled, centers = i, iter.max = 1000)
  r2[i] <- kmeans_cluster$betweenss / kmeans_cluster$totss
}

plot(c(1:20), r2, type="b",
     main="The Elbow Method - Percentage of Variance Explained",
     xlab="Number of clusters",
     ylab="Percentage of Variance Explained")







  (3) 실루엣 방법을 이용한 군집의 개수 결정 (The Silhouette Method)


Peter J. Rousseeuw 는 "Silhouettes: a grapical aid to the interpretation and validation of cluster analysis" (1987) 라는 논문에서 분할적 군집분석(partitioning clustering)의 결과를 시각화하여 해석하고 평가할 수 있는 지표로서 실루엣(Silhouette)을 제안하였습니다.


실루엣을 계산하기 위해서 먼저 아래의 용어를 정의합니다. (아래의 논문 예시 그림 참조)


군집 A가 객체 i와 다른 객체들을 포함하고 있을 때,


a(i) = 군집 A 내의 객체 i 와 군집 A 내의 다른 객체들 간의 평균 비유사성 (즉, 거리 (distance))

        (average dissimilarity of i to all other objects of A)


d(i, C) = 군집 A 내의 객체 i와 다른 군집 C에 속한 모든 객체와의 평균 비유사성 (즉, 거리)

        (average dissimilarity of i to all objects of C)


b(i) = d(i, C) 의 최소값 =



* source: Reter J. Rousseeuw (1987)



실루엣은 아래 공식을 보면 알 수 있는 것처럼, 밀집성(tightness)와 분리성(separation)의 비교에 기반한 지표로서, 실루엣은 어떤 객체가 군집 안에 잘 놓여 있는지, 그리고 어떤 객체는 단지 군집들 사이의 어딘가에 놓여있는지를 보여줍니다.




전체 군집분석의 실루엣들을 하나의 그래프에 모아서 보여줌으로써, 데이터 구성과 형상의 개요(overview of the data configuration)군집들의 상대적인 질(the relative quality of the clusters)을 평가할 수 있습니다.


평균 실루엣 폭(the average silhouette width)은 군집화 결과에 대한 타당성(validity)을 평가하고, 또 적절한 군집 개수를 선택(to select an 'appropritate' number of clusters)하는데 활용할 수 있습니다.


실루엣은 -1 <= s(i) <= 1 사이의 값을 가집니다. 위 공식에 의하면 "실루엣 값이 1에 가까우면 다른 군집과의 거리보다 동일 군집 내 객체 간 거리가 가깝다는 뜻이므로 객체 i가 잘 군집화가 되었다는 의미"입니다. (이와 반대로 실루엣 값이 -1에 가까우면 객체 i의 군집화가 잘못되었다는 뜻입니다.)


만약 대부분의 객체가 높은 실루엣 값을 가진다면 군집의 구성이 적절하게 잘 되었다고 평가할 수 있습니다. 반면 많은 객체들이 낮거나 혹은 음(-)의 실루엣 값을 가진다면 군집 구성이 너무 많거나 또는 너무 적은 수의 군집을 가졌기 때문이라고 판단할 수 있습니다.

(아래 예에서는 군집4 에 정렬된 객체들의 뒷부분에 낮은 실루엣 값, 또는 음의 실루엣 값을 가진 객체들이 여러개 보이네요.)



## fviz_silhouette: Visualize Silhouette Information from Clustering
install.packages("factoextra")
library(factoextra)


# K-means clustering
set.seed(1004)
km.res <- kmeans(USArrests_scaled, centers = 4)

# Visualize silhouhette information
library("cluster")
sil <- silhouette(km.res$cluster, dist(USArrests_scaled))
fviz_silhouette(sil)





이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요. :-)


[Reference]

* Determining the number of clusters in a data set
   : https://en.wikipedia.org/wiki/Determining_the_number_of_clusters_in_a_data_set

* Silhouette (Clustering): https://en.wikipedia.org/wiki/Silhouette_(clustering)

* Peter J. Rousseeuw, Journal of Computational and Applied Mathematics 20 (1987), "Silhouettes: a Graphical Aid to the Interpretation and Validation of Cluster Analysis"



728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 (1) 응집형 계층적 군집화(Agglomerative Hierarchical Clustering) 방법 5가지(단일연결법, 완전연결법, 평균연결법, 중심연결법, Ward연결법) 중에서, 오차제곱합의 증분으로 군집 간 (비)유사성을 측정해서 군집화를 하는 Ward 연결법에 대해서 알아보았습니다.

 

 

이번 포스팅부터는 (2) 분할적 군집화(Partitional Clustering) 기법 중에서 프로토타입 기반(Prototype-based)K-중심 군집화(K-centroid clustering)에 대해서 알아보도록 하겠습니다.

 

 

[ 분할적 군집 (Partitional Clustering, Non-hierarchical Clustering) ]

 

 

 

 

복습하는 차원에서 한번 더 복기를 하자면,

 

- 응집형 계층적 군집화(Agglomerative Hierarchical Clustering)은 각각의 객체에서 시작해서 유사성 척도(proximity measure)에 의거해 유사한 (거리가 짧은) 객체들을 Tree 형태의 계층적 군집으로 차근 차근 묶어가는 기법입니다. (a set of nested clusters organized as a hierarchical trees).  일단 한번 군집으로 묶이면 그 객체는 계속 그 군집에 속하게 되고 변동이 없으며, 계층 구조의 Tree에서 어느 수준을 기준으로 하느냐에 따라서 군집이 달라지게 됩니다.

 

- 분할적 군집화(Partitional Clustering)은 객체가 하나의 군집에 exclusive하게 속하도록 군집을 형성합니다. (A division data objects into non-overlapping subsets such that each data object is in exactly one subset). 분할 방법에는 프로토타입 기반(Prototype-based), 분포 기반(distribution-based), 밀도 기반(Density-based), 그래프 기반(Graph-based) 기법이 있습니다.

 

 

참고로,

- Hard clustering은 객체별로 어느 군집에 속할지를 명시적으로 할당하는 기법이며,

K-중심군집은 Hard clustering에 속합니다.

 

- Soft clustering은 각 객체가 어느 군집에 속할지를 가중치(weight)나 확률(probability)로서 가능성 정도를 나타내주는 기법으로서, Fuzzy Clustering과 혼합분포군집(Mixture Distribution Clustering)이 이에 속합니다.

 

 

 

이번 포스팅에서 소개할 분할적 군집화는 이중에서 프로토타입 기반(Prototype-based) 기법 중에서도 K-중심군집(K-centroid Clustering) 모형이 되겠습니다.

 

프로토타입 기반 군집화(Prototype-based Clustering)는 미리 정해놓은 각 군집의 프로토타입에 각 객체가 얼마나 유사한가 (혹은 가까운가)를 가지고 군집을 형성하는 기법입니다. 

 

K-중심군집에서는 연속형 데이터의 경우 평균(Mean)이나 중앙값(Median)을 그 군집의 프로토타입으로 하며, 이산형 데이터인 경우는 최빈값(Mode)이나 메도이드(Medoid)라고 해서 해당 군집을 가장 잘 표현할 수 있는 측도를 정해서 프로토타입으로 정하게 됩니다.

 

보통 군집분석을 공부한다고 했을 때 가장 많이 회자되고, 가장 처음에 배우는 기법이 아마도 'K-평균 군집화(K-means Clustering)이 아닐까 싶습니다.  그런데 앞서 소개드린 것처럼 군집분석 기법에는 정말 많은 알고리즘이 있습니다. K-평균 군집은 그 중에서도 일부에 해당하는 기법일 뿐이며, 프로토타잎도 데이터 형태에 따라서 '평균(Mean)'을 쓰는 K-means Clustering, '중앙값(Median)'을 쓰는 K-median Clustering, '메도이드(Medoid)'를 쓰는 K-medoid Clustering 등으로 세분화된다는 점은 알아두시면 좋겠습니다.  이들을 모두 묶어서 'K-중심군집(K-centroid Clustering)'이라고 합니다.

 

여기서 'K'는 '군집의 수(number of clusters)'를 나타내는 모수(parameter)로서, 분석가가 사전에 정해주어야 합니다.  참고로, 군집의 수 K를 미리 지정해주어야 하는 군집분석 기법으로는 이번 포스팅의 주제인 K-중심군집(K-centroid Clustering), 그리고 퍼지군집(Fuzzy Clustering), 혼합분포 군집(Mixture Distribution Clustering) 등이 있습니다.

 

군집의 수 K를 정하는 문제가 참 중요한데요, 좀 어렵고 주관적이고 애매한 부분이 있습니다.


군집 개수별 전체 분산에서 설명가능한 분산의 비율의 꺽인 부분을 보는 The elbow method 나, 동일 군집 내 객체 간의 거리와 다른 군집 간의 거리를 고려한 실루엣 방법(Silhouette method)을 통해서 적정 군집의 개수를 선택하는 방법은 https://rfriend.tistory.com/585 또는 Wikipedia 를 참고하세요.


저는 보통은 위의 방법과 더불어 업에 대한 이해를 바탕으로 분석 목적을 감안하여 복수의 k를 지정해서 군집분석을 수행한 후에, 군집에 대한 profiling을 해보고, 가장 적합하다고 판단되는 k를 정하곤 했습니다.  다분히 분석가의 업에 대한 경험/이해도와 주관이 많이 들어가고, Biz 활용 목적과 현실적 제약조건도 고려해야 하며, 또 시행착오와 profiling을 통한 오랜 탐색이 필요합니다. 

 

 

 

[ 군집의 수 K 정하기의 애미모호함 ?  어려움?? ]

 

 

 

 

이번 포스팅에서는 일반적으로 가장 많이 사용하는 'K-평균 군집(K-means Clustering)'에 대해서만 대표로 설명을 하도록 하겠습니다.

 

 

K-평균 군집(K-means Clustering)의 원리를 알아보면요,

 

1) 군집 내 응집도 최대화(maximizing cohesion within cluster) : 군집 內 중심(centroid)과 해당 군집의 각 객체 간 거리의 합 최소화

 

2) 군집 간 분리도 최대화(maxizing separation between clusters) : 각 군집의 중심(centroid) 間 거리 합 최대화 

 

의 두 가지 목적함수를 만족하는 해(解, solution)를 찾는 것입니다.

 

 

[ K-평균 군집의 개념 및 원리 (Concept and Principle of K-means Clustering) ]

 

 

 

즉, 군집분석은 결국 위의 두 목적함수에 대한 최적화 (optimization of global objective function) 문제임을 알 수 있습니다.  복잡도(complexity)를 살펴보면, 군집의 수가 k, 차원의 수가 d, 객체의 수가 n 일 때 입니다. (* 출처 : https://en.wikipedia.org/wiki/K-means_clustering)  기본적으로 객체의 수(n)가 많을 수록 시간이 오래걸리며, 특히 변수의 수(d)와 군집의 수(k)가 늘어날 수록 지수적으로 계산 시간이 증가함을 알 수 있습니다.  따라서 허접한 변수들 몽땅 때려넣고 군집화하라고 컴퓨터한테 일 시킬 것이 아니라, 똘똘하고 핵심적인 변수를 선별해서 차원을 줄인 후에 군집분석을 실행하는 것이 연산시간을 줄이는 측면에서나, 또 Biz. 목적에 맞게 잘 군집화가 되도록 하는 측면에서나 중요합니다.

 

 

다음으로, 'K-중심군집 알고리즘(K-centroid Clustering Algorithm)'에 대해서 알아보겠습니다.  알고리즘은 알고나면 허무할 정도로 정말 쉽습니다. ^^' 컴퓨터야 중심과 객체 간 거리를 반복적으로 계산하느라 죽어나겠지만 말이지요.

 

 

[ 'K-중심군집 알고리즘(K-centroid Clustering Algorithm) ]

 

 

0: Select number of clusters, K

 

1: Select K points as the initial centroids


2: Repeat


3:     Form K clusters by assigning all points
       to the closest centroid


4:     Recompute the centroid of each cluster


5: Until The centroids don't change 

 

 

0: 군집의 수 K 결정

 

1: K개 군집의 초기 중심 선정

 

2: Repeat

 

3:    객체와 K군집의 중심과 거리가 가장 가까운

      군집으로 각 객체를 할당

 

4:    객체와 새로 바뀐 K군집의 중심과의

      거리를 재계산

 

5: Until K군집 중심이 바뀌지 않을 때까지 반복

 

 

 

 

위 알고리즘을 도식화해서 예를 들어보면 아래와 같습니다. 매번의 반복(iteration) 마다 군집의 중심이 새로 계산되고, 새로 바뀐 중심과 각 객체간 거리가 다시 계산되면서 군집이 계속 동적으로 바뀌다가 더 이상 변동이 없이 수렴될 때까지 반복을 하게 됩니다. 

 

 

[ K-평균군집화의 개념적인 예시 (Conceptual exmaple of K-means Clustering) ]

 

 

 

위의 개념적 예시 그림에서도 짐작할 수 있듯이, 초기 중심값(initial centroid)가 바뀌면 군집 묶이는게 바뀔 수 있습니다.  이런 점때문에 B2C에서 고객세분화(customer segmentation)에 K-means clustering을 적용하게 되면 매번 군집화를 시도할 때마다 군집에 묶이는 고객이 달라질 수 있어서 문제가 될 소지가 있습니다.  (참고로, R에서 set.seed = 1234 처럼 set.seed() 함수를 사용하면 무작위수가 매번 실행때마다 동일하게 할 수 있음)

 

 

이번 포스팅은 K-평균 군집(K-means Clustering)을 다룬다고 했으므로, 중심(centroid)는 '평균(Mean)'이 되겠지요.

 

그리고 유사도(proximity, similarity)는 보통은 유클리드 거리(Euclidean distance,

) 혹은 유클리드 제곱 거리(SSE, SUM of Squared Error, R에서 사용하는 거리)를 사용합니다.  데이터 특성에 따라서 유사도 측도로서 적합한 Measure를 선택해서 분석하시면 되겠습니다. (☞ 유사도 측정 Distance Measures 참고 : http://rfriend.tistory.com/199)

 

거리를 가지고 유사성을 측정한다고 했는데요, 이러다 보니 K-평균군집(K-means Clustering)은 노이즈나 이상치에 민감(Sensitive to Noise and Outlier)한 단점이 있습니다.  평균보다는 중앙값이 이상치에 덜 민감하므로 이상치로 인한 왜곡이 우려되면 K-중앙값군집(K-median Clustering)이 대안이 될 수 있겠네요.  아니면 탐색적 분석 단계에서 이상치를 제거하는 것도 방법이 될 수 있겠고요.

 

 

마지막으로, 만약 여러 변수들의 계측 단위(scale)이 서로 다르다면 사전에 표준화(standardization)를 해줄 필요가 있습니다.  안그러면 측정 단위가 큰 특정 한, 두개의 변수에 의해 군집화가 휘둘릴 수 있기 때문입니다.  보통 표준정규분포로 z 표준화를 많이 사용합니다. (R의 scale() 함수)

 

 


 

 

K-중심 군집(K-Centroid Clustering) 이론에 대해서는 왠만큼 소개를 한듯 하니, 이제 데이터셋을 가지고 R script 를 써가면서 실습을 해보겠습니다.  R script 가 무척 짧아서 당황하실수도 있다는 점 미리 안내드립니다. ㅋㅋ

 

실습 데이터셋은 iris 입니다. 

Sepal.Length, Sepal.Width, Petal.Length, Petal.Width 의 4개의 변수를 가지고 있고, 150개의 관측치를 가지고 있는 데이터프레임입니다.

 

결측값은 없이 깨끗하네요.

 

측정 척도의 단위(scale)가 4개 변수 모두 길이를 재는 동일 단위이므로 iris 데이터셋의 경우 별도로 표준화르 할 필요는 없겠네요. 

 

> ##-----------------------------------
> ## K-centroid clustering
> ##-----------------------------------
> 
> # dataset : iris
> str(iris)
'data.frame':	150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> 
> # checking missing value
> colSums(is.na(iris))
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
           0            0            0            0            0

 

 

 

 

산포도(Scatter Plot)를 그려보면 아래와 같습니다.

 

> # scatter plot of iris
> panel.fun <- function(x, y, ...) {
+   horizontal <- (par("usr")[1] + par("usr")[2]) / 2; 
+   vertical <- (par("usr")[3] + par("usr")[4]) / 2; 
+   text(horizontal, vertical, format(abs(cor(x,y)), digits=2)) 
+ }
> 
> pairs(iris[1:4], 
+       pch = 21, bg = c("red","green3","blue")[unclass(iris$Species)], 
+       upper.panel=panel.fun, 
+       main = "Statter Plot of Iris Dataset")

 

 

 

 

K-means Clustering이 중심과의 거리를 가지고 군집을 묶는 방법이다보니, 위의 산포도를 보면 Petal.Length와 Petal.Width 의 두개의 변수를 가지고 군집화(Clustering)를 하는 것이 제일 좋을 것 같군요.(아마 Sepal.Width와 Petal.Length 의 두개 변수를 사용해서 K-means Clustering을 돌리면 좌측 상단의 두 Species가 반반씩 잘못 섞여서 군집화가 될겁니다. 왜 그럴지는 한번 생각해보시길...) 

 

Petal.Length와 Petal.Width 로 산점도를 그려보면 아래와 같습니다.

 

[plot 1 : original scatter plot]

 

 

> # Original Scatter Plot of Iris Petal.Length & Petal.Width 
> install.packages("ggplot2")
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.3/ggplot2_2.1.0.zip'
Content type 'application/zip' length 2001758 bytes (1.9 MB)
downloaded 1.9 MB

package ‘ggplot2’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
	C:\Users\Administrator\AppData\Local\Temp\Rtmpi20q05\downloaded_packages
> library(ggplot2)
> iris_plot <- ggplot(data=iris, aes(x=Petal.Length, y=Petal.Width, colour=Species)) + 
+   geom_point(shape=19, size=4) + 
+   ggtitle("Original Scatter Plot of Iris Petal.Length & Petal.Width")
>   
> iris_plot
> # text annotation with Species Name
> iris_plot_2 <- iris_plot +
+   annotate("text", x=1.5, y=0.7, label="Setosa", size=5) + # text annotation
+   annotate("text", x=3.5, y=1.5, label="Versicolor", size=5) + 
+   annotate("text", x=6, y=2.7, label="Virginica", size=5)
> 
> iris_plot_2
> # adding shadowed box
> iris_plot_3 <- iris_plot_2 +
+   annotate("rect", xmin=0, xmax=2.6, ymin=0, ymax=0.8, alpha=0.1, fill="red") + 
+   annotate("rect", xmin=2.6, xmax=4.9, ymin=0.8, ymax=1.5, alpha=0.1, fill="green") + 
+   annotate("rect", xmin=4.8, xmax=7.2, ymin=1.5, ymax=2.7, alpha=0.1, fill="blue")
> 
> iris_plot_3

 

 

 

 

 

Noise나 이상값(outlier)는 없어보이므로 별도 전처리 없이 그대로 데이터 가져다 쓰면 되겠네요.

 

자, 이제 드디어 K-평균군집(K-means Clustering)을 R로 돌려보겠습니다.  군집의 개수 K = 3 으로 하겠습니다. (iris 품종으로 Setosa, Versicolor, Virginica 의 3종류가 있다고 우리가 이미 알고 있기 때문에 K 3으로 한 것임.  일반적으로 K-평균군집분석을 할 때 Y Label에 대해서 모르거나 없는 상태에서 비지도학습(Un-supervised Learning)으로서 데이터 속에 숨겨진 패턴을 컴퓨터 보고 한번 찾아보라고 마이닝을 시키게 됨.  다시 한번 말하지만, 이번 iris 데이터셋은 Y Lable을 알고 있는 상태에서 K-평균군집분석 결과를 좀더 이해하기 쉽도록 비교해서 보여주는 것 뿐이며, Y Lable 모른 채, 혹은 없는 상태에서 군집분석을 수행하게 됨)

 

K-평균군집의 R script는..... 음..... 아래 한줄이 끝입니다. -_- 

 

kmeans(dataset, k)  # k : number of clusters

 

> # K-means clustering with Petal.Length and Petal.Width
> iris_k_means <- kmeans(iris[,c("Petal.Length", "Petal.Width")], 3) 

 

 

 

K-평균군집의 객체 iris_k_means 를 호출하면 아래와 같이 K-평균 군집 결과를 일목요연하게 볼 수 있습니다. 

 

- K-means clustering with 3 clusters of sizes 50, 52, 48

   : 군집의 개수(k)가 3개, 군집 1/2/3별 크기가(개체 개수) 50개, 52개, 48개

- Cluster means

   : 군집 1/2/3 별 두개의 변수 Petal.Length, Petal.Width의 평균 좌표 

     (=> profiling 하기에 good!)

- Clustering vector

   : 각 개체별 군집 벡터
- Within cluster sum of squares by cluster

   : 각 군집의 중심(centroid)와 각 군집에 속한 개체간 거리의 제곱합

- Available components

   : 군집분석 결과의 구성요소
     => 필요한거 있으면 이 객체(object)를 indexing해서 쓰면 요긴함
 

 

> iris_k_means
K-means clustering with 3 clusters of sizes 50, 52, 48

Cluster means:
  Petal.Length Petal.Width
1     1.462000    0.246000
2     4.269231    1.342308
3     5.595833    2.037500

Clustering vector:
  [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 1 2
 [52] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3
[103] 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3

Within cluster sum of squares by cluster:
[1]  2.02200 13.05769 16.29167
 (between_SS / total_SS =  94.3 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"   

 

 

 

 

아래처럼 names() 함수를 써서 군집분석 결과의 객체들에 무엇이 있는지 확인해볼 수도 있습니다.

 

- cluster : 각 개체별 할당된 군집 번호, 1부터 k번까지 군집 숫자 

             (A vector of integers (from 1:k) indicating the cluster to which each point is allocated.)

- centers : 군집의 중심 (centroid) 좌표 행렬 (A matrix of cluster centres.)

- totss : 제곱합의 총합 (total sum of squares)

- withinss : 군집 내 군집과 개체간 거리의 제곱합 벡터.

               (Vector of within-cluster sum of squares, one component per cluster)

- tot.withinss : 군집 내 군집과 개체간 거리의 제곱합의 총합, 즉, sum(withinss)

                   (Total within-cluster sum of squares, i.e. sum(withinss))

- betweenss : 군집과 군집 간 중심의 거리 제곱합

                   (The between-cluster sum of squares, i.e. totss-tot.withinss)

- size : 각 군집의 개체의 개수 (The number of points in each cluster)

- iter : 반복 회수 (The number of (outer) iterations)

- ifault : 전문가용의 발생 가능한 알고리즘 문제의 indocator (?? 이거 뭔지 잘 모르겠음... -_-??)
           (integer: indicator of a possible algorithm problem – for experts)

 

> # objects of k-means clustering in R
> names(iris_k_means)
[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"

 

 

 

 

그럼, 군집의 크기(객체의 개수)를 한번 확인해볼까요?  table() 함수를 써도 되고 size 객체를 가져다가 확인해도 됩니다. 두 가지 방법 모두 아래에 소개하였습니다.

 

> # cluster size > table(iris_k_means$cluster) 1 2 3 50 52 48


>
iris_k_means$size [1] 50 52 48 > > prop.table(iris_k_means$size) [1] 0.3333333 0.3466667 0.3200000

 

 

 

 

각 군집 1, 2, 3의 중심(centroid)도 확인해보겠습니다.

 

> # centroid of clusters
> iris_k_means$centers
  Petal.Length Petal.Width
1     1.462000    0.246000
2     4.269231    1.342308
3     5.595833    2.037500 

 

 

 

마지막으로, 각 개체들을 군집별로 색깔을 달리해서 산점도(scatter plot) 그려보겠습니다.  덤으로 각 군집의 중심(centroid)을 검정색 점으로 해서 덮입혀보았습니다.

 

위의 [plot 1 : original scatter plot]에서 iris species 로 색깔을 구분해서 그린 산점도와 아래의 군집(cluster)별로 색깔을 구분해서 그린 산점도가 거의 유사하지요?

 

> # Scatter plot of Iris' K-menas clusters
> cluster <- iris_k_means$cluster
> iris_k_means_x_y <- cbind(cluster, iris[,c("Petal.Length", "Petal.Width")])
> head(iris_k_means_x_y)
  cluster Petal.Length Petal.Width
1       1          1.4         0.2
2       1          1.4         0.2
3       1          1.3         0.2
4       1          1.5         0.2
5       1          1.4         0.2
6       1          1.7         0.4
> 
> sapply(iris_k_means_x_y, class)
     cluster Petal.Length  Petal.Width 
   "integer"    "numeric"    "numeric" 
> iris_k_means_x_y <- transform(iris_k_means_x_y, 
+                               cluster = as.factor(cluster))
> 
> sapply(iris_k_means_x_y, class)
     cluster Petal.Length  Petal.Width 
    "factor"    "numeric"    "numeric" 
> 
> 
> library(ggplot2)
> iris_k_means_x_y_plot <- ggplot(data=iris_k_means_x_y, 
+                                 aes(x=Petal.Length, y=Petal.Width, colour=cluster)) + 
+   geom_point(shape=19, size=4) + 
+   ggtitle("Scatter Plot of Iris' K-means clusters")
> 
> iris_k_means_x_y_plot
> 
> 
> # adding centroid points of cluster 1, 2, 3
>   # centers(centroids) by cluster 1, 2, 3
> iris_k_means_centers <- iris_k_means$centers
> iris_k_means_centers
  Petal.Length Petal.Width
1     1.462000    0.246000
2     4.269231    1.342308
3     5.595833    2.037500
> 
> iris_k_means_x_y_plot_2 <- iris_k_means_x_y_plot +
+   annotate("point", x = 1.462, y = 0.246, size = 6, color = "black") + 
+   annotate("point", x = 5.595, y = 2.037, size = 6, color = "black") + 
+   annotate("point", x = 4.269, y = 1.342, size = 6, color = "black") + 
+   
+   annotate("text", x=1.462, y=0.4, label="Cluster 1", size=5) + 
+   annotate("text", x=5.595, y=2.2, label="Cluster 2", size=5) + 
+   annotate("text", x=4.269, y=1.5, label="Cluster 3", size=5)
>  
> iris_k_means_x_y_plot_2

 

 

 

 

 

이상으로 K-중심 군집의 하나인 K-평균군집(K-means Clustering)에 대해서 알아보았습니다.

 

다음번 포스팅에서는 프로토타입 기반(Prototype-based) 군집분석의 두번째 기법으로 퍼지 군지(Fuzzy Clustering)에 대해서 알아보겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감~♡'를 꾸욱 눌러주세요.

 

 

[Reference]

(1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book

(2) "Clustering Algorithm", Ana Fred, INSTITUTO SUPERIOR TECNICO, Universidade Techica de Lisboa, 2009

(3) "R, SAS, MS-SQL을 활용한 데이터마이닝", 이정진 지음, 자유아카데미, 2011

(4) "Data Mining Cluster Analysis : Basic Concepts and Algorithms", Tan, Steinbach, Kumar, 2004

(5) Wikipedia :

    https://en.wikipedia.org/wiki/K-means_clustering

    https://en.wikipedia.org/wiki/Determining_the_number_of_clusters_in_a_data_set

   

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Y값에 대한 Label이 없는 비지도학습(unsupervised learning)의 두번째 기법으로 '군집분석 (Cluster Analysis, Clustering)'에 대해서 소개하도록 하겠습니다.

 

1) 군집분석(cluster analysis)이란?

 

군집분석이란 데이터가 속해 있는 군집을 모르는 상태에서(Y값 label 없음) 유사한 혹은 동질의 데이터끼리 군집(cluster)로 묶어 주는 분석기법입니다.

 

 

 

 사자성어 중에 보면

 

"유유상종(類類相從)", "끼리 끼리 모인다"라는 말이 있는데요, 군집분석을 잘 나타내는 말 같습니다.

 

 

서양 속담에도 비슷한 것이 있습니다.

 

"Birds of a feather flock together"

 * 그림 출처 : http://www.winglish.com/free/asp/mrwin_default_com.asp?j_num=6

 

 

군집분석은 유의미하거나 유용한 데이터의 구조를 파악하여 활용(clustering for utility)하거나, 데이터의 구조를 이해(understanding)하는 목적으로 분석 초기 탐색적 분석 단계에서 아주 많이 활용하곤 합니다.  

 

군집분석은 마케팅, 심리학, 사회학, 통계, 패턴 인식, 기계학습, 데이터마이닝 등에 다방면에 사용됩니다. 마케팅, CRM에 종사하는 분들은 고객세분화(cutomer segmentation) 하는데 군집분석 & 프로파일링 (customer clustering & profiling) 에 대해서 들어보았거나 시도를 해봤을 것 같습니다.  

 

(1) 군집분석으로 고객세분화를 먼저 수행하고 (un-supervised learning) -> (2) Decision Tree를 사용해서 군집분석을 통해 만든 군집들을 분류(Classification, supervised learning)하는 모델을 만드는 semi-supervised learning approach를 취하는 것도 생각해 볼 수 있을 것입니다.

 

데이터가 X와 Y의 2차원으로만 구성되어 있다면 산점도(scatter plot)을 그려서 눈으로 확인해보는 것만으로도 데이터셋에 내재한 패턴, 군집 유무, 데이터 간 관계를 어림짐작할 수 있습니다.  3차원도 (좀 보기에 헷갈리기는 하지만) 3D plot을 그려서 눈으로 확인할 수 있습니다. 하지만 4차원 이상 넘어가면 사람 눈으로 군집 유무 여부를 확인, 판단하는게 어려워집니다. 이때 군집분석을 활용하면 좋겠지요?!  개별 나무를 몰라도 (데이터셋에 대한 사전지식이 없어도) 숲에 대한 조감도(군집)를 찾을 수 있다니 군집분석은 참 유용한 데이터 마이닝 (숨은 지식, 패턴 캐내기) 기법입니다.

 

 

 

2) 군집분석의 원리(Principal of custer analysis)는?

 

군집분석은 데이터가 어떤 군집에 속해있는지 알 수 있는 Y값 Label이 없는 상태에서 진행된다고 하였으므로 지도학습(supervised learning)처럼 명쾌한 모델성능평가가 쉽지가 않습니다.  군집을 몇 개로 하느냐에 따라서도 군집화가 영향을 많이 받기도 하는데요, 보통은 데이터 내 군집이 몇 개 있는지 모르는 경우가 많습니다.

 

그렇다면 군집분석에서 모델 생성, 평가는 무슨 기준으로 하는 것일까 하는 의문이 들 것입니다. 군집분석에서는 주로 응집도(cohesion)분리도(separation) 척도를 많이 사용하는 편인데요, 군집분석을 컴퓨터가 이해하도록 수식, 척도를 가지고 군집화의 원리를 나타내보면

 

      (1) 군집 內 응집도를 최대화하고, (maximizing cohesion within cluster,
                                                    i.e. minimizing sum of distance b/w x and y) 

  (2) 군집 間 분리도를 최대화하도록 (maximizing separation between clusters)

 

군집을 형성한다는 것입니다.

 

 

 

 

 

군집분석 알고리즘의 근간에는 최적화(optimization) 개념이 들어있음을 알 수 있습니다.

 

Graph-based clustering과 Prototype-base clustering 의 두 가지 approach별로 나누어서 응집도(cohesion)와 분리도(separation)의 개념을 수식과 시각화로 같이 나타내면 아래와 같습니다.

 

 

 (2-a) 그래프 기반 응집도와 분리도 (Graph-based view of cohesion and separation)

 

 

 

 

 (2-b) 프로토타입 기반 응집도와 분리도 (Prototype-base view of cohesion and separation)

 

아래에 군집의 중심(centroid)을 기준으로 군집 내 데이터와 중심 간 거리를 가지고 응집도를, 군집 중심 간의 거리를 가지고 분리도를 나타내보았습니다. 

 

 

 

 

3) 군집분석에에는 어떤 유형이 있나?  어떻게 구분할 수 있나?

 

 군집분석을 구분할 수 있는 기준이 여러개 있을 수 있는데요, 한 군집 안에 부분군집이 있느냐 없느냐에 따라서 계층적 군집(hierarchical clustering)분할적 군집(partitional clustering)으로 나눌 수 있습니다. 계층적 군집은 한 군집 안에 부분군집이 있는 반면, 분할적 군집은 군집간 부분집합이나 중복없이 상호 배타적으로(exclusive) 존재합니다. 아래 그림의 이미지를 참고하시면 이해하기 쉬울거예요.   

 

 

 

 

   (3-a) 계층적 군집분석 (Hierarchical Clustering)

 

계층적 군집분석은 (3-a-1) 개별 데이터에서 시작해서 유사한 데이터끼리 군집으로 차근차근 묶어가는 기법인 응집형 방법 (Aggolomerative, Bottom-up method)과, 응집형과는 반대로 (3-a-2) 모든 데이터를 하나의 군집에 속한다고 놓고, 차근차근 세부 군집으로 나누어가는 분리형 방법 (Divisive, Top-down method) 으로 구분할 수 있습니다.

 

 

일반적으로 군집 간 합치기와 분할은 greedy manner (각 단계별 국소 최적해를 찾아가는 휴리스틱 최적화 알고리즘) 에 의해서 결정이 됩니다. 일반적인 경우 응집형(agglomerative) 군집화의 복잡도(complexity)는 으로서 큰 규모의 데이터셋에 적용하기에는 시간이 너무 오래 걸려서 무리일 수 있습니다. 일부 특별한 경우로, 단일(최단) 연결(single-linkage (SLINK)), 완전(최장) 연결법(complete-linkage, CLINK)는 복잡도가 로서 최적의 효과적인 응집형 방법으로 알려져 있습니다. 모든 관측치를 상호배타적으로 탐색하는 경우의 분리형(divisive) 군집화는 복잡도가 으로서 아주 끔찍한 수준입니다. ^^; (from Wikipedia)

앞으로 연재할 때 복잡도가 어마무시 높은 분리형 군집화는 제외하도록 할께요.  

 

응집형(Agglomerative) 방법에는 군집간 거리 척도와 연결법에 따라서 단일(최단) 연결법 (Single Linkage Method), 완전(최장) 연결법 (Complete Linkage Method), 평균 연결법 (Average Linkage Method), 중심 연결법 (Centroid Linkage Method), Ward 연결법 (Ward Linkage Method)이 있습니다.

분리형(Divisive) 방법에는 DIANA 방법(DIANA algorithm)이 있습니다.

 

 

 

 

  (3-b) 분할적 군집분석 (Partitional Clustering, Non-Hierarchical clustering)

 

분할적 군집(Partitional clustering) 방법에는 거리 기반 군집화 (distance-based clustering), 밀도 기반 군집화(density-based clustering), 신경망 기반 군집화 (neural network-based clustering) 등이 있습니다.

 

(3-b-1) 프로토타입 기반(Prototype-based) 군집화 기법에는 K-중심 군집(K-centroid clustering), 퍼지 군집(Fuzzy clustering)

 

(3-b-2) 분포 기반(Distribution-based) 군집화에는 혼합분포 군집(Mixture distribution clustering)이 있습니다.

 

(3-b-3) 밀도 기반(Density-based) 군집화 기법에는 중심 밀도 군집(Center density clustering), 격자 기반 군집(Grid-based clustering), 커넬 기반 군집(Kernel-based clustering) 등이 있습니다.

 

(3-b-4) 그래프 기반(Graph-based) 군집화에는 코호넨 군집(Kohenen clustering) 이 있습니다.

 

 

 

보통 군집분석 공부한다고 하면 'K-means clustering' 알고리즘 공부하고 끝내는 경우가 있는데요 (좀더 공부한다면 계층적 군집화 일부...), 위에 제시한 것처럼 군집분석 기법/알고리즘이 상당히 많이 있습니다. 분석 기법이 많다보니 뭘 써야하나 혼란스러울 수 있는데요, 군집분석 알고리즘별로 데이터 특성과 구조, 분석 목적에 맞게 보다 적절한 알고리즘이 있습니다. 따라서 분석가는 각 알고리즘의 개념, 특성, 장점과 단점을 알고 있어야 하고, 분석 목적, 데이터 특성에 맞게 잘 선택해서 사용할 줄 알아야 하겠습니다.

 

위에서는 분석 기법 이름만 구조를 잡아서 나열을 했는데요, 앞으로 하나씩 차근차근 알고리즘 설명과 예시, 그리고 R script를 풀어보도록 하겠습니다.  

 

 

[Reference]

 

1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book

2) Wikipedia

 

 

다음번 포스팅에서는 기초체력을 다지고 시작한다는 의미에서 군집분석에서 유사성(similarity), 비유사성(dis-similarity)의 척도에 대해서 알아보도록 하겠습니다.

 

이번 포스팅이 도움이 되었다면 아래 '공감 ~♡'를 꾸욱 눌러주세요.

 

728x90
반응형
Posted by Rfriend
,