# Import library yang diperlukan
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering, KMeans
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
import scipy.cluster.hierarchy as sch
from sklearn.datasets import make_blobs
# Set style plotting
'seaborn-v0_8-whitegrid')
plt.style.use('figure.figsize'] = (12, 8)
plt.rcParams['Set2')
sns.set_palette(
# Menetapkan random seed untuk reproduksibilitas
42) np.random.seed(
Notebook Clustering: Hierarchical dan K-Means
Pada praktikum ini, kita akan mengeksplorasi dua teknik clustering utama: 1. Hierarchical Clustering (Clustering Hirarki) 2. K-Means Clustering (Clustering Non-Hirarki)
Kemudian kita akan mempelajari bagaimana mengevaluasi hasil clustering menggunakan berbagai metrik.
1. Persiapan Data
Pertama, kita impor library yang diperlukan dan menyiapkan dataset untuk analisis clustering. Kita akan menggunakan dataset Mall Customers yang berisi informasi tentang pelanggan di sebuah mall.
1.1 Load dan Eksplorasi Dataset
Kita akan menggunakan dataset Mall Customers yang berisi informasi tentang pelanggan mall seperti usia, pendapatan, dan skor spending. Dataset ini cocok untuk demonstrasi teknik clustering karena kita ingin menemukan segment pelanggan berdasarkan pola belanja.
Keterangan Dataset:
CustomerID
: ID PelangganGender
: Jenis KelaminAge
: UsiaAnnual Income (k$)
: Pendapatan Tahunan dalam ribuan dolarSpending Score (1-100)
: Skor Belanja (1-100), Skor ini merepresentasikan tingkat loyalitas atau kecenderungan pelanggan dalam berbelanja di mall tersebut. Nilai yang lebih tinggi menunjukkan pelanggan lebih sering dan lebih banyak berbelanja, sedangkan nilai rendah menunjukkan aktivitas belanja yang lebih sedikit.
# Load dataset
= 'https://raw.githubusercontent.com/SteffiPeTaffy/machineLearningAZ/master/Machine%20Learning%20A-Z%20Template%20Folder/Part%204%20-%20Clustering/Section%2025%20-%20Hierarchical%20Clustering/Mall_Customers.csv'
url = pd.read_csv(url)
df
# Tampilkan informasi dataset
print("Informasi Dataset:")
print(f"Jumlah baris: {df.shape[0]}")
print(f"Jumlah kolom: {df.shape[1]}")
print("\nLima baris pertama:")
display(df.head())
# Statistik deskriptif
display(df.describe())
# Cek apakah ada missing value
print("\nMissing values:")
sum()) display(df.isnull().
Informasi Dataset:
Jumlah baris: 200
Jumlah kolom: 5
Lima baris pertama:
CustomerID | Genre | Age | Annual Income (k$) | Spending Score (1-100) | |
---|---|---|---|---|---|
0 | 1 | Male | 19 | 15 | 39 |
1 | 2 | Male | 21 | 15 | 81 |
2 | 3 | Female | 20 | 16 | 6 |
3 | 4 | Female | 23 | 16 | 77 |
4 | 5 | Female | 31 | 17 | 40 |
CustomerID | Age | Annual Income (k$) | Spending Score (1-100) | |
---|---|---|---|---|
count | 200.000000 | 200.000000 | 200.000000 | 200.000000 |
mean | 100.500000 | 38.850000 | 60.560000 | 50.200000 |
std | 57.879185 | 13.969007 | 26.264721 | 25.823522 |
min | 1.000000 | 18.000000 | 15.000000 | 1.000000 |
25% | 50.750000 | 28.750000 | 41.500000 | 34.750000 |
50% | 100.500000 | 36.000000 | 61.500000 | 50.000000 |
75% | 150.250000 | 49.000000 | 78.000000 | 73.000000 |
max | 200.000000 | 70.000000 | 137.000000 | 99.000000 |
Missing values:
CustomerID 0
Genre 0
Age 0
Annual Income (k$) 0
Spending Score (1-100) 0
dtype: int64
1.2 Persiapan Fitur untuk Clustering
Untuk analisis ini, kita akan fokus pada dua fitur: Annual Income (k$)
dan Spending Score (1-100)
. Kita akan melakukan standardisasi fitur untuk memastikan bahwa kedua fitur memiliki bobot yang sama dalam analisis clustering.
# Memilih fitur yang akan digunakan untuk clustering
= df.iloc[:, [3, 4]].values # Annual Income dan Spending Score
X
# Standardisasi fitur
= StandardScaler()
scaler = scaler.fit_transform(X)
X_scaled
# Visualisasi data sebelum clustering
=(10, 8))
plt.figure(figsize0], X[:, 1], s=100, alpha=0.6)
plt.scatter(X[:, 'Pelanggan berdasarkan Annual Income dan Spending Score', fontsize=15)
plt.title('Annual Income (k$)', fontsize=12)
plt.xlabel('Spending Score (1-100)', fontsize=12)
plt.ylabel(True, alpha=0.3)
plt.grid( plt.show()
2. Hierarchical Clustering (Clustering Hirarki)
Hierarchical Clustering membangun hirarki klaster dalam bentuk pohon (dendogram). Ada dua pendekatan utama:
- Agglomerative (Bottom-up): Dimulai dengan setiap titik data sebagai cluster terpisah dan secara bertahap menggabungkan cluster terdekat.
- Divisive (Top-down): Dimulai dengan semua titik data dalam satu cluster dan secara bertahap membagi menjadi cluster yang lebih kecil.
Kita akan menggunakan metode Agglomerative karena lebih umum digunakan. Kita juga akan menggunakan metode Ward untuk menghitung jarak antar cluster, yang meminimalkan varians dalam cluster.
# Membuat dendogram untuk menentukan jumlah optimal cluster
=(12, 8))
plt.figure(figsize= sch.dendrogram(sch.linkage(X_scaled, method='ward'))
dendrogram 'Dendogram', fontsize=15)
plt.title('Pelanggan', fontsize=12)
plt.xlabel('Euclidean Distance', fontsize=12)
plt.ylabel(=6, color='r', linestyle='--')
plt.axhline(y100, 6.5, 'Threshold line untuk menentukan jumlah cluster', color='r')
plt.text(
plt.show()
# Berdasarkan dendogram, kita dapat menentukan jumlah optimal cluster
# Misalnya, jika kita memotong dendogram pada jarak sekitar 6, kita akan mendapatkan 5 cluster
# Implementasi Hierarchical Clustering dengan jumlah cluster yang ditentukan
= 5 # Berdasarkan analisis dendogram
n_clusters = AgglomerativeClustering(n_clusters=n_clusters, affinity='euclidean', linkage='ward')
hc = hc.fit_predict(X_scaled)
y_hc
# Visualisasi hasil Hierarchical Clustering
=(12, 8))
plt.figure(figsizefor i in range(n_clusters):
== i, 0], X[y_hc == i, 1], s=100,
plt.scatter(X[y_hc =f'Cluster {i+1}')
label
'Hierarchical Clustering (Cluster Pelanggan)', fontsize=15)
plt.title('Annual Income (k$)', fontsize=12)
plt.xlabel('Spending Score (1-100)', fontsize=12)
plt.ylabel(
plt.legend()True, alpha=0.3)
plt.grid( plt.show()
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_agglomerative.py:983: FutureWarning: Attribute `affinity` was deprecated in version 1.2 and will be removed in 1.4. Use `metric` instead
warnings.warn(
2.1 Analisis Hasil Hierarchical Clustering
Mari kita analisis hasil hierarchical clustering dengan menghitung statistik untuk setiap cluster dan mendeskripsikan karakteristik masing-masing segmen pelanggan.
# Menambahkan hasil cluster ke dataframe
'Hierarchical_Cluster'] = y_hc
df[
# Menghitung statistik untuk setiap cluster
= df.groupby('Hierarchical_Cluster').agg({
cluster_stats 'Age': ['mean', 'min', 'max', 'std'],
'Annual Income (k$)': ['mean', 'min', 'max', 'std'],
'Spending Score (1-100)': ['mean', 'min', 'max', 'std'],
})
print("Statistik Cluster Hirarki:")
display(cluster_stats)
# Visualisasi distribusi umur, pendapatan, dan spending score di setiap cluster
= plt.subplots(1, 3, figsize=(18, 6))
fig, axes
# Plot distribusi umur
='Hierarchical_Cluster', y='Age', data=df, ax=axes[0])
sns.boxplot(x0].set_title('Distribusi Umur per Cluster')
axes[
# Plot distribusi pendapatan
='Hierarchical_Cluster', y='Annual Income (k$)', data=df, ax=axes[1])
sns.boxplot(x1].set_title('Distribusi Pendapatan per Cluster')
axes[
# Plot distribusi spending score
='Hierarchical_Cluster', y='Spending Score (1-100)', data=df, ax=axes[2])
sns.boxplot(x2].set_title('Distribusi Spending Score per Cluster')
axes[
plt.tight_layout() plt.show()
Statistik Cluster Hirarki:
Age | Annual Income (k$) | Spending Score (1-100) | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
mean | min | max | std | mean | min | max | std | mean | min | max | std | |
Hierarchical_Cluster | ||||||||||||
0 | 41.000000 | 19 | 59 | 11.036596 | 89.406250 | 71 | 137 | 16.612975 | 15.593750 | 1 | 39 | 8.936548 |
1 | 32.692308 | 27 | 40 | 3.728650 | 86.538462 | 69 | 137 | 16.312485 | 82.128205 | 63 | 97 | 9.364489 |
2 | 42.482353 | 18 | 70 | 16.395856 | 55.811765 | 39 | 79 | 9.731508 | 49.129412 | 29 | 65 | 7.281399 |
3 | 25.333333 | 18 | 35 | 5.378971 | 25.095238 | 15 | 38 | 7.133756 | 80.047619 | 61 | 99 | 10.249274 |
4 | 45.217391 | 19 | 67 | 13.228607 | 26.304348 | 15 | 39 | 7.893811 | 20.913043 | 3 | 40 | 13.017167 |
3. K-Means Clustering (Clustering Non-Hirarki)
K-Means adalah algoritma clustering non-hirarki yang populer karena kesederhanaan dan efisiensinya. K-Means bekerja dengan membagi data menjadi K klaster dengan meminimalkan jarak antara titik data dan pusat klaster (centroid).
Langkah-langkah algoritma K-Means: 1. Inisialisasi K centroid secara acak 2. Tetapkan setiap titik data ke centroid terdekat (membentuk cluster) 3. Hitung ulang centroid sebagai rata-rata titik data dalam cluster 4. Ulangi langkah 2-3 hingga centroid tidak berubah signifikan
Tantangan utama dalam K-Means adalah menentukan jumlah K yang optimal. Kita akan menggunakan metode Elbow untuk ini.
# Metode Elbow untuk menentukan jumlah optimal cluster
= [] # Within-Cluster Sum of Squares
wcss = 10
max_clusters
for i in range(1, max_clusters + 1):
= KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=42)
kmeans
kmeans.fit(X_scaled)
wcss.append(kmeans.inertia_)
# Visualisasi metode Elbow
=(10, 6))
plt.figure(figsizerange(1, max_clusters + 1), wcss, marker='o', linestyle='-', color='blue')
plt.plot('Metode Elbow', fontsize=15)
plt.title('Jumlah Cluster', fontsize=12)
plt.xlabel('WCSS (Within-Cluster Sum of Squares)', fontsize=12)
plt.ylabel(=5, color='r', linestyle='--')
plt.axvline(x5.2, wcss[1], 'Elbow point/titik siku', color='r')
plt.text(True, alpha=0.3)
plt.grid( plt.show()
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
# Implementasi K-Means dengan jumlah optimal cluster
= 5 # Berdasarkan metode Elbow
n_clusters = KMeans(n_clusters=n_clusters, init='k-means++', max_iter=300, n_init=10, random_state=42)
kmeans = kmeans.fit_predict(X_scaled)
y_kmeans = scaler.inverse_transform(kmeans.cluster_centers_)
centroids
# Visualisasi hasil K-Means Clustering
=(12, 8))
plt.figure(figsizefor i in range(n_clusters):
== i, 0], X[y_kmeans == i, 1], s=100,
plt.scatter(X[y_kmeans =f'Cluster {i+1}')
label
0], centroids[:, 1], s=300, c='yellow',
plt.scatter(centroids[:, ='*', edgecolors='black', label='Centroids')
marker'K-Means Clustering (Cluster Pelanggan)', fontsize=15)
plt.title('Annual Income (k$)', fontsize=12)
plt.xlabel('Spending Score (1-100)', fontsize=12)
plt.ylabel(
plt.legend()True, alpha=0.3)
plt.grid( plt.show()
c:\Users\derik\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
warnings.warn(
3.1 Analisis Hasil K-Means Clustering
Mari kita analisis hasil K-Means clustering dan bandingkan hasilnya dengan Hierarchical clustering.
# Menambahkan hasil cluster ke dataframe
'KMeans_Cluster'] = y_kmeans
df[
# Menghitung statistik untuk setiap cluster
= df.groupby('KMeans_Cluster').agg({
cluster_stats_kmeans 'Age': ['mean', 'min', 'max', 'std'],
'Annual Income (k$)': ['mean', 'min', 'max', 'std'],
'Spending Score (1-100)': ['mean', 'min', 'max', 'std'],
})
print("Statistik Cluster K-Means:")
display(cluster_stats_kmeans)
# Visualisasi distribusi umur, pendapatan, dan spending score di setiap cluster
= plt.subplots(1, 3, figsize=(18, 6))
fig, axes
# Plot distribusi umur
='KMeans_Cluster', y='Age', data=df, ax=axes[0])
sns.boxplot(x0].set_title('Distribusi Umur per Cluster')
axes[
# Plot distribusi pendapatan
='KMeans_Cluster', y='Annual Income (k$)', data=df, ax=axes[1])
sns.boxplot(x1].set_title('Distribusi Pendapatan per Cluster')
axes[
# Plot distribusi spending score
='KMeans_Cluster', y='Spending Score (1-100)', data=df, ax=axes[2])
sns.boxplot(x2].set_title('Distribusi Spending Score per Cluster')
axes[
plt.tight_layout() plt.show()
Statistik Cluster K-Means:
Age | Annual Income (k$) | Spending Score (1-100) | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
mean | min | max | std | mean | min | max | std | mean | min | max | std | |
KMeans_Cluster | ||||||||||||
0 | 42.716049 | 18 | 70 | 16.447822 | 55.296296 | 39 | 76 | 8.988109 | 49.518519 | 34 | 61 | 6.530909 |
1 | 41.114286 | 19 | 59 | 11.341676 | 88.200000 | 70 | 137 | 16.399067 | 17.114286 | 1 | 39 | 9.952154 |
2 | 45.217391 | 19 | 67 | 13.228607 | 26.304348 | 15 | 39 | 7.893811 | 20.913043 | 3 | 40 | 13.017167 |
3 | 25.272727 | 18 | 35 | 5.257030 | 25.727273 | 15 | 39 | 7.566731 | 79.363636 | 61 | 99 | 10.504174 |
4 | 32.692308 | 27 | 40 | 3.728650 | 86.538462 | 69 | 137 | 16.312485 | 82.128205 | 63 | 97 | 9.364489 |
4. Evaluasi Clustering
Evaluasi hasil clustering adalah tahap penting untuk menilai kualitas cluster yang dihasilkan. Karena clustering adalah pembelajaran tanpa pengawasan (unsupervised learning), kita tidak memiliki label yang benar untuk dievaluasi. Oleh karena itu, kita menggunakan metrik internal yang mengukur seberapa baik data terkelompok.
Beberapa metrik evaluasi umum:
Silhouette Coefficient: Mengukur seberapa mirip objek dengan clusternya sendiri dibandingkan dengan cluster lain. Nilai berkisar antara -1 hingga 1, di mana nilai yang lebih tinggi menunjukkan clustering yang lebih baik.
Calinski-Harabasz Index: Juga dikenal sebagai Variance Ratio Criterion, menghitung rasio dispersi antar cluster dan dalam cluster. Nilai yang lebih tinggi menunjukkan cluster yang lebih terpisah dengan baik.
Davies-Bouldin Index: Mengukur jarak rata-rata antara setiap cluster dan cluster yang paling mirip dengannya. Nilai yang lebih rendah menunjukkan clustering yang lebih baik.
# Fungsi untuk mengevaluasi dan membandingkan hasil clustering
def evaluate_clustering(X, labels, method_name):
= silhouette_score(X, labels)
silhouette = calinski_harabasz_score(X, labels)
calinski = davies_bouldin_score(X, labels)
davies
print(f"Evaluasi untuk {method_name}:")
print(f"Silhouette Score: {silhouette:.4f} (semakin tinggi semakin baik, range [-1, 1])")
print(f"Calinski-Harabasz Index: {calinski:.4f} (semakin tinggi semakin baik)")
print(f"Davies-Bouldin Index: {davies:.4f} (semakin rendah semakin baik)")
print("-" * 50)
return silhouette, calinski, davies
# Evaluasi hasil Hierarchical Clustering
= evaluate_clustering(X_scaled, y_hc, "Hierarchical Clustering")
sil_hc, cal_hc, dav_hc
# Evaluasi hasil K-Means Clustering
= evaluate_clustering(X_scaled, y_kmeans, "K-Means Clustering") sil_km, cal_km, dav_km
Evaluasi untuk Hierarchical Clustering:
Silhouette Score: 0.5538 (semakin tinggi semakin baik, range [-1, 1])
Calinski-Harabasz Index: 244.4103 (semakin tinggi semakin baik)
Davies-Bouldin Index: 0.5779 (semakin rendah semakin baik)
--------------------------------------------------
Evaluasi untuk K-Means Clustering:
Silhouette Score: 0.5547 (semakin tinggi semakin baik, range [-1, 1])
Calinski-Harabasz Index: 248.6493 (semakin tinggi semakin baik)
Davies-Bouldin Index: 0.5722 (semakin rendah semakin baik)
--------------------------------------------------
# Visualisasi perbandingan metrik evaluasi
= ['Silhouette\nScore', 'Calinski-Harabasz\nIndex', 'Davies-Bouldin\nIndex']
metrics = [sil_hc, cal_hc/100, dav_hc] # Scaling untuk visualisasi yang lebih baik
hc_scores = [sil_km, cal_km/100, dav_km]
km_scores
= np.arange(len(metrics))
x = 0.35
width
= plt.subplots(figsize=(12, 6))
fig, ax = ax.bar(x - width/2, hc_scores, width, label='Hierarchical Clustering')
rects1 = ax.bar(x + width/2, km_scores, width, label='K-Means Clustering')
rects2
'Nilai Metrik')
ax.set_ylabel('Perbandingan Metrik Evaluasi')
ax.set_title(
ax.set_xticks(x)
ax.set_xticklabels(metrics)
ax.legend()
# Menambahkan label nilai pada bar
def autolabel(rects):
for rect in rects:
= rect.get_height()
height f'{height:.3f}',
ax.annotate(=(rect.get_x() + rect.get_width()/2, height),
xy=(0, 3),
xytext="offset points",
textcoords='center', va='bottom')
ha
autolabel(rects1)
autolabel(rects2)
# Tambahkan catatan untuk interpretasi
0.5, 0.01,
plt.figtext('Catatan: Untuk Silhouette dan Calinski-Harabasz, nilai lebih tinggi = lebih baik. \nUntuk Davies-Bouldin, nilai lebih rendah = lebih baik.',
='center', fontsize=10, bbox={"facecolor":"orange", "alpha":0.2, "pad":5})
ha
plt.tight_layout() plt.show()
5. Studi Kasus: Segmentasi Pelanggan
Berdasarkan hasil clustering, mari kita interpretasikan segmen pelanggan yang telah kita identifikasi. Segmentasi pelanggan adalah salah satu aplikasi clustering yang paling umum dalam bisnis, memungkinkan strategi pemasaran yang lebih ditargetkan.
# Visualisasi scatter plot dengan ketiga fitur (menggunakan warna untuk umur)
=(14, 10))
plt.figure(figsize
= plt.scatter(X[:, 0], X[:, 1], c=df['Age'], s=100, alpha=0.6, cmap='viridis')
scatter ='Umur')
plt.colorbar(scatter, label
# Menambahkan centroid K-Means
0], centroids[:, 1], s=300, c='red',
plt.scatter(centroids[:, ='*', edgecolors='black', label='Centroids')
marker
# Menambahkan anotasi untuk segmen
for i, centroid in enumerate(centroids):
f'Segmen {i+1}',
plt.annotate(0], centroid[1]),
(centroid[=(10, 10),
xytext='offset points',
textcoords=12,
fontsize=dict(boxstyle="round,pad=0.3", fc="white", ec="black", alpha=0.8))
bbox
'Segmentasi Pelanggan berdasarkan Pendapatan dan Spending Score', fontsize=15)
plt.title('Annual Income (k$)', fontsize=12)
plt.xlabel('Spending Score (1-100)', fontsize=12)
plt.ylabel(
plt.legend()True, alpha=0.3)
plt.grid( plt.show()
# Deskripsi segmen pelanggan
= {
segment_descriptions 0: "Pelanggan dengan pendapatan tinggi dan spending score tinggi (Target Utama)",
1: "Pelanggan dengan pendapatan rendah dan spending score rendah (Pelanggan Hemat)",
2: "Pelanggan dengan pendapatan tinggi tapi spending score rendah (Potensial Tidak Terealisasi)",
3: "Pelanggan dengan pendapatan rendah tapi spending score tinggi (Loyal Tapi Terbatas)",
4: "Pelanggan dengan pendapatan dan spending score rata-rata (Pelanggan Biasa)"
}
# Menambahkan deskripsi segmen ke DataFrame
'Segment_Description'] = df['KMeans_Cluster'].map(segment_descriptions)
df[
# Menampilkan jumlah pelanggan di setiap segmen
= df['KMeans_Cluster'].value_counts().sort_index()
segment_counts print("Jumlah Pelanggan per Segmen:")
for i, count in enumerate(segment_counts):
print(f"Segmen {i} - {segment_descriptions[i]}: {count} pelanggan")
# Visualisasi jumlah pelanggan per segmen
=(12, 6))
plt.figure(figsize= plt.bar(segment_descriptions.values(), segment_counts, color=sns.color_palette("Set2"))
bars
# Menambahkan label jumlah pada setiap bar
for bar in bars:
= bar.get_height()
height + bar.get_width()/2., height + 0.5,
plt.text(bar.get_x() f'{height}',
='center', va='bottom')
ha
'Jumlah Pelanggan per Segmen', fontsize=15)
plt.title('Segmen Pelanggan', fontsize=12)
plt.xlabel('Jumlah Pelanggan', fontsize=12)
plt.ylabel(=45, ha='right')
plt.xticks(rotation
plt.tight_layout() plt.show()
Jumlah Pelanggan per Segmen:
Segmen 0 - Pelanggan dengan pendapatan tinggi dan spending score tinggi (Target Utama): 81 pelanggan
Segmen 1 - Pelanggan dengan pendapatan rendah dan spending score rendah (Pelanggan Hemat): 35 pelanggan
Segmen 2 - Pelanggan dengan pendapatan tinggi tapi spending score rendah (Potensial Tidak Terealisasi): 23 pelanggan
Segmen 3 - Pelanggan dengan pendapatan rendah tapi spending score tinggi (Loyal Tapi Terbatas): 22 pelanggan
Segmen 4 - Pelanggan dengan pendapatan dan spending score rata-rata (Pelanggan Biasa): 39 pelanggan
6. Kesimpulan
Dalam praktikum ini, kita telah mempelajari:
- Hierarchical Clustering:
- Membangun dendogram untuk menentukan jumlah cluster optimal
- Menggunakan metode Ward untuk menghitung jarak antar cluster
- Visualisasi dan interpretasi hasil
- K-Means Clustering:
- Menggunakan metode Elbow untuk menentukan jumlah cluster optimal
- Implementasi dan visualisasi K-Means clustering
- Interpretasi centroid cluster
- Evaluasi Clustering:
- Menggunakan Silhouette Score, Calinski-Harabasz Index, dan Davies-Bouldin Index
- Membandingkan kinerja berbagai metode clustering
- Segmentasi Pelanggan:
- Mengidentifikasi dan mendeskripsikan segmen pelanggan berdasarkan pendapatan dan spending score
- Memberikan implikasi bisnis untuk setiap segmen
Teknik clustering sangat berguna dalam berbagai aplikasi bisnis, terutama untuk segmentasi pelanggan, yang memungkinkan strategi pemasaran yang lebih ditargetkan dan personalisasi produk/layanan yang lebih baik.