KMeans Kümeleme Analizi
Mustafa Germec, PhD
Merhaba sevgili okurlar,
Bu yazımda KMeans Kümeleme Analizi ile ilgili kısa ve öz bilgiler paylaştım. Umarım faydalı bulursunuz. Şimdiden keyifli okumalar dilerim.
KMeans kümeleme analizinde amaç, gözlemleri birbirlerine olan benzerliklerine göre kümelere ayırmaktır, yani kümelerin içerisindeki homojenliği artırmaktır.
Yukarıdaki şekilde bazı gözlemler, birbirlerine olan yakınlıklarına göre çeşitli uzaklık metriklerini kullanılarak kümelere ayrılmıştır. Sınıflandırma problemlerinden farkı, sınıflandırma problemlerinin sınıflara ayrılmasıdır. Burada ise gözlemler birbirlerine olan benzerliklerine göre kümelere ayrılmaktadır. Yani kümeleme işlemlerinde sınıf bilgisi olmadığından gözlem birimleri kendi içerisinde birbirlerine olan benzerliklerine göre gruplara ayrılır.
KMeans yöntemi nasıl çalışır?
Adim 1: Küme sayısı belirlenir (örneğin 5 küme)
Adim 2: Rastgele k adet merkez seçilir (dolayısıyla 5 merkez).
Adim 3: Her gözlem için k merkezlere olan uzaklıklar hesaplanır.
Adim 4: Her gözlem en yakın olan merkeze yani kümeye atanır.
Adim 5: Atama merkezlerinden sonra oluşan kümeler için tekrar merkez hesaplamaları yapılır. Bu adim oldukça kritiktir.
Adim 6: Bu işlem, belirlenen bir iterasyon adedince tekrar edilir küme için hata kareler toplamlarının toplamının (total within-cluster variation) minimum olduğu durumdaki gözlemlerin kümelenme yapısı, nihai kümelenme olarak seçilir.
Küme yapısının belirlenmesi ve rastgele k adet merkez seçilmesi, bu yöntemin dezavantajlarıdır.
Uygulama
Kütüphaneleri import etme
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from yellowbrick.cluster import KElbowVisualizer
import warnings
warnings.filterwarnings("ignore")
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 500)
Veri setini import etme
df = pd.read_csv('/kaggle/input/us-arrests/us_arrests.csv', index_col=0)
Veri setinin sıfırıncı indeksinde indeks bilgisi olduğundan dolayı index_col=0 yapılır.
Veri setini anlama
Veri setini kontrol etmek için aşağıdaki check_dataframe fonksiyonunu kullanabilirsiniz.
def check_dataframe(dataframe, head=5):
print("Dataset Info:".upper())
display(dataframe.head(head))
print("\nShape:", dataframe.shape)
print("\nData Types:\n", dataframe.info())
print("\nMissing Values:\n", dataframe.isnull().sum().sort_values(ascending=False))
print("\nDescriptive Statistics:\n", dataframe.describe([0.05, 0.10, 0.25, 0.50, 0.75, 0.90, 0.95, 0.99]).T)
check_dataframe(df)
Bu veri seti, Amerika Birleşik Devletleri’nin 50 eyaletinde cinayet, saldırı, kentsel nüfus ve tecavüz suçlarının yıllık oranlarını içermektedir. Veri setinde hiçbir eksik değer bulunmamaktadır.
Saldırı, ortalama 170,76 ile en yüksek ortalama değere sahip suçtur. Aynı zamanda standart sapması da yüksektir, bu da eyaletler arasındaki saldırı suçu oranlarının diğer suç oranlarından daha farklı olabileceğini göstermektedir.
Murder suç oranı ortalaması 7,78'dir ve standart sapması 4,36'dır. Rape suçu ortalaması 21,23'tür ve standart sapması 9,37'dir. Bu suç oranları, saldırı suçu kadar yüksek değildir, ancak yine de önemli düzeydedir.
UrbanPop, ortalama 65,54 ile en düşük suç oranına sahiptir. Ancak veri setinde kentsel nüfusun suç oranları üzerindeki etkisini açıklamak için yeterli bilgi yoktur.
Tanımlayıcı istatistiklerdeki değerler, bu verilerin özellikleri hakkında daha fazla bilgi sağlar. Örneğin, cinayet oranı en düşük olan eyalette (Minnesota), en yüksek olan eyalet (Louisiana) arasında değişirken, diğer özelliklerde de farklılıklar görülmektedir. Saldırı oranı en düşük olan eyalette (Maine), en yüksek olan eyalet (Nevada) arasında değişirken, tecavüz oranı en düşük olan eyalette (North Dakota), en yüksek olan eyalet (Alaska) arasında değişir. Ayrıca, şehir nüfusu en az olan eyalette (Vermont), en fazla olan eyalette (California) arasında değişmektedir.
Bu veri setindeki bilgiler, suç oranları üzerine analiz yapmak isteyenler için faydalı olabilir.
Verilerin standartlaştırılması
Uzaklık ve gradient descent temelli yöntemlerin kullanımındaki süreçlerde değişkenlerin standartlaştırılması önemlidir. Dolayısıyla buradaki değişkenlerde standartlaştırılmalıdır. Verileri 0–1 arasındaki değerlere dönüştürmek için MinMaxScaler kullanabilirsiniz.
mms = MinMaxScaler(feature_range=(0, 1))
df = mms.fit_transform(df) # Bu islem sonrasinda numpy arrayi elde edilir.
df[0:5]
Veriler, fit_trasnform() prosesinden çıktıktan sonra numpy arrayine dönüştürülür. Dolayısıyla ilk 5 gözleme bakmak için df[0:5] kullanılır.
Model kurma
kmeans = KMeans(n_clusters=4, random_state=0).fit(df)
Model kurma işlemi tamamlandıktan sonra modelin hiperparametreleri get_params() metodunun kullanarak elde edilir.
print(f'KMeans modelinin hiperparemetreleri: \n{kmeans.get_params()}')
Yukarıdaki parametrelere göre dışarıdan ayarlanması gereken en önemli hiperparametre n_clusters’tir. Küme sayları aşağıdaki kodlama kullanılarak elde edilebilir.
print(f"KMeans modelinin küme sayısı: {kmeans.n_clusters}'tür.")
# KMeans modelinin küme sayısı: 4'tür.
Küme merkezlerini belirleme
Küme merkezlerini belirlemek için aşağıdaki kodlama kullanılır. Nihai olarak belirlenen 4 kümenin merkezleri gelir. Yani standartlaştırılmış değerlerdeki birer gözlem birimidir.
print(f'KMeans modelinin küme merkezleri: \n{kmeans.cluster_centers_}')
Belirlenen kümelerin küme etiketlerini (labels) getirme
Bu işlem aşağıdaki gibi yapılır. Elde edilen sonuca göre 0'dan 3'e kadar 4 küme/labels vardir. 0, ilk kümeyi, 3 ise son kümeyi temsil eder. Dolayısıyla bunlar, veri setindeki her bir gözlemin kmeans modeli tarafından belirlenen kümeleridir.
print(f'Belirlenen kümelerin küme etiketleri: \n{kmeans.labels_}')
Hata değerlerini (SSD, SSE, SSR) hesaplama
Bu işlem için inertia_ metodu kullanılır. inertia_, örneklerin en yakın küme merkezine olan uzaklıklarının karelerinin toplamını ifade eder.
print(f"KMeans modelinin hatası: {round(kmeans.inertia_, 2)}'dir.")
# KMeans modelinin hatası: 3.68'dir.
Optimum küme sayısını belirleme
n_clusters hiperparametresinin ön tanımlı değeri 8'dir. Öyle bir işlem yapılmalı ki farklı k parametre değerlerine göre SSD incelenmeli ve SSD’ye göre karar verilmelidir. Bu işlem aşağıdaki gibidir.
kmeans = KMeans() # boş bir KMeans nesnesi oluşturma
ssd = [] # ssd isimli bos bir liste oluşturma
K = range(1, 30) # 1'den 30'a kadar K değerlerini oluşturma
# Döngü aracılığıyla işlemleri gerçekleştirme
for k in K:
kmeans = KMeans(n_clusters = k).fit(df)
ssd.append(kmeans.inertia_)
# ssd değerlerini görselleştirme
plt.plot(K, ssd)
plt.xlabel('K değerleri')
plt.ylabel('SSD')
plt.title('Elbow Methodu ile SSD değerlerini görselleştirme')
plt.show()
Yukarıdaki grafiğe göre, küme sayısı arttıkça SSD değerleri azalır. Dolayısıyla burada bir karar vermek gerekirse k değeri 5 olarak belirlenebilir. Gözlem birimi kadar küme olduğunda SSD değeri sıfır olur. Çünkü bütün gözlem birimleri bir küme ve her bir gözlem birimi de bir merkez olur. Dolayısıyla SSD=0 olur. Küme sayısı arttıkça hatanın düşmesi beklenir. Bu durumda ne yapılmalıdır? Pratikte gözlem birimlerinin hepsiyle belirli bir hareket tarzı, aksiyonu gerçekleştirilemediğinden dolayı kümelere ayırmak istediğimiz için organik olarak 3, 4, 5, belki 7, 8 gibi küme olması gerekir ki bu gruplara göre hareket edilmesi gerekir. Öte yandan, KMeans ve Hiyerarşik kümeleme gibi yöntemler kullanılırken algoritmanın verdiği referanslara göre (SSD) olan küme sayılarına doğrudan bakılarak işlem yapılmamalıdır. Çalışmanın başında is bilgisi de ne kadar küme yapılacağı hakkında ön fikir olmalıdır. Bu duruda matematiksel temeller için makine öğrenmesi modelleri kullanılır. Örneğin, veri setinde 40 tane değişkenin olduğunu ve bu değişkenleri kullanarak kümeleme yapılması gerektiğini düşünelim. Ancak, kümelemeyi göz yordamıyla yapmak mümkün değildir. O yüzden matematiksel bir metot gerekmektedir. Dolayısıyla kümeleme yöntemlerinden biri olan KMeans yöntemi kullanılabilir. Yukarıdaki sekil, merkez sayısını belirlemede bir sinyal vermektedir. Ancak, bu kesin olarak belirlenemeyebilir. Bu durumda optimum noktayı belirlemek için aşağıdaki yöntem kullanılabilir.
ElbowVisualizer yöntemine göre optimum küme sayısını belirleme
kmeans = KMeans()
elbow = KElbowVisualizer(kmeans, k=(2, 20))
elbow.fit(df)
elbow.show()
Optimum k değerini elde etme
print(f"Optimum k değeri: {elbow.elbow_value_}'dir.")
# Optimum k değeri: 7'dir.
KMeans final modeli
Final kümelerinin oluşturulması
kmeans = KMeans(n_clusters=elbow.elbow_value_).fit(df)
print(f'Küme sayısı: {kmeans.n_clusters}.\n')
print(f'Küme merkezleri: \n{kmeans.cluster_centers_}\n')
print(f'Küme etiketleri: \n{kmeans.labels_}') # 0'dan 5'e kadar küme olusturulur.
Hangi gözlem biriminin hangi kümeye ait olduğunu belirleme
clusters_kmeans = kmeans.labels_
df = pd.read_csv('/kaggle/input/us-arrests/us_arrests.csv', index_col=0)
df['cluster'] = clusters_kmeans + 1 # veri setine yeni değişken ekleme
df.head()
Hangi eyaletin hangi kümeye ait olduğunu belirleme
df = df.reset_index()
df.rename(columns = {'index':'state'}, inplace = True)
for i in df['cluster'].unique():
print(f'\nKüme numarasi {i} olan eyaletler')
print(df['state'][df['cluster'] == i])
KMeans kümelemede segmentler neye göre oluşturulur?
K-Means kümeleme, verilerin özelliklerine göre yapılan ölçümlerle benzer verilerin aynı kümede toplanmasını sağlar. Bununla beraber, değişkenler standardize edilmektedir. Bu sayede verilerin segmentler halinde gruplandırılması ve farklı özelliklere sahip verilerin ayrılması mümkün olur.
df.groupby('cluster').agg(['count', 'mean', 'median'])
Yukarıdaki tablo, bir veri kümesinin K-Means kümeleme algoritması kullanılarak 6 farklı küme (cluster) halinde segmentlere ayrılması sonucunu göstermektedir. Kümeleme işlemi, dört farklı özellik (Murder, Assault, UrbanPop, Rape) üzerinde gerçekleştirilmiştir. Tabloda her küme için özelliklerin sayısı, ortalaması ve medyanı verilmiştir.
“count” sütunu, her bir kümede kaç adet verinin olduğunu göstermektedir.
“mean” sütunu, her bir kümenin o özellik için ortalama değerini vermektedir.
“median” sütunu, her bir kümenin o özellik için ortanca değerini vermektedir.
Örneğin, “cluster 1” için Murder özelliği için ortalama değer 2.68, medyan değeri 2.4 olarak belirtilmiştir. Bu kümede 10 veri bulunmaktadır. Aynı şekilde Assault özelliği için ortalama değer 70.1, medyan değeri 64.5'tir. UrbanPop özelliği için ortalama değer 51.0, medyan değeri 52.5'tir. Rape özelliği için ise ortalama değer 10.91, medyan değeri 11.0 olarak belirtilmiştir. Benzer yorumlar diğer kümeler için de yapılabilir.
Öte yandan, yukarıdaki tablo, verilerin farklı özelliklerine göre kümelere ayrılmasını göstermektedir. Her bir kümenin özelliklerinin ortalaması ve medyanı, bu kümenin diğer kümelere göre nasıl bir farklılık gösterdiğini anlamak için kullanılabilir. Örneğin, “cluster 2” Assault özelliği için ortalama değeri en yüksek kümedir. Benzer şekilde, “cluster 6” Rape özelliği için en yüksek ortalama değere sahip kümedir.
Çalışmanın bundan sonraki aşaması, bir sınıflandırma problemi olarak devam ettirilip bazı özellik çıkarımları gerçekleştirildikten sonra makine öğrenmesi modeli oluşturulup gelecekle ilgili tahminleme yapılabilir.
Bir sonraki yazımda görüşmek üzere…
Sağlıcakla kalın…
WordPress | Kaggle | LinkedIn | GitHub | ResearchGate | Google Akademik