[ADP] K-평균 군집 (K-means Clustering)
> # 10. K-평균 군집 (K-means Clustering)
>
>
> # 군집 수에 따른 집단 내 제곱합(within group sum of squares)을 구하고 그래프를 그리는 함수 정의
> wssplot <- function(data, nc=15, seed=1234) {
+ 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 Cluster', ylab='Within Group sum of squares')
+ }
>
> library(rattle)
>
> # 178개 이탈리아 와인에 대한 13가지의 화학적 성분을 측정한 자료이다.
> data("wine")
> head(wine)
Type Alcohol Malic Ash Alcalinity Magnesium Phenols Flavanoids Nonflavanoids Proanthocyanins Color Hue Dilution Proline
1 1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
2 1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
3 1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
4 1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
5 1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735
6 1 14.20 1.76 2.45 15.2 112 3.27 3.39 0.34 1.97 6.75 1.05 2.85 1450
>
> # 변수의 측정 단위가 다르므로 군집분석 수행 전에 데이터 표준화
> df <- scale(wine[-1])
>
> wssplot(df)
> # 군집수 3에서 오차제곱합이 크게 감소되었음을 알 수 있다.
>
> # NbClust 패키지로도 확인
> library(NbClust)
> set.seed(1234)
> 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
*******************************************************************
> nc$Best.nc
KL CH Hartigan CCC Scott Marriot TrCovW TraceW Friedman Rubin Cindex
Number_clusters 3.0000 3.00 3.0000 14.0000 3.0000 3 3.0 3.0000 3.0000 3.0000 2.0000
Value_Index 14.3567 70.94 41.7215 6.3155 374.2416 33048027677429170724246662 10183.3 305.3194 10.0771 -0.3046 0.3018
DB Silhouette Duda PseudoT2 Beale Ratkowsky Ball PtBiserial Frey McClain Dunn Hubert SDindex
Number_clusters 3.0000 3.0000 3.0000 3.0000 3.0000 3.0000 3.0000 3.0000 1 2.000 3.0000 0 3.0000
Value_Index 1.4681 0.2849 1.5712 -33.0827 -3.1777 0.3748 401.2608 0.6154 NA 0.641 0.2323 0 1.0492
Dindex SDbw
Number_clusters 0 15.0000
Value_Index 0 0.3746
> # 최적의 군집수를 정하기 위해 사용되는 지수(총 30개 중 여기서는 26개 지수가 계산됨) 중에서 19개의 지수가 3을 최적의 군집수로 다수결 투표했음을 알 수 있다.
>
> par(mfrow=c(1,1))
> barplot(table(nc$Best.nc[1,]), xlab='Number of Cluster', ylab='Number of Criteria', main='Number of Cluster Chosen by 26 Criteria')
> # 최적의 군집수에 대한 다수결 결과를 시각화
>
> set.seed(1234)
> # k-means 수행
> fit.km <- kmeans(df, 3, nstart = 25)
> # 각 군집의 크기 확인
> fit.km$size
[1] 62 65 51
>
> # 군집결과 시각화
> par(mfrow=c(1,1))
> plot(df, col=fit.km$cluster)
> # 각 군집의 중심점 추가
> points(fit.km$centers, col=1:3, pch=8, cex=1.5)
>
> # 군집결과 요약
> aggregate(wine[-1], by=list(cluster=fit.km$cluster), mean)
cluster Alcohol Malic Ash Alcalinity Magnesium Phenols Flavanoids Nonflavanoids Proanthocyanins Color
1 1 13.67677 1.997903 2.466290 17.46290 107.96774 2.847581 3.0032258 0.2920968 1.922097 5.453548
2 2 12.25092 1.897385 2.231231 20.06308 92.73846 2.247692 2.0500000 0.3576923 1.624154 2.973077
3 3 13.13412 3.307255 2.417647 21.24118 98.66667 1.683922 0.8188235 0.4519608 1.145882 7.234706
Hue Dilution Proline
1 1.0654839 3.163387 1100.2258
2 1.0627077 2.803385 510.1692
3 0.6919608 1.696667 619.0588
> # 각 군집별 변수의 평균값을 확인할 수 있다.
>
> # k-평균군집의 정오분류표 확인
> 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
> # 대각선 방향이 정분류이므로 정확도는 172/178*100=96.6%이다.
>
> library(flexclust)
> randIndex(ct.km)
ARI
0.897495
> # flexclust 패키의 randIndex() 함수를 이용하면 실제 와인의 종류(Type)와 군집 간의 일치도(agreement)를 나타내는 수정된 랜드지수를 구할 수 있다. 이 지수는 -1(no agreement)과 1(perfect agreement) 사이의 값을 가진다.
>
출처 : 2020 데이터 분석 전문가 ADP 필기 한 권으로 끝내기