Clustering - K-Means — تعلم الآلة
التجميع بـ K-Means
في التعلم بدون إشراف لا توجد إجابات. نريد أن يكتشف النموذج مجموعات طبيعية في البيانات: شرائح العملاء، أنواع المقالات، أنماط الاستخدام.
الخوارزمية
1. اختر K مراكز عشوائية.
2. التعيين: كل نقطة تنضم لأقرب مركز.
3. التحديث: كل مركز ينتقل إلى متوسط نقاط مجموعته.
4. كرر 2 و 3 حتى تتوقف المراكز عن الحركة.
import numpy as np
rng = np.random.default_rng(0)
X = np.vstack([rng.normal([0, 0], 0.5, (20, 2)), rng.normal([4, 4], 0.5, (20, 2))])
centers = X[[0, 25]].copy() # بداية: نقطتان من البيانات
for step in range(5):
dists = np.linalg.norm(X[:, None, :] - centers[None, :, :], axis=2)
labels = dists.argmin(axis=1) # التعيين
centers = np.array([X[labels == k].mean(axis=0) for k in range(2)]) # التحديث
print(step, centers.round(2).tolist())هذا هو K-Means كاملاً في عشرة أسطر. KMeans في scikit-learn يضيف بداية ذكية (k-means++) وتكرارات متعددة من بدايات مختلفة (n_init) ويأخذ الأفضل.
اختيار K
لا توجد إجابة "صحيحة"، لكن هناك أدوات:
- طريقة الكوع: ارسم inertia (مجموع مربعات المسافات للمراكز) مقابل K. تنخفض دائماً، لكن ابحث عن النقطة التي يتوقف بعدها الانخفاض الكبير.
- Silhouette: لكل نقطة، كم هي قريبة من مجموعتها مقارنة بالمجموعة التالية (من −1 إلى 1، أعلى أفضل). أوضح من الكوع غالباً.
- المعنى العملي: 4 شرائح عملاء يستطيع فريق التسويق التعامل معها قد تكون أفضل من 9 "أمثل رياضياً".
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score
X, _ = make_blobs(n_samples=300, centers=4, random_state=3)
for k in range(2, 7):
labels = KMeans(n_clusters=k, n_init=10, random_state=0).fit_predict(X)
print(k, round(silhouette_score(X, labels), 3))تحذيرات
- قيّس الميزات أولاً: المسافة تعتمد على المقاييس.
- K-Means يفترض مجموعات كروية ومتقاربة الحجم. مع أشكال متعرجة أو كثافات مختلفة يفشل — جرّب DBSCAN (يكتشف عدد المجموعات بنفسه ويحدد النقاط الشاذة).
- أرقام المجموعات (0، 1، 2) بلا معنى بحد ذاتها؛ افهم كل مجموعة بحساب متوسط ميزاتها.
تمرين
في المثال الكامل استبدل الرسم بحساب Silhouette لقيم K من 2 إلى 8. هل يتفق مع الكوع؟ ثم اطبع متوسط الميزات لكل مجموعة وأعطها اسماً وصفياً.
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np
# إنشاء بيانات
np.random.seed(42)
X = np.vstack([
np.random.randn(50, 2) + [0, 0],
np.random.randn(50, 2) + [5, 5],
np.random.randn(50, 2) + [10, 0]
])
# Scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# ===== Elbow Method =====
inertias = []
K_range = range(1, 10)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X_scaled)
inertias.append(kmeans.inertia_)
plt.plot(K_range, inertias, 'bo-')
plt.xlabel('K')
plt.ylabel('Inertia')
plt.title('Elbow Method')
plt.show()
# ===== K-Means مع K=3 =====
kmeans = KMeans(n_clusters=3, random_state=42)
labels = kmeans.fit_predict(X_scaled)
# رسم النتائج
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')
centers = scaler.inverse_transform(kmeans.cluster_centers_)
plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='X', s=200)
plt.title('K-Means Clustering')
plt.show()
print(f"عدد النقاط في كل مجموعة:")
for i in range(3):
print(f" Cluster {i}: {(labels == i).sum()}")اختبر فهمك