Bildiğiniz üzere, K means, bir kümeleme yöntemidir. Yani algoritma, istatistiksel olarak benzer nitelikteki verileri iteratif yöntemle gruplamaya çalışır. Algoritmanın birinci baş harfi olan K de küme sayısını belirtir. Bizim belirttiğimiz K merkezlerine göre yakınlık derecesine göre değerlendirilerek hangi verinin hangi kümede olacağına karar verir.
Temel Kuralımız:
Gruplar arası uzaklık maksimum, grup içi uzaklığı minimum
Küme Sayısının Belirlenmesi:
Şimdi biraz absürt düşünelim 😊 örneklem büyüklüğüm 25 olsun k (küme) sayısını 25 belirleyelim. Bu şekilde grupiçi uzaklığımda sıfır olur (Eee bu super fikir) ama burada biz gerçekten bunu mu bekliyoruz. Her bir örneklemi maksimum detaydaki farklılığına göre ayrıştırmak mı yoksa küçük detayları gözardı edip karmaşıklığı azaltıp gruplaştırmak mı istiyoruz. Bence asıl soru da budur… Sonuç olarak yaptığımız çalışmanın gerçek anlamda yorumlanabilirliliğini artırabilmek için k sayısının doğru belirlememiz önemlidir. Şimdi isterseniz optimal k sayısını nasıl belirliyoruz ona bakalım.
25 sample bir örnek veri seti oluşturdum. Müşteriler ve onların kullandığı Data, Voice, SMSdeğerleri olsun. Önce verimizi R’a okutalım ve descriptive analizini yapalım.
customer <- read.csv(“customer.csv”, header = TRUE, sep=”;”, row.names=1)
df <- customer
summary(df)
df <- scale(df)
as_tibble(df)
rownames(df)
library(funModeling)
profiling_num(customer)

distance <- get_dist(df)
fviz_dist(distance, gradient = list(low = “#00AFBB”, mid = “white”, high = “#FC4E07”))

k2 <- kmeans(df, centers = 2, nstart = 25)
fviz_cluster(k2, data = df)

k2
k3 <- kmeans(df , centers = 3, nstart = 25)
k4 <- kmeans(df , centers = 4, nstart = 25)
k5 <- kmeans(df , centers = 5, nstart = 25)
p1 <- fviz_cluster(k2, geom = “point”, data = df) + ggtitle(“k=2”)
p2 <- fviz_cluster(k3, geom = “point”, data = df) + ggtitle(“k=3”)
p3 <- fviz_cluster(k4, geom = “point”, data = df) + ggtitle(“k=4”)
p4 <- fviz_cluster(k5, geom = “point”, data = df) + ggtitle(“k=5”)
library(gridExtra)
grid.arrange(p1, p2, p3, p4, nrow = 2)

Elbow Metodu
Bu method en çok tercih edilen bize büyük resmi gösteren bir yöntemdir. WCSS (Within Cluster Sum of Square) her bir noktanın küme merkezine olan uzaklığının karesinin toplamını alınarak hesaplanır. Elbow Metodu, WCSS deki değişim miktarının azaldığı nokta yani dirsek noktası optimum noktadır der.
Eminim aklımıza şu soru geliyordur. Aşağıdaki grafikte de görüldüğü üzere cluster sayım artıkça WCSS azalıyor peki, Optimum cluster 5 seçtik ama ben 6 cluster bölmek istedim. Çok büyük bir ihtimalle, bir cluster’a benzer alt bir cluster oluşturdunuz. Yani veri setinize göre cluster:1-2-3-4-5 olması gerekirken siz cluster_1_1 gibi cluster_1 altında türev bir cluster oluşturdunuz. Örnek vermek gerekirse değişkenleri yordayıp, ülkeleri cluster ederken (Almanya, Türkiye, Fransa vs.) biz yine Türkiye grubunun altında belki Marmara bölgesi diye bir alt cluster oluşturduk. WCSS’de de anlamlı bir değişiklik olmadı. O sebeple de optimum küme sayısı önemlidir ki yaptığınız çalışmayı doğru yorumlayabilelim.
set.seed(123)
fviz_nbclust(df, kmeans, method = “wss”)

Average Silhouette Indeks
Rousseeuw (1987), her bir birimin kendi kümesine uygunluğunu tanımlayacak bir Silhouette indeksi önermiştir. a(i) ; i. birimin kendi kümesindeki tüm noktalara olan ortalama uzaklıklarını (benzerliğini) ve b(i); i. birimin diğer kümelerdeki tüm noktalara olan ortalama uzaklıkların minimumunu göstersin. Buradan i. birim için Silhouette indeksi;
Sil(i) = (b(i) – a(i)) / max (a(i),b(i))
olarak tanımlanır. Eğer sil(i) değeri 1’e yaklaşırsa i. birimin atandığı kümeye daha uygun olduğu, sil (i) değeri 0’a yaklaşırsa veya negatif olursa i. birimin atandığı kümeye uygun olmadığı sonucuna varılır. Negatif değerler yalnızca bir birim en uygun kümesine atanamadığında ortaya çıkar.
Olayı biraz daha basitleştirirsek;
K=2 olsun. cluster_1 içindeki bir noktanın a(i): Küme içindeki her bir noktaya uzaklığının ortalaması. b(i) cluster_2 her bir noktalara olan ort. uzaklığıdır. Eğer cluster_3 olsaydı aralarında karşılaştırıp min. seçecektik.
Sil(i) = (b(i) – a(i)) / max (a(i),b(i)) formulünde yerine koyulur, Çıkan sonuç, o noktanın silület skorudur. Bu değer + 1 ne kadar yakın ise o kadar doğru gruplamışız demektir. Ama eksi çıkıyor ise demekki o nokta yanlış clusterda yer almıştır yorumunu yapacağız.
fviz_nbclust(df, kmeans, method = “silhouette”)

GAP istatistiği
Kümelerin, gerçekleşen değerlerinin karelerinin toplamlarının, beklenen değerlerine göre log() değerce farkını karşılaştırıyor. Bunun içinde ikinci bir bootstrapping yöntemiyle örneklem oluşturuluyor. Bu iki değer arasındaki gap büyüklüğü, random uniform dağılımdan o kadar uzakta olduğu ve bizim için de bir o kadar anlamlı olduğunu gösteriyor.
set.seed(123)
gap_stat <- clusGap(df, FUN = kmeans, nstart = 25, K.max = 5, B = 25)
print(gap_stat, method = “firstmax”)

K=5 seçtiğimiz de Özet Gösterim:
set.seed(123)
final <- kmeans(df, 5, nstart = 25)
print(final)
customer %>%
mutate(Cluster = final$cluster) %>%
group_by(Cluster) %>%
summarise_all(“mean”)

Yukarıdaki özet tabloda k=5 seçildiğinde değişkenlerin cluster’ın merkez değerleri gösterilmiştir. Her ne kadar da gerçek hayatta böyle olmasa da sensitivity açısında önce Voice sonra da SMS değişkeninden dolayı müşteriler 5 farklı clusterda olması gerektiği görülmüştür.
Bu ve buna benzer birçok method var önemli olan çalışma mantıklarını bilip, sizin için en anlamlı olanı seçip nedenleriyle açıklayabilmektir.
Herkesin çalışmasında kolaylıklar dilerim 😉
Gurkan.