Logo
تعلم الآلة (2026-2027) - التجميع بخوارزمية k-Means

في نافذة الطباعة اختر «حفظ كملف PDF» كوجهة.

تعلم الآلة، الأسبوع 8

التجميع بخوارزمية k-Means

تجميع عملاء لا تحمل بياناتهم أي تسمية: إسناد، ثم تحديث، ثم تكرار. ثم تقسيم 200 عميل إلى شرائح من أجل حملة.

الأهداف

  • التمييز بين التعلم الموجه (supervised learning) والتجميع (clustering)
  • تطبيق k-means يدويا: الإسناد إلى أقرب مركز (centroid)، ثم الانتقال إلى المتوسط، ثم التكرار
  • حساب مجموع المربعات داخل العناقيد (WCSS)، الذي تسميه scikit-learn inertia_
  • تدريب KMeans، وقراءة cluster_centers_ وlabels_، واختيار k بطريقة الكوع (elbow method)
  • تقسيم العملاء إلى شرائح (segments) واختيار الشريحة التي تستهدفها الحملة
  • شرح لماذا قد تعطي بداية مختلفة نتيجة مختلفة، وما يفعله n_init

الأسبوع 8 من الخطة

موقع الدرس من المقرر

  • دفتران (notebooks): Clustering (الكتل، ثم 200 عميل من عملاء مجمع تجاري) وK_Means_Clustering_Practice (777 كلية أمريكية)
  • سيناريو من الواقع: تقسيم العملاء إلى شرائح من بياناتهم لتحديد من تستهدفه حملة لمنتج جديد أو عرض ترويجي (promotion) يزيد مشترياتهم
  • مرحلة المشروع (project milestone) هذا الأسبوع: عروض فرق المشاريع ومناقشاتها (Project Teams Presentations and Discussions)

خطة الساعتين

الجزءما نفعلهالزمن
1التجميع وخوارزمية k-means، ثم خمسة عملاء يدويا40 دقيقة
2الدفتر 1: الكتل (blobs) وطريقة الكوع15 دقيقة
3الدفتر 1: تقسيم العملاء إلى شرائح20 دقيقة
4الدفتر 2: الكليات، ومرحلة المشروع15 دقيقة
5تمارين مع الإجابات، ثم الخلاصة30 دقيقة

الجزء 1

فكرة التجميع

إيجاد مجموعات من الصفوف المتشابهة، دون تسميات نتعلم منها

التعلم الموجه مقابل التجميع

التعلم الموجه (الأسابيع من 3 إلى 7)التجميع (هذا الأسبوع)
بيانات التدريبالخصائص (features) X وتسمية (label) yالخصائص X فقط
ما يتعلمه النموذجكيف يتنبأ بقيمة yمجموعات من الصفوف المتشابهة
مثالتتنبأ KNN بنوع زهرة irisتجد k-means شرائح العملاء
التحقق من النتيجةالمقارنة بقيمة y الحقيقيةلا توجد إجابة صحيحة في العادة

ما خوارزمية k-Means؟

k-means
تقسم العينات إلى k من العناقيد لا تتداخل. ويوصف كل عنقود بمتوسط (mean) عيناته: وهو مركزه.
  • أنت تختار k، أي عدد العناقيد
  • المركز في العادة ليس إحدى نقاط البيانات، لكنه يقع في الفضاء نفسه
  • للعملاء الموصوفين بزوج (الدخل، الإنفاق)، يكون المركز أيضا زوجا (الدخل، الإنفاق)

الخوارزمية

  1. اختر k وضع k من مراكز البداية، مثلا على k من نقاط البيانات تختارها عشوائيا
  2. الإسناد (assign): تنضم كل نقطة إلى أقرب مركز إليها (مربع المسافة الإقليدية)
  3. التحديث (update): ينتقل كل مركز إلى متوسط نقاطه
  4. كرر الإسناد والتحديث حتى لا تغير أي نقطة عنقودها

صيغتان

نقطة (x, y)، ومركز (a, b)، وعنقود فيه n من النقاط

d2 = (x − a)2 + (y − b)2
a = x1 + x2 + ... + xnn, b = y1 + y2 + ... + ynn
  • خطوة الإسناد تستخدم d²: لا حاجة إلى الجذر التربيعي، فهو لا يغير أبدا أي المراكز هو الأقرب
  • خطوة التحديث تستخدم المتوسطين: المركز الجديد هو النقطة المتوسطة في عنقوده
  • المسافة نفسها التي استخدمتها KNN في الأسبوع 5، لكنها تقاس الآن إلى المراكز

يدويا

مثال محلول: خمسة عملاء

خمسة عملاء حقيقيون من الدفتر 1: الدخل السنوي (ألف دولار) ودرجة الإنفاق (من 1 إلى 100)

العميلالدخل (ألف دولار)درجة الإنفاق
#111914
#494042
#624655
#1367388
#19010385

التكرار 1: الإسناد

μ1 = (19, 14)، وμ2 = (46, 55)؛ والفرق = العميل ناقص المركز

العميلd² إلى μ1d² إلى μ2ينضم إلى
#110 + 0 = 0729 + 1681 = 2410μ1
#49441 + 784 = 122536 + 169 = 205μ2
#62729 + 1681 = 24100 + 0 = 0μ2
#1362916 + 5476 = 8392729 + 1089 = 1818μ2
#1907056 + 5041 = 120973249 + 900 = 4149μ2

التكرار 1: التحديث

العنقود 1: #11. العنقود 2: #49، #62، #136، #190

μ1 = (19, 14)
μ2 = (40 + 46 + 73 + 1034, 42 + 55 + 88 + 854) = (65.5, 67.5)

التكرار 2: الإسناد

μ1 = (19, 14)، وμ2 = (65.5, 67.5)

العميلd² إلى μ1d² إلى μ2ينضم إلى
#110 + 0 = 02162.25 + 2862.25 = 5024.5μ1
#49441 + 784 = 1225650.25 + 650.25 = 1300.5μ1
#62729 + 1681 = 2410380.25 + 156.25 = 536.5μ2
#1362916 + 5476 = 839256.25 + 420.25 = 476.5μ2
#1907056 + 5041 = 120971406.25 + 306.25 = 1712.5μ2

التكرار 2: التحديث

العنقود 1: #11، #49. العنقود 2: #62، #136، #190

μ1 = (19 + 402, 14 + 422) = (29.5, 28)
μ2 = (46 + 73 + 1033, 55 + 88 + 853) = (74, 76)

التكرار 3: الإسناد

μ1 = (29.5, 28)، وμ2 = (74, 76)

العميلd² إلى μ1d² إلى μ2ينضم إلى
#11110.25 + 196 = 306.253025 + 3844 = 6869μ1
#49110.25 + 196 = 306.251156 + 1156 = 2312μ1
#62272.25 + 729 = 1001.25784 + 441 = 1225μ1
#1361892.25 + 3600 = 5492.251 + 144 = 145μ2
#1905402.25 + 3249 = 8651.25841 + 81 = 922μ2

التكرار 3: التحديث

العنقود 1: #11، #49، #62. العنقود 2: #136، #190

μ1 = (19 + 40 + 463, 14 + 42 + 553) = (35, 37)
μ2 = (73 + 1032, 88 + 852) = (88, 86.5)

التكرار 4: لا شيء يتحرك

μ1 = (35, 37)، وμ2 = (88, 86.5)

العميلd² إلى μ1d² إلى μ2ينضم إلى
#11256 + 529 = 7854761 + 5256.25 = 10017.25μ1
#4925 + 25 = 502304 + 1980.25 = 4284.25μ1
#62121 + 324 = 4451764 + 992.25 = 2756.25μ1
#1361444 + 2601 = 4045225 + 2.25 = 227.25μ2
#1904624 + 2304 = 6928225 + 2.25 = 227.25μ2

WCSS: ما مدى تماسك العناقيد؟

N من النقاط، وd_i = المسافة من النقطة i إلى مركزها الذي تنتمي إليه

J = d12 + d22 + ... + dN2
التكرارJ بعد الإسنادJ بعد التحديث
161724026
23950.52904.5
32680.751734.5
41734.5اكتمل التقارب

جربها: k-Means خطوة بخطوة

الجزء 2

الدفتر 1: الكتل والكوع

نقاط مولدة أولا، لنعرف الإجابة الصحيحة

افتح الدفترين في Colab

text
https://colab.research.google.com/github/
jeffprosise/Machine-Learning/blob/master/
Clustering.ipynb
الدفتر 1. ادمج الأسطر في عنوان واحد، أو اضغط "Open in Colab" في صفحة الدرس.
text
https://colab.research.google.com/github/
tirthajyoti/Machine-Learning-with-Python/blob/master/
Clustering-Dimensionality-Reduction/
K_Means_Clustering_Practice.ipynb
الدفتر 2، للجزء 4.

أربع كتل: اطلب 3 أو 4 أو 5 عناقيد

make_blobs(n_samples=300, centers=4, cluster_std=0.8, random_state=0)، ثم KMeans(n_clusters=k, random_state=0)

الكتل بعد تجميعها عند k = 3 و4 و5، والمراكز باللون الأحمر؛ والقصور الذاتي 708.8 و369.5 و328.6
  • k = 3 يدمج كتلتين في عنقود واحد من 151 نقطة
  • k = 4 يجد الكتل الأربع: 81 و74 و73 و72 نقطة
  • k = 5 يقطع كتلة حقيقية واحدة إلى 42 و31 نقطة

نقطة جديدة: إلى أي عنقود؟

يتنبأ نموذج k = 4 بعنقود (-0.5, 5) باستخدام kmeans.predict(point)، ثم يطبع المسافة إلى كل مركز

text
[array([1.46570934]), array([4.8470332]),
 array([2.93542029]), array([2.52147763])]
المسافات المطبوعة إلى المراكز 0 و1 و2 و3

اختيار k: طريقة الكوع

القصور الذاتي مقابل عدد العناقيد للكتل، والكوع عند 4
  • نفذ الحلقة لقيم k من 1 إلى 9 وسجل kmeans.inertia_
  • القصور الذاتي (inertia) ينخفض دائما مع زيادة k، فأصغر قيمة ليست الإجابة
  • اختر الكوع: من 3 إلى 4 ينخفض 339.24، ومن 4 إلى 5 ينخفض 40.88 فقط
  • إذن k = 4، وهو عدد الكتل التي جرى توليدها

جربها: شغل حلقة الكوع

الجزء 3

تقسيم العملاء إلى شرائح

سيناريو الأسبوع 8: من يحصل على الحملة؟

السيناريو

تقسيم العملاء إلى شرائح بناء على بياناتهم، لتحديد العملاء الذين تستهدفهم حملة لمنتج جديد أو عرض ترويجي يزيد نشاطهم الشرائي.
سيناريو الأسبوع 8 من الواقع
العمودفي العملاء الـ200
GenderMale أو Female (88 و112)
Ageمن 18 إلى 70
Annual Income (k$)من 15 إلى 137
Spending Score (1-100)من 1 إلى 99: مقدار إنفاق العميل

التحميل والاستكشاف

قيمة customers.shape هي (200, 5)؛ ويعرض info() أنه لا توجد قيم مفقودة

python
url = ("https://raw.githubusercontent.com/"
       "jeffprosise/Machine-Learning/master/"
       "Data/customers.csv")
customers = pd.read_csv(url)

points = customers.iloc[:, 3:5].values
x = points[:, 0]
y = points[:, 1]
plt.scatter(x, y, s=50, alpha=0.7)
يقرأ الدفتر Data/customers.csv، وهو غير موجود في Colab: اقرأه من المستودع.
200 عميل حسب الدخل السنوي ودرجة الإنفاق: مجموعة كثيفة في الوسط وأربع مجموعات في الأركان

الكوع يقول 5

القصور الذاتي مقابل عدد العناقيد للدخل والإنفاق، والكوع عند 5
  • الحلقة نفسها، قيم k من 1 إلى 9، على الدخل والإنفاق
  • من 4 إلى 5 ينخفض 29231.33 (من 73679.79 إلى 44448.46)
  • من 5 إلى 6 ينخفض 5589.50 فقط
  • يقسم الدفتر العملاء إلى خمسة عناقيد

خمس شرائح

KMeans(n_clusters=5, random_state=0)؛ والنقاط الحمراء هي المراكز

العملاء الـ200 في خمس شرائح مع مراكزها؛ والنجمة عند (120, 20) تقع في العنقود 2

أي شريحة تحصل على العرض الترويجي؟

مراكز الشرائح الخمس

العنقودمتوسط الدخل (ألف دولار)متوسط الإنفاقالعملاء
055.3049.5281
186.5482.1339
288.2017.1135
326.3020.9123
425.7379.3622

بناء قائمة الحملة

python
df = customers.copy()
df['Cluster'] = kmeans.predict(points)

cluster = kmeans.predict(np.array([[120, 20]]))[0]
clustered_df = df[df['Cluster'] == cluster]
clustered_df['CustomerID'].values

التقسيم على الخصائص الأربع كلها

الجنس والعمر والدخل والإنفاق؛ مع استبعاد CustomerID

python
from sklearn.preprocessing import LabelEncoder

df = customers.copy()
encoder = LabelEncoder()
df['Gender'] = encoder.fit_transform(df['Gender'])
points = df.iloc[:, 1:5].values

kmeans = KMeans(n_clusters=5, random_state=0)
kmeans.fit(points)
قيمة encoder.classes_ هي ['Female' 'Male']: تصبح Female القيمة 0، وMale القيمة 1
القصور الذاتي مقابل عدد العناقيد مع أربع خصائص: الكوع أقل وضوحا

شرائح الخصائص الأربع

حلقة التقرير في الدفتر، صف لكل عنقود

العنقودمتوسط العمرمتوسط الدخلمتوسط الإنفاق
054.0640.4636.72
132.6986.5482.13
225.2525.8376.92
341.6588.7416.76
433.4058.0648.77

بداية مختلفة، نتيجة مختلفة

يعرض الدفتر المحفوظ أعمارا أخرى للخلية نفسها: 45.22، 32.69، 43.09، 40.67، 25.52

  • البداية عشوائية (init='k-means++')، ويثبتها random_state
  • n_init = عدد البدايات التي يشغلها النموذج؛ ويحتفظ منها بالتشغيل صاحب أصغر قصور ذاتي
  • منذ scikit-learn 1.4 تعني القيمة الافتراضية n_init='auto' بداية واحدة
الإعدادالقصور الذاتيأحجام العناقيد
بداية واحدة (الافتراضي)82657.0550, 39, 24, 34, 53
n_init=1075399.6223, 39, 79, 23, 36

الجزء 4

الدفتر 2: الكليات

هل تستطيع k-means أن تجد الكليات الخاصة والحكومية دون التسميات؟

777 كلية، وعنقودان

  • Private (Yes أو No) و17 عددا: Apps، وF.Undergrad، وOutstate، وExpend، ...
  • 565 كلية خاصة و212 كلية حكومية
  • تجميع الكليات على الأعداد الـ17 وحدها، ثم المقارنة بالعمود Private
  • لا توجد تسميات في التجميع الحقيقي؛ أما هنا فهي تتيح لنا تقييم النتيجة
طلاب المرحلة الجامعية بدوام كامل مقابل رسوم الطلاب من خارج الولاية، ملونة حسب Private

ثلاث خلايا تحتاج إلى إصلاح

python
url = ("https://raw.githubusercontent.com/"
       "tirthajyoti/Machine-Learning-with-Python/"
       "master/Datasets/College_Data")
df = pd.read_csv(url, index_col=0)
df.loc['Cazenovia College', 'Grad.Rate'] = 100
  • الملف College_Data ليس بجوار الدفتر في Colab: اقرأه من Datasets
  • السطر df['Grad.Rate']['Cazenovia College'] = 100 تعيين متسلسل (chained assignment): مع pandas 3 يكتفي بتحذير ويبقى المعدل 118. استخدم .loc
  • تحتاج seaborn الآن إلى x= وy= بالاسم، وإلى height= بدلا من size= في lmplot وFacetGrid

تدريب نموذج بعنقودين

أضفنا random_state=0 ليكون التشغيل قابلا للتكرار

python
kmeans = KMeans(n_clusters=2, verbose=0, tol=1e-3, max_iter=300,
                n_init=20, random_state=0)
kmeans.fit(df.drop('Private', axis=1))
الخاصيةالعنقود 0 (669)العنقود 1 (108)
Apps1813.210363.1
F.Undergrad2188.513061.9
Outstate10395.710719.2
Expend8932.014170.5

مقارنة العناقيد بالتسميات

Cluster = 1 للكلية الخاصة، و0 للحكومية؛ وA = الدقة (accuracy)

python
print(confusion_matrix(df['Cluster'], kmeans.labels_))
# [[138  74]
#  [531  34]]
الصفوف: التسمية الحقيقية (0 حكومية، 1 خاصة). والأعمدة: العنقود.
A = 138 + 34777 = 0.2214

بدل رقمي العنقودين

1 - kmeans.labels_: المصفوفة المحفوظة في الدفتر

العنقود 0العنقود 1
حكومية (0)74138
خاصة (1)34531
A = 74 + 531777 = 0.7786

قبل التمارين

الأخطاء الشائعة

  • اعتبار أرقام العناقيد ذات معنى: اقرأ المراكز
  • اختيار قيمة k صاحبة أصغر قصور ذاتي بدلا من الكوع
  • الثقة ببداية واحدة: استخدم n_init=10 أو أكثر
  • التجميع على عمود معرف (ID)، أو تمرير أعمدة نصية دون ترميزها
  • تقييم العناقيد مقابل التسميات قبل مطابقة الأرقام
  • كتابة df1 = df وأنت تقصد df1 = df.copy(): فبهذه الطريقة تسرب الخلية الأخيرة في الدفتر التسميات

مشروع فريقك

مرحلة المشروع: العروض والمناقشات

  1. المشكلة ومجموعة البيانات: الصفوف، والخصائص، والهدف
  2. كيف نظفت البيانات واستكشفتها، مع رسم أو رسمين
  3. النماذج التي بنيتها منذ الأسبوع 3، ونتائجها على مجموعة الاختبار نفسها
  4. النموذج الذي تحتفظ به، وسبب اختياره
  5. ما لا يزال ناقصا، وخطتك

الجزء 5

التمارين: دورك

نحو 30 دقيقة، والإجابات بعد كل مهمة

نحو 10 دقائق

التمرين 1: بداية مختلفة

  1. العملاء الخمسة أنفسهم، k = 2، وابدأ عند μ1 = #11 = (19, 14) وμ2 = #136 = (73, 88)
  2. نفذ الإسناد والتحديث حتى لا يغير أي عميل عنقوده
  3. اكتب العنقودين النهائيين، والمركزين، وقيمة J
  4. كم خطوة إسناد احتجت إليها، مقارنة بالمثال المحلول؟

الإجابات

التمرين 1: الإجابة

التكرار 1: المسافات إلى μ1 = (19, 14) وμ2 = (73, 88)

العميلd² إلى μ1d² إلى μ2ينضم إلى
#1102916 + 5476 = 8392μ1
#49441 + 784 = 12251089 + 2116 = 3205μ1
#62729 + 1681 = 2410729 + 1089 = 1818μ2
#13683920μ2
#1907056 + 5041 = 12097900 + 9 = 909μ2

نحو 5 دقائق

التمرين 2: أي شريحة؟

عميل جديد: الدخل 100، والإنفاق 50

العنقودالمركز (الدخل، الإنفاق)
0(55.3, 49.5)
1(86.5, 82.1)
2(88.2, 17.1)
3(26.3, 20.9)
4(25.7, 79.4)

نحو 5 دقائق

التمرين 3: تقييم عناقيد الكليات

بعد التبديل؛ A الدقة، وP_1 الضبط (precision) وR_1 الاستدعاء (recall) لصنف الكليات الخاصة

العنقود 0العنقود 1
حكومية (0)74138
خاصة (1)34531
A = 74 + 531777 = 0.7786
P1 = 531531 + 138 = 0.7937, R1 = 531565 = 0.9398

نحو 10 دقائق

التمرين 4: في Colab

  1. الدفتر 1، الشرائح الخمس على الدخل والإنفاق: تنبأ بشريحة [[100, 50], [20, 90]] باستدعاء واحد
  2. أعد تشغيل نموذج الخصائص الأربع مع n_init=10: اطبع inertia_ وnp.bincount(kmeans.labels_)
  3. الدفتر 2 مع random_state=2: اطبع مصفوفة الالتباس (confusion matrix) وaccuracy_score
المهمةالنتيجة
1[1 4]: دخل مرتفع وإنفاق مرتفع، ثم دخل منخفض وإنفاق مرتفع
275399.62، والأحجام [23 39 79 23 36]
3[[74 138] [34 531]]، والدقة 0.7786: تغيرت الأسماء فقط

الخلاصة

  1. يجد التجميع مجموعات في بيانات لا تسميات لها
  2. تكرر k-means الإسناد (أقرب مركز) والتحديث (المتوسط) حتى لا يتغير شيء
  3. يقيس WCSS (inertia_) مدى التماسك، ولا تستطيع أي من الخطوتين رفعه
  4. اختر k عند الكوع، لا عند أصغر قصور ذاتي
  5. تعتمد النتيجة على البداية: استخدم n_init
  6. أرقام العناقيد اعتباطية: اقرأ المراكز واختر أسماء الشرائح

افتح هذا الدرس

Mahmoud Abasالتجميع بخوارزمية k-Means