군집분석

군집분석: 각 개체에 대해 관측된 여러 개의 변수 값들로부터 n개의 개체를 유사한 성격을 가지는 몇 개의 군집으로 집단화하고, 형성된 군집들의 특석을 파악하여 군집들 사이의 관계를 분석하는 비지도 학습 기법이며 지식발견 그 자체 혹은 알려지지 않았던 통찰을 발견하고 목적변수가 없는 상태에서 유사한 특성을 가진 개체끼리 그룹화 한다.

The difference between K means and Hierarchical Clustering

계층적 군집 분류는 모든 객체가 하나의 군집에 포함되는 경우부터 객체 하나 하나가 각각의 군집을 구성하는 경우까지 단계적으로 군집을 구성하는 방법이다. 이 방법에는 상향식 방법과 하향식 방법이 있다. k-평균 군집 분류는 사용자가 군집의 개수 ’k’를 미리 결정하는 방법으로, 초기화 상태에 따라 다양한 결과를 얻게 된다.

1. 계층적 군집

계층적군집:가장 유사한 개체를 묶어나가는 과정을 반복하여 원하는 개수의 군집을 형성하는 방법이고보통 덴드로그램의 형태로 결과가 주어진다.

병합적 방법: 작은 군집으로부터 출발하여 군집을 병행해 나간다.

분할적 방법: 큰 군집으로부터 출발하여 군집을 분리해나가는 방법이다.

응집법

예제1: USArrests - 미국 50개 주에서 1973년에 발생한 폭행, 살인, 강간 범죄를 주민 10만명당 체포된 사람의 통계 자료이다.

# 데이터 추출
data("USArrests")

# view data
#View(USArrests)

# 구조 
str(USArrests)
## 'data.frame':    50 obs. of  4 variables:
##  $ Murder  : num  13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
##  $ Assault : int  236 263 294 190 276 204 110 238 335 211 ...
##  $ UrbanPop: int  58 48 80 50 91 78 77 72 80 60 ...
##  $ Rape    : num  21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9 25.8 ...
# 거리
d<-dist(USArrests, method = 'euclidean')

# 계층분석
fit<-hclust(d, method = 'ave') # 군집간의 평균을 구하면서 군집화

# 시각화
plot(fit)

# k=6
plot(fit)
rect.hclust(fit, k=6, border = 'red' )

# Height = 70
plot(fit)
rect.hclust(fit, h=70)

2. k-평균 군집

k-평균 군집은 군집의 매 단계마다 군집 중심으로부터 오차 제곱합을 최소화하는 방향으로 군집을 형성한다.

k-평균은 원하는 군집수만큼 초기 k 값을 지정하고 군집을 형성한뒤 각 군집의 평균을 재계산하여 초기값을 갱신한다. 다시 군집 형성 반복

k = 2 예시

그럼 어떻게 최적의 k 값을 찾을까?

군집 수에 따른 집단 내 제곱합 그래프

wssplot<-function(data, nc = 15, seed = 123){
  wss<-(nrow(data)-1) * sum(apply(data,2,var))
  for (i in 2:nc){
    set.seed(seed)
    wss[i]<-sum(kmeans(data, centers = i)$withinss)}

  plot(1:nc, wss, type = 'b', xlab = 'Number of Clusters',
       ylab = 'Within groups sum of squares')
}

예제 1. rattle 패티지에서 제공하는 178개 이탈리안 와인에 대해 13 가지의 화학적 성분 측정

# 데이터 추출
data(wine, package = 'rattle')

# View data
#View(wine)

# 변수의 단위가 다르므로 표준화 
df<-scale(wine[-1]) # remove type

# arm plot
wssplot(df)

군집수 3 에서 오차제곱합이 크게 감소되었음을 확인할 수 있다. Nbclust로 확인해보자.

library(NbClust)

set.seed(123)

nc<-NbClust(df, min.nc = 2, max.nc = 15, method = 'kmeans')

## *** : The Hubert index is a graphical method of determining the number of clusters.
##                 In the plot of Hubert index, we seek a significant knee that corresponds to a 
##                 significant increase of the value of the measure i.e the significant peak in Hubert
##                 index second differences plot. 
## 

## *** : The D index is a graphical method of determining the number of clusters. 
##                 In the plot of D index, we seek a significant knee (the significant peak in Dindex
##                 second differences plot) that corresponds to a significant increase of the value of
##                 the measure. 
##  
## ******************************************************************* 
## * Among all indices:                                                
## * 2 proposed 2 as the best number of clusters 
## * 19 proposed 3 as the best number of clusters 
## * 1 proposed 14 as the best number of clusters 
## * 1 proposed 15 as the best number of clusters 
## 
##                    ***** Conclusion *****                            
##  
## * According to the majority rule, the best number of clusters is  3 
##  
##  
## *******************************************************************
barplot(table(nc$Best.n[1,]),
        xlab = 'Number of Clusters',
        ylab = 'Number of Criteria',
        main = 'Number of Clusters Chosen by 26 Criteria')

set.seed(1234)

# nstart option attempts multiple initial configurations and reports on the best one. For example, adding nstart=25 will generate 25 initial random centroids and choose the best one for the algorithm

# k = 3
fit.km<-kmeans(df, 3, nstart = 25)
fit.km$cluster
##   [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
##  [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 3 2 2 2 2 2 2 2 2 2 2 2 1
##  [75] 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [112] 2 2 2 2 2 2 2 3 2 2 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [149] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
# 시각화 
plot(df, col = fit.km$cluster)
points(fit.km$center, col = 1:3, pch = 8, cex = 1.5)

# 정오분류표 (accuracy)
ct.km <- table(wine$Type, fit.km$cluster)
ct.km
##    
##      1  2  3
##   1 59  0  0
##   2  3 65  3
##   3  0  0 48