K-aracı kümelemesinin karışık türdeki verilerle yapılmaması gerektiği konusunda haklısın. K-aracı esas olarak kümelenmiş gözlemler ile küme centroid arasındaki küme içi kare Euclidean mesafelerini en aza indiren bir bölüm bulmak için basit bir arama algoritması olduğu için, sadece kare Euclid uzaklıklarının anlamlı olacağı verilerle kullanılmalıdır.
Verileriniz karışık tipteki değişkenlerden oluşuyorsa, Gower'ın mesafesini kullanmanız gerekir. CV user @ttnphns, buradaki Gower'ın mesafesine harika bir genel bakış sunar . Temelde, sırayla her değişken için sıralarınız için, o değişkene uygun bir mesafe tipi kullanarak (örneğin, sürekli veri için Euclidean, vb.) Bir mesafe matrisi hesaplarsınız; - sırasının son mesafesi, her değişken için mesafelerin (muhtemelen ağırlıklı) ortalamasıdır. Dikkat edilmesi gereken bir şey, Gower'ın mesafesinin aslında bir ölçü olmadığıdır . Bununla birlikte, karışık verilerle, Gower'ın mesafesi büyük ölçüde şehirdeki tek oyundur. benben'
Bu noktada, orijinal veri matrisine ihtiyaç duymak yerine, bir mesafe matrisinde çalışabilen herhangi bir kümeleme yöntemini kullanabilirsiniz. (K-araçlarının ikincisine ihtiyaç duyduğuna dikkat edin.) En popüler seçimler, medoidlerin (PAM, esasen k-aracıyla aynıdır, ancak merkezî yerine en merkezi gözlemi kullanır) etrafında bölünürler , çeşitli hiyerarşik kümeleme yaklaşımları (örn. , medyan, tek bağlantı ve tam bağlantı; hiyerarşik kümelemeyle son küme atamaları için ' ağacı kesmek ' için karar vermeniz gerekir ) ve çok daha esnek küme şekillerine izin veren DBSCAN .
İşte basit bir R
demo (nb, aslında 3 küme var, ancak veriler çoğunlukla 2 küme gibi görünüyor):
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 ile farklı sayıdaki kümeleri arayarak başlayabiliriz:
# 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"
Bu sonuçlar hiyerarşik kümelemenin sonuçlarıyla karşılaştırılabilir:
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)
Ortanca yöntem 2 (muhtemelen 3) küme önermektedir, tek kişi sadece 2'yi desteklemektedir, ancak tüm yöntem gözüme 2, 3 veya 4 önerebilir.
Sonunda, DBSCAN'ı deneyebiliriz. Bunun için iki parametre belirtilmesi gerekir: eps, 'ulaşılabilirlik mesafesi' (iki gözlemin birbirine ne kadar yakın olması gerekir) ve minPts (onları aramak için istekli olmadan önce birbirlerine bağlanması gereken minimum puan sayısı ) 'küme'. MinPts için bir kural, boyut sayısından bir tanesini kullanmaktır (bizim durumumuzda 3 + 1 = 4), ancak çok küçük bir sayıya sahip olmanız önerilmez. İçin varsayılan değer 5'tir dbscan
; buna sadık kalacağız. Ulaşılabilirlik mesafesini düşünmenin bir yolu, mesafelerin yüzde kaçının belirli bir değerden daha az olduğunu görmektir. Bunu mesafelerin dağılımını inceleyerek yapabiliriz:
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")
Mesafelerin kendileri, görsel olarak ayırt edilebilir 'yakın' ve 'daha uzak' gruplarına ayrılıyor gibi görünmektedir. .3 değeri, iki uzaklık grubunu en net şekilde ayırt ediyor gibi görünmektedir. Çıktının farklı eps seçeneklerine duyarlılığını araştırmak için, .2 ve .4 değerlerini de deneyebiliriz:
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
Kullanmak eps=.3
, (en azından niteliksel olarak) yukarıdaki diğer yöntemlerden ne gördüğümüzü kabul eden çok temiz bir çözüm sunar.
Anlamlı bir küme 1 olmadığından, hangi gözlemlerin farklı kümelenmelerden 'küme 1' olarak adlandırıldığını eşleştirmeye çalışmalıyız. Bunun yerine, tablolar oluşturabiliriz ve bir kümede 'küme 1' adı verilen gözlemlerin birçoğunun diğerinde 'küme 2' olarak adlandırılması durumunda sonuçların hala büyük ölçüde benzer olduğunu görürüz. Bizim durumumuzda, farklı kümelenmeler çoğunlukla çok kararlıdır ve her seferinde aynı kümelere aynı gözlemleri koymaktadır; sadece tam bağlantı hiyerarşik kümeleme farklıdır:
# 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
Tabii ki, herhangi bir küme analizinin verilerinizdeki gizli kümeleri geri kazanabileceği garantisi yoktur. Gerçek kümelenme etiketlerinin olmaması (örneğin bir lojistik regresyon durumunda mevcut olacak), çok fazla bilginin kullanılamayacağı anlamına gelir. Çok büyük veri kümelerinde bile, kümeler mükemmel bir şekilde kurtarılabilir olması için yeterince iyi ayrılmayabilir. Bizim durumumuzda, gerçek kümelenme üyeliğini bildiğimizden, bunun ne kadar iyi olduğunu görmek için bunu çıktıyla karşılaştırabiliriz. Yukarıda belirttiğim gibi, aslında 3 gizli küme var, ancak veriler bunun yerine 2 kümenin görünümünü veriyor:
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