k- 평균 군집화는 혼합 유형의 데이터로 수행해서는 안됩니다. k- 평균은 본질적으로 군집 관측치와 군집 중심 사이의 클러스터 내 제곱 유클리드 거리를 최소화하는 파티션을 찾기위한 간단한 검색 알고리즘이므로, 제곱 유클리드 거리가 의미가있는 데이터에만 사용해야합니다.
데이터가 혼합 유형의 변수로 구성된 경우 Gower의 거리를 사용해야합니다. CV 사용자 @ttnphns는 Gower의 거리에 대한 훌륭한 개요를 제공 합니다 . 본질적으로 해당 변수 유형에 적합한 거리 유형 (예 : 연속 데이터의 유클리드 등)을 사용하여 각 변수의 행에 대한 거리 행렬을 차례로 계산합니다. 행 내지 의 최종 거리는 각 변수에 대한 거리의 (가중치) 평균이다. 한 가지 알아야 할 것은 Gower의 거리가 실제로는 미터법 이 아니라는 것 입니다. 그럼에도 불구하고 데이터가 혼합되어있어 Gower의 거리는 대부분 도시에서 유일한 게임입니다. 나는나는'
이 시점에서 원본 데이터 매트릭스 대신 거리 매트릭스에서 작동 할 수있는 모든 클러스터링 방법을 사용할 수 있습니다. (k-means는 후자를 필요로한다.) 가장 인기있는 선택은 medoid (PAM, k-means와 본질적으로 동일하지만 중심이 아니라 가장 중심적인 관찰을 사용함), 다양한 계층 적 군집 접근법 (예 : , 중앙값, 단일 연결 및 전체 연결; 계층 적 클러스터링을 사용하면 최종 클러스터 할당을 얻기 위해 ' 트리를자를 위치'를 결정 하고 훨씬 유연한 클러스터 모양을 허용하는 DBSCAN 을 결정해야합니다 .
다음은 간단한 R
데모입니다 (nb, 실제로는 3 개의 클러스터가 있지만 데이터는 2 개의 클러스터가 적절 해 보입니다).
library(cluster) # we'll use these packages
library(fpc)
# here we're generating 45 data in 3 clusters:
set.seed(3296) # this makes the example exactly reproducible
n = 15
cont = c(rnorm(n, mean=0, sd=1),
rnorm(n, mean=1, sd=1),
rnorm(n, mean=2, sd=1) )
bin = c(rbinom(n, size=1, prob=.2),
rbinom(n, size=1, prob=.5),
rbinom(n, size=1, prob=.8) )
ord = c(rbinom(n, size=5, prob=.2),
rbinom(n, size=5, prob=.5),
rbinom(n, size=5, prob=.8) )
data = data.frame(cont=cont, bin=bin, ord=factor(ord, ordered=TRUE))
# this returns the distance matrix with Gower's distance:
g.dist = daisy(data, metric="gower", type=list(symm=2))
PAM으로 다른 수의 클러스터를 검색하여 시작할 수 있습니다.
# we can start by searching over different numbers of clusters with PAM:
pc = pamk(g.dist, krange=1:5, criterion="asw")
pc[2:3]
# $nc
# [1] 2 # 2 clusters maximize the average silhouette width
#
# $crit
# [1] 0.0000000 0.6227580 0.5593053 0.5011497 0.4294626
pc = pc$pamobject; pc # this is the optimal PAM clustering
# Medoids:
# ID
# [1,] "29" "29"
# [2,] "33" "33"
# Clustering vector:
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# 1 1 1 1 1 2 1 1 1 1 1 2 1 2 1 2 2 1 1 1 2 1 2 1 2 2
# 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
# 1 2 1 2 2 1 2 2 2 2 1 2 1 2 2 2 2 2 2
# Objective function:
# build swap
# 0.1500934 0.1461762
#
# Available components:
# [1] "medoids" "id.med" "clustering" "objective" "isolation"
# [6] "clusinfo" "silinfo" "diss" "call"
이러한 결과는 계층 적 군집 결과와 비교할 수 있습니다.
hc.m = hclust(g.dist, method="median")
hc.s = hclust(g.dist, method="single")
hc.c = hclust(g.dist, method="complete")
windows(height=3.5, width=9)
layout(matrix(1:3, nrow=1))
plot(hc.m)
plot(hc.s)
plot(hc.c)
중앙값 방법은 2 개 (아마도 3 개)의 군집을 나타내며, 단일은 2 개만 지원하지만 완전한 방법은 2, 3 또는 4를 내 눈에 제안 할 수 있습니다.
마지막으로 DBSCAN을 사용해 볼 수 있습니다. 이를 위해서는 eps, '도달 가능 거리'(두 관측치가 서로 얼마나 밀접하게 연결되어야하는지) 및 minPts (서로 연결하기 전에 서로 연결해야하는 최소 지점 수)라는 두 가지 매개 변수를 지정해야합니다. '클러스터'). minPts의 경험 법칙은 차원 수 (이 경우 3 + 1 = 4)보다 하나 이상을 사용하는 것이지만 너무 작은 숫자는 사용하지 않는 것이 좋습니다. 의 기본값 dbscan
은 5입니다. 우리는 그것을 고수 할 것입니다. 도달 거리에 대해 생각하는 한 가지 방법은 거리의 몇 퍼센트가 주어진 값보다 작은지를 보는 것입니다. 우리는 거리의 분포를 조사함으로써 그렇게 할 수 있습니다 :
windows()
layout(matrix(1:2, nrow=1))
plot(density(na.omit(g.dist[upper.tri(g.dist)])), main="kernel density")
plot(ecdf(g.dist[upper.tri(g.dist)]), main="ECDF")
거리 자체는 시각적으로 알아볼 수있는 '가까운'그룹과 '더 멀리있는'그룹으로 묶인 것 같습니다. 값이 .3이면 두 그룹의 거리를 가장 명확하게 구분하는 것 같습니다. 다양한 eps 선택에 대한 출력 감도를 탐색하기 위해 .2 및 .4도 시도해 볼 수 있습니다.
dbc3 = dbscan(g.dist, eps=.3, MinPts=5, method="dist"); dbc3
# dbscan Pts=45 MinPts=5 eps=0.3
# 1 2
# seed 22 23
# total 22 23
dbc2 = dbscan(g.dist, eps=.2, MinPts=5, method="dist"); dbc2
# dbscan Pts=45 MinPts=5 eps=0.2
# 1 2
# border 2 1
# seed 20 22
# total 22 23
dbc4 = dbscan(g.dist, eps=.4, MinPts=5, method="dist"); dbc4
# dbscan Pts=45 MinPts=5 eps=0.4
# 1
# seed 45
# total 45
를 사용 eps=.3
하면 매우 깨끗한 솔루션이 제공되며, 이는 적어도 적어도 다른 방법에서 본 것과 동의합니다.
의미있는 군집 1-ness 가 없으므로 여러 군집에서 '클러스터 1'이라고하는 관측치와 일치하도록주의해야합니다. 대신, 우리는 테이블을 구성 할 수 있으며 한 피팅에서 '클러스터 1'이라는 관측치의 대부분이 다른 클러스터에서는 '클러스터 2'라고 불리는 경우 결과가 여전히 실질적으로 유사하다는 것을 알 수 있습니다. 우리의 경우, 서로 다른 군집은 대부분 매우 안정적이며 매번 같은 군집에 동일한 관측치를 둡니다. 전체 연계 계층 클러스터링 만 다릅니다.
# comparing the clusterings
table(cutree(hc.m, k=2), cutree(hc.s, k=2))
# 1 2
# 1 22 0
# 2 0 23
table(cutree(hc.m, k=2), pc$clustering)
# 1 2
# 1 22 0
# 2 0 23
table(pc$clustering, dbc3$cluster)
# 1 2
# 1 22 0
# 2 0 23
table(cutree(hc.m, k=2), cutree(hc.c, k=2))
# 1 2
# 1 14 8
# 2 7 16
물론 클러스터 분석이 데이터에서 실제 잠재 클러스터를 복구한다고 보장 할 수는 없습니다. 실제 군집 레이블이 없으면 (예 : 로지스틱 회귀 상황에서 사용 가능) 막대한 양의 정보를 사용할 수 없음을 의미합니다. 매우 큰 데이터 세트의 경우에도 클러스터를 완벽하게 복구 할 수있을만큼 충분히 분리되지 않을 수 있습니다. 우리의 경우, 진정한 클러스터 멤버쉽을 알고 있기 때문에 출력과 비교하여 얼마나 잘했는지 확인할 수 있습니다. 위에서 언급했듯이 실제로 3 개의 잠재 클러스터가 있지만 데이터는 대신 2 개의 클러스터로 나타납니다.
pc$clustering[1:15] # these were actually cluster 1 in the data generating process
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 1 1 1 1 1 2 1 1 1 1 1 2 1 2 1
pc$clustering[16:30] # these were actually cluster 2 in the data generating process
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# 2 2 1 1 1 2 1 2 1 2 2 1 2 1 2
pc$clustering[31:45] # these were actually cluster 3 in the data generating process
# 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
# 2 1 2 2 2 2 1 2 1 2 2 2 2 2 2