K-means 클러스터링 r - k-means keulleoseuteoling r

k-평균(k-means algorithm) 군집 분석이란? 

K-평균 알고리즘의 3단계

1) 임의로 k개의 데이터 포인트를 시드로 선택

2) 각각의 레코드를 가장 가까운 시드에 배정하여 묶음. (각 개체들과 시드 간의 거리를 구함)

3) 군집의 중심점을 찾아감

 군집의 중심점이 다음 2단계에서 시드가 됨. 

 2와 3 단계가 계속 반복됨. 

 군집의 경계가 더 이상 변하지 않을 때까지 계속 됨.

k-평균 알고리즘의 예시

1) 프로세스 1: 군집수 k를 2로 정함. -> 랜덤으로 2개의 시드를 초기화 함. (이 값은 random seed에 따라 달라짐)

K-means 클러스터링 r - k-means keulleoseuteoling r
파란 동그라미 - 각 객체들/ 빨란 네모 - 시드

2) 프로세스 2: 모든 개체들과 두 시드와의 거리를 계산하여 가장 가까운 시드에 배정함으로써 군집을 생성.

K-means 클러스터링 r - k-means keulleoseuteoling r

3) 프로세스 3: 묶여진 군집 내에서 중심을 이동.

K-means 클러스터링 r - k-means keulleoseuteoling r

4) 프로세스 2': 이동한 중심을 기준으로 가장 가까운 시드에 배정하여 군집을 생성.

K-means 클러스터링 r - k-means keulleoseuteoling r

5) 프로세스 3': 묶여진 군집 내에서 중심이 이동됨.

K-means 클러스터링 r - k-means keulleoseuteoling r

6) 이동한 중심을 기준으로 가장 가까운 시드에 배정하여 군집을 생성. 만약 군집이 변함이 없다면 프로세스 종료.

K-means 클러스터링 r - k-means keulleoseuteoling r

K-means의 장단점은?

장점

  • 계층적 군집화보다 계산이 빠름

  • 보다 안정적인 결과를 제시

단점

  • 군집 수를 미리 정해야 함 → 군집 수에 따라 군집의 품질이 달라짐, 군집 수 정하는 것부터 수십번 반복할 수도 있음

  • 초기 값에 따라 결과가 달라질 수 있음 → nstart 파라미터를 사용해 여러번 수행함으로써 분산이 가장 작은 값 선택

  • 이상치에 민감함 → k-medoids 사용 

실습

  • Data: wine 데이터
  • NbClust package: 군집수를 선택하는데 도움을 주는 함수 제공. (군집 평가하는 23 가지 지수와 가장 적당한 군집수 가이드 제공)
  • Factoextra package: 주성분 분석 제공, 고차원 데이터를 저차원 투영 해줌

#####  k- means 군집분석  #####

if (require("HDclassif") == F) install.packages("HDclassif") #for sample data
if (require("NbClust") ==F) install.packages("NbClust") #for cluster profileling
if (require("cluster") == F) install.packages("cluster") #for sample data
if (require("sparcl") == F) install.packages("sparcl") #for visualization
if (require("compareGroups") == F) install.packages("compareGroups")
if (require("factoextra") == F) install.packages("factoextra") #for visualization

library(dplyr)
library(cluster)
library(compareGroups)
library(NbClust)
library(sparcl)
library(HDclassif)
library(factoextra)
library(ggplot2)

set.seed(1234) #k-means 자체가 랜덤씨드 가져다가 초기값을 선택 --> 재현성을 높여주기 위해 시드 정해줌

#데이터 불러오기 및 확인

data(wine)
str(wine)
names(wine) <- c("Class", "Alcohol", "MalicAcid", "Ash", "Alk_ash", "magnesium",
                 "T_phenols", "Flavanoids", "Non_flav", "Proantho", "C_Intensity",
                 "Hue", "OD280_315", "Proline")

head(wine)

wine_scale <- scale(wine[,-1]) #class 변수 제외
wine_scale <- as.data.frame(wine_scale) #scale 함수를 사용한 경우 데이터 프레임형태로 바뀜뀜

str(wine_scale)

#몇개의 군집을 만들까?!

num_kmeans <- NbClust(wine, min.nc = 2, max.nc = 6, method = "kmeans", index = "all")
km_2 <- kmeans(wine_scale, 2, nstart = 30)
km_3 <- kmeans(wine_scale, 3, nstart = 30)

table(km_2$cluster)
table(km_2$cluster, wine$Class)

table(km_3$cluster)
table(km_3$cluster, wine$Class)

#시각화 (전체 데이터) wiht PCA
princ <- prcomp(wine_scale, retx = T)

project <- as.data.frame(predict(princ, newdata = wine_scale)[,1:2])

project$class <- wine$Class
project$km_2 <- km_2$cluster
project$km_3 <- km_3$cluster

ggplot(project, aes(x = PC1, y = PC2, colour = factor(km_2), shape = factor(class))) + geom_point(size = 3)
ggplot(project, aes(x = PC1, y = PC2, colour = factor(km_3), shape = factor(class))) + geom_point(size = 3)

K-means 클러스터링 r - k-means keulleoseuteoling r
K-means 클러스터링 r - k-means keulleoseuteoling r

2개의 군집, 3개의 군집으로 각각 나눴을 때