از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
راهنمای قطعی برای K-Means Clustering با Scikit-Learn
سرفصلهای مطلب
معرفی
K-به معنی خوشه بندی است یکی از پرکاربردترین الگوریتمهای یادگیری ماشینی بدون نظارت است که خوشههایی از دادهها را تشکیل میدهد. روی شباهت بین نمونه های داده
در این راهنما، ابتدا نگاهی به یک مثال ساده می اندازیم تا بفهمیم الگوریتم K-Means چگونه کار می کند قبل از اجرای آن با استفاده از Scikit-Learn. سپس، روش تعیین تعداد خوشه ها (Ks) در K-Means و همچنین معیارهای فاصله، واریانس، و مزایا و معایب K-Means را مورد بحث قرار خواهیم داد.
انگیزه
وضعیت زیر را تصور کنید. یک روز، هنگامی که در اطراف محله قدم می زدید، متوجه شدید که 10 فروشگاه رفاه وجود دارد و شروع به تعجب کردید که کدام فروشگاه ها شبیه به یکدیگر هستند – در مجاورت یکدیگر. در حالی که به دنبال راه هایی برای پاسخ به این سوال هستید، با رویکرد جالبی برخورد کرده اید که فروشگاه ها را به گروه های مبتنی بر تقسیم می کند. روی مختصات آنها روی نقشه.
به عنوان مثال، اگر یک فروشگاه در 5 کیلومتری غرب و 3 کیلومتری شمال قرار داشت – شما آن را اختصاص می دهید (5, 3)
مختصات آن است و آن را در یک نمودار نشان می دهد. بیایید این اولین نقطه را ترسیم کنیم تا آنچه را که اتفاق میافتد تجسم کنیم:
import matplotlib.pyplot as plt
plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)
این فقط اولین نکته است، بنابراین ما می توانیم ایده ای در مورد روش نمایندگی یک فروشگاه داشته باشیم. فرض کنید ما در حال حاضر 10 مختصات برای 10 فروشگاه جمع آوری شده داریم. پس از سازماندهی آنها در یک numpy
آرایه، ما همچنین می توانیم مکان های آنها را رسم کنیم:
import numpy as np
points = np.array(((5, 3), (10, 15), (15, 12), (24, 10), (30, 45), (85, 70), (71, 80), (60, 78), (55, 52),(80, 91)))
xs = points(:,0)
ys = points(:,1)
plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)
روش پیاده سازی دستی الگوریتم K-Means
اکنون می توانیم به 10 فروشگاه نگاه کنیم روی یک نمودار، و مشکل اصلی یافتن راهی است که بتوان آنها را به گروه های مختلف تقسیم کرد روی نزدیکی؟ فقط با نگاهی گذرا به نمودار، احتمالا متوجه خواهیم شد دو گروه فروشگاه – یکی نقاط پایین به سمت چپ-پایین و دیگری نقاط بالا-راست است. شاید حتی بتوانیم آن دو نقطه را در وسط به عنوان یک گروه مجزا از هم متمایز کنیم – بنابراین ایجاد سه گروه مختلف.
در این بخش به بررسی آن خواهیم پرداخت process خوشه بندی دستی نقاط – تقسیم آنها به تعداد معین گروه. به این ترتیب، ما اساساً تمام مراحل را با دقت مرور خواهیم کرد الگوریتم خوشه بندی K-Means. در پایان این بخش، درک بصری و عملی از تمام مراحل انجام شده در طول خوشه بندی K-Means به دست خواهید آورد. پس از آن، آن را به Scikit-Learn واگذار می کنیم.
بهترین راه برای تعیین وجود دو یا سه گروه از نقاط چیست؟ یک راه ساده این است که به سادگی یک تعدادی از گروه ها را انتخاب کنید – به عنوان مثال، دو – و سپس سعی کنید نقاط را بر اساس گروه بندی کنید روی آن انتخاب
بیایید بگوییم که ما تصمیم گرفته ایم وجود داشته باشد دو گروه از فروشگاه های ما (نقاط). حال باید راهی پیدا کنیم تا بفهمیم کدام نقاط به کدام گروه تعلق دارند. این را می توان با انتخاب یک نقطه برای نشان دادن انجام داد گروه 1 و یکی برای نمایندگی گروه 2. این نقاط به عنوان مرجع در هنگام اندازه گیری فاصله از تمام نقاط دیگر به هر گروه استفاده می شود.
به این ترتیب، نکته را بگویید (5, 3)
به گروه 1 تعلق می گیرد و امتیاز می گیرد (79, 60)
به گروه 2. هنگام تلاش برای اختصاص یک نقطه جدید (6, 3)
به گروه ها، باید فاصله آن را تا آن دو نقطه اندازه گیری کنیم. در مورد نقطه (6, 3)
است نزدیک تر به (5, 3)
، بنابراین متعلق به گروهی است که توسط آن نقطه نشان داده شده است – گروه 1. به این ترتیب به راحتی می توانیم تمام نقاط را در گروه های مربوطه گروه بندی کنیم.
در این مثال، علاوه بر تعیین تعداد گروه ها (خوشه ها) – ما همچنین در حال انتخاب برخی از نقاط به عنوان a ارجاع فاصله امتیازات جدید هر گروه
این ایده کلی برای درک شباهت های بین فروشگاه های ما است. بیایید آن را عملی کنیم – ابتدا می توانیم دو نقطه مرجع را انتخاب کنیم تصادفی. نقطه مرجع از گروه 1 خواهد بود (5, 3)
و نقطه مرجع از گروه 2 خواهد بود (10, 15)
. ما می توانیم هر دو نقطه خود را انتخاب کنیم numpy
آرایه توسط (0)
و (1)
ایندکس ها و ذخیره آنها در g1
(گروه 1) و g2
متغیرهای (گروه 2):
g1 = points(0)
g2 = points(1)
پس از انجام این کار، باید فاصله تمام نقاط دیگر تا آن نقاط مرجع را محاسبه کنیم. این یک سوال مهم را ایجاد می کند – چگونه می توان آن فاصله را اندازه گیری کرد. اساساً میتوانیم از هر اندازهگیری فاصله استفاده کنیم، اما برای هدف این راهنما، از Euclidean Distance_ استفاده میکنیم.
دانستن اینکه اندازه گیری فاصله اقلیدسی مبتنی است می تواند مفید باشد روی قضیه فیثاغورث:
$$
c^2 = a^2 + b^2
$$
هنگامی که با نقاط یک هواپیما سازگار است – (a1, b1)
و (a2, b2)
، فرمول قبلی می شود:
$$
c^2 = (a2-a1)^2 + (b2-b1)^2
$$
فاصله مربع خواهد بود root از c
، بنابراین می توانیم فرمول را به صورت زیر بنویسیم:
$$
اقلیدسی_{dist} = \sqrt(2)((a2 – a1)^2 + (b2 – b1) ^2))
$$
توجه داشته باشید: همچنین می توانید فرمول فاصله اقلیدسی را برای نقاط چند بعدی تعمیم دهید. به عنوان مثال، در یک فضای سه بعدی، نقاط دارای سه مختصات هستند – فرمول ما آن را به روش زیر منعکس می کند:
$$
اقلیدسی_{dist} = \sqrt(2)((a2 – a1)^2 + (b2 – b1) ^2 + (c2 – c1) ^2))
$$
بدون توجه به تعداد ابعاد فضایی که در آن مشغول به فعالیت هستیم، از همین اصل پیروی می شود.
تا اینجا ما نقاطی را برای نمایش گروه ها انتخاب کرده ایم و می دانیم که چگونه فاصله ها را محاسبه کنیم. حالا بیایید فاصله ها و گروه ها را با تخصیص هر یک از امتیازهای فروشگاه جمع آوری شده به یک گروه کنار هم قرار دهیم.
برای تجسم بهتر آن، سه لیست را اعلام می کنیم. اولین نفری که امتیازهای گروه اول را ذخیره می کند – points_in_g1
. نفر دوم برای ذخیره امتیاز از گروه 2 – points_in_g2
و آخرین مورد – group
، به برچسب نقاط به عنوان هر دو 1
(به گروه 1 تعلق دارد) یا 2
(متعلق به گروه 2)
points_in_g1 = ()
points_in_g2 = ()
group = ()
اکنون میتوانیم نقاط خود را تکرار کنیم و فاصله اقلیدسی بین آنها و هر یک از مراجع گروه خود را محاسبه کنیم. هر نقطه خواهد بود نزدیک تر به یکی از دو گروه – مبتنی بر روی کدام گروه نزدیکترین است، هر نقطه را به لیست مربوطه اختصاص میدهیم و در عین حال اضافه میکنیم 1
یا 2
به group
لیست:
for p in points:
x1, y1 = p(0), p(1)
euclidean_distance_g1 = np.sqrt((g1(0) - x1)**2 + (g1(1) - y1)**2)
euclidean_distance_g2 = np.sqrt((g2(0) - x1)**2 + (g2(1) - y1)**2)
if euclidean_distance_g1 < euclidean_distance_g2:
points_in_g1.append(p)
group.append('1')
else:
points_in_g2.append(p)
group.append('2')
بیایید به نتایج این تکرار نگاه کنیم تا ببینیم چه اتفاقی افتاده است:
print(f'points_in_g1:{points_in_g1}\n \
\npoints_in_g2:{points_in_g2}\n \
\ngroup:{group}')
که منجر به:
points_in_g1:(array((5, 3)))
points_in_g2:(array((10, 15)), array((15, 12)),
array((24, 10)), array((30, 45)),
array((85, 70)), array((71, 80)),
array((60, 78)), array((55, 52)),
array((80, 91)))
group:(1, 2, 2, 2, 2, 2, 2, 2, 2, 2)
همچنین میتوانیم نتیجه خوشهبندی را با رنگهای مختلف ترسیم کنیم روی گروه های اختصاص داده شده با استفاده از Seaborn’s scatterplot()
با group
به عنوان یک hue
بحث و جدل:
import seaborn as sns
sns.scatterplot(x=points(:, 0), y=points(:, 1), hue=group)
به وضوح قابل مشاهده است که تنها نقطه اول ما به گروه 1 اختصاص داده شده است، و تمام نقاط دیگر به گروه 2 اختصاص داده شده است. این نتیجه با آنچه در ابتدا تصور می کردیم متفاوت است. با توجه به تفاوت بین نتایج و انتظارات اولیه ما – آیا راهی وجود دارد که بتوانیم آن را تغییر دهیم؟ به نظر می رسد وجود دارد!
یک رویکرد تکرار process و نقاط مختلف را به عنوان مرجع گروه ها انتخاب کنید. این نتایج ما را تغییر خواهد داد، امیدواریم که بیشتر مطابق با آنچه در ابتدا تصور می کردیم، باشد. این بار دوم، ما میتوانیم آنها را نه بهطور تصادفی مانند گذشته، بلکه با گرفتن یک انتخاب کنیم منظور داشتن از تمام نقاط از قبل گروه بندی شده ما. به این ترتیب، آن نقاط جدید می توانند در وسط گروه های مربوطه قرار گیرند.
به عنوان مثال، اگر گروه دوم فقط امتیاز داشت (10, 15)
، (30, 45)
. جدید مرکزی نقطه خواهد بود (10 + 30)/2
و (15+45)/2
– که برابر است با (20, 30)
.
از آنجایی که ما نتایج خود را در لیست ها قرار داده ایم، می توانیم ابتدا آنها را به تبدیل کنیم numpy
آرایه ها، xs، ys آنها را انتخاب کرده و سپس آن را بدست آورید منظور داشتن:
g1_center = (np.array(points_in_g1)(:, 0).mean(), np.array(points_in_g1)(:, 1).mean())
g2_center = (np.array(points_in_g2)(:, 0).mean(), np.array(points_in_g2)(:, 1).mean())
g1_center, g2_center
مشاوره: سعی کنید استفاده کنید numpy
و آرایه های NumPy تا حد امکان. آنها برای عملکرد بهتر بهینه شده اند و بسیاری از عملیات جبر خطی را ساده می کنند. هر زمان که سعی می کنید برخی از مسائل جبر خطی را حل کنید، قطعاً باید نگاهی به آن بیندازید numpy
اسنادی برای بررسی اینکه آیا وجود دارد یا خیر numpy
روش طراحی شده برای حل مشکل شما شانس این است که وجود دارد!
برای کمک به تکرار process با نقاط مرکزی جدیدمان، بیایید کد قبلی خود را به یک تابع تبدیل کنیم، آن را اجرا کنیم و ببینیم آیا تغییراتی در روش گروه بندی نقاط وجود دارد یا خیر:
def assigns_points_to_two_groups(g1_center, g2_center):
points_in_g1 = ()
points_in_g2 = ()
group = ()
for p in points:
x1, y1 = p(0), p(1)
euclidean_distance_g1 = np.sqrt((g1_center(0) - x1)**2 + (g1_center(1) - y1)**2)
euclidean_distance_g2 = np.sqrt((g2_center(0) - x1)**2 + (g2_center(1) - y1)**2)
if euclidean_distance_g1 < euclidean_distance_g2:
points_in_g1.append(p)
group.append(1)
else:
points_in_g2.append(p)
group.append(2)
return points_in_g1, points_in_g2, group
توجه داشته باشید: اگر متوجه شدید که یک کد را بارها و بارها تکرار می کنید، باید آن کد را در یک تابع جداگانه بپیچید. سازماندهی کد به توابع بهترین روش در نظر گرفته می شود، به ویژه به این دلیل که تست را تسهیل می کند. آزمایش یک قطعه کد جدا شده از یک کد کامل بدون هیچ عملکردی آسان تر است.
بیایید تابع را فراخوانی کنیم و نتایج آن را در آن ذخیره کنیم points_in_g1
، points_in_g2
، و group
متغیرها:
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group
و همچنین نمودار پراکندگی را با نقاط رنگی ترسیم کنید تا تقسیم گروه ها را تجسم کنید:
sns.scatterplot(x=points(:, 0), y=points(:, 1), hue=group)
به نظر می رسد خوشه بندی نقاط ما است بهتر شدن. اما با این حال، دو نقطه در وسط نمودار وجود دارد که میتوان به هر یک از گروهها در مجاورت هر دو گروه نسبت داد. الگوریتمی که ما تاکنون ایجاد کرده ایم، هر دوی این نقاط را به گروه دوم اختصاص می دهد.
این بدان معنی است که ما احتمالا می توانیم آن را تکرار کنیم process یک بار دیگر با استفاده از ابزارهای Xs و Ys، ایجاد دو نقطه مرکزی جدید (سنتروئیدها) به گروه های ما و تخصیص مجدد آنها بر اساس روی فاصله
بیایید یک تابع برای به روز رسانی سانتروئیدها نیز ایجاد کنیم. تمام process اکنون می توان به چندین تماس آن تابع کاهش داد:
def updates_centroids(points_in_g1, points_in_g2):
g1_center = np.array(points_in_g1)(:, 0).mean(), np.array(points_in_g1)(:, 1).mean()
g2_center = np.array(points_in_g2)(:, 0).mean(), np.array(points_in_g2)(:, 1).mean()
return g1_center, g2_center
g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points(:, 0), y=points(:, 1), hue=group)
توجه داشته باشید که پس از این تکرار سوم، هر یک از نقاط اکنون به خوشه های مختلفی تعلق دارند. به نظر می رسد که نتایج بهتر می شود – بیایید یک بار دیگر این کار را انجام دهیم. در حال حاضر رفتن به تکرار چهارم روش ما:
g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points(:, 0), y=points(:, 1), hue=group)
این چهارمین بار رسیدیم همان نتیجه مانند قبلی بنابراین به نظر می رسد امتیازات ما دیگر گروه را تغییر نمی دهد، نتیجه ما به نوعی ثبات رسیده است – به حالت غیرقابل تغییر رسیده است، یا همگرا شد. علاوه بر این، دقیقاً همان نتیجه ای را داریم که برای 2 گروه متصور بودیم. همچنین میتوانیم ببینیم که آیا این تقسیم بندی منطقی است یا خیر.
بیایید به سرعت کارهایی را که تاکنون انجام دادهایم مرور کنیم. ما 10 فروشگاه خود را از نظر جغرافیایی به دو بخش تقسیم کرده ایم – یکی در مناطق جنوب غربی پایین و بقیه در شمال شرقی. جمعآوری دادههای بیشتر علاوه بر آنچه در حال حاضر داریم – درآمد، تعداد روزانه مشتریان و بسیاری موارد دیگر، میتواند جالب باشد. به این ترتیب میتوانیم تجزیه و تحلیل غنیتری انجام دهیم و احتمالاً نتایج جالبتری تولید کنیم.
مطالعات خوشهبندی مانند این میتواند زمانی انجام شود که یک برند از قبل تاسیس شده بخواهد منطقهای را برای افتتاح یک فروشگاه جدید انتخاب کند. در این مورد، متغیرهای بسیار بیشتری علاوه بر مکان در نظر گرفته شده است.
همه اینها چه ربطی به الگوریتم K-Means دارد؟
در حالی که این مراحل را دنبال می کنید، ممکن است تعجب کرده باشید که آنها چه ارتباطی با الگوریتم K-Means دارند. را process ما تاکنون انجام داده ایم الگوریتم K-Means. به طور خلاصه، تعداد گروهها/خوشهها، نقاط اولیه را بهطور تصادفی انتخاب کردهایم، و مرکزها را در هر تکرار تا زمانی که خوشهها همگرا شوند، بهروزرسانی کردهایم. ما اساساً کل الگوریتم را با دست انجام داده ایم – هر مرحله را با دقت انجام می دهیم.
را ک در K-Means از تعداد خوشه ها که باید قبل از شروع تکرار تنظیم شوند process. در مورد ما K = 2. این ویژگی گاهی اوقات به عنوان دیده می شود منفی با توجه به روشهای خوشهبندی دیگری مانند خوشهبندی سلسله مراتبی، که نیازی به داشتن تعداد ثابتی از خوشهها از قبل نیست.
به دلیل استفاده از وسیله، K-means نیز می شود نسبت به مقادیر پرت و شدید حساس است – آنها تغییرپذیری را افزایش می دهند و انجام نقش خود را برای مرکزهای ما دشوارتر می کنند. بنابراین، از نیاز به اجرا آگاه باشید مقادیر شدید و تجزیه و تحلیل بیرونی قبل از انجام یک خوشه بندی با استفاده از الگوریتم K-Means.
همچنین، توجه داشته باشید که نقاط ما در قسمت های مستقیم تقسیم شده اند، هنگام ایجاد خوشه ها منحنی وجود ندارد. این همچنین می تواند یک نقطه ضعف الگوریتم K-Means باشد.
توجه داشته باشید: هنگامی که به انعطاف پذیری و سازگاری بیشتر با بیضی ها و اشکال دیگر نیاز دارید، سعی کنید از a استفاده کنید تعمیم K-means مدل مخلوط گاوسی. این مدل می تواند با خوشه های تقسیم بندی بیضوی سازگار شود.
K-Means نیز بسیاری دارد مزایای! عملکرد خوبی دارد روی مجموعه داده های بزرگ اگر از انواع الگوریتمهای خوشهبندی سلسله مراتبی استفاده میکنید، رسیدگی به آن دشوار میشود. آن را نیز همگرایی را تضمین می کند، و به راحتی می تواند تعمیم دادن و سازگار شدن. علاوه بر آن، احتمالاً پرکاربردترین الگوریتم خوشهبندی است.
اکنون که تمام مراحل انجام شده در الگوریتم K-Means را مرور کردیم و تمام جوانب مثبت و منفی آن را فهمیدیم، در نهایت می توانیم K-Means را با استفاده از کتابخانه Scikit-Learn پیاده سازی کنیم.
روش پیاده سازی الگوریتم K-Means با استفاده از Scikit-Learn
برای بررسی مجدد نتیجه، بیایید این کار را انجام دهیم process دوباره، اما اکنون با استفاده از 3 خط کد با sklearn
:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2, random_state=42)
kmeans.fit(points)
kmeans.labels_
در اینجا، برچسب ها مانند گروه های قبلی ما هستند. بیایید به سرعت نتیجه را ترسیم کنیم:
sns.scatterplot(x = points(:,0), y = points(:,1), hue=kmeans.labels_)
نمودار به دست آمده همانند تصویر بخش قبل است.
توجه داشته باشید: فقط نگاه کردن به روش اجرای الگوریتم K-Means با استفاده از Scikit-Learn ممکن است به شما این تصور را بدهد که این کار بیهوده است و نیازی نیست که زیاد نگران آن باشید. زمانی که الگوریتم K-Means را به صورت گام به گام بررسی کردیم، فقط 3 خط کد تمام مراحلی را که در بخش قبل در مورد آن صحبت کردیم انجام می دهد. ولی، شیطان در جزئیات است در این مورد! اگر تمام مراحل و محدودیت های الگوریتم را درک نکنید، به احتمال زیاد با موقعیتی مواجه خواهید شد که الگوریتم K-Means نتایجی را به شما می دهد که انتظارش را نداشتید.
با Scikit-Learn، میتوانید K-Means را برای همگرایی سریعتر با تنظیم init='k-means++'
بحث و جدل. به عبارتی گسترده تر، K-Means++ هنوز هم انتخاب می کند ک مرکز خوشه اولیه به صورت تصادفی پس از توزیع یکنواخت. سپس، هر مرکز خوشه بعدی از میان نقاط داده باقیمانده نه با محاسبه اندازه گیری فاصله – بلکه با استفاده از احتمال انتخاب می شود. استفاده از احتمال، الگوریتم را سرعت می بخشد و در هنگام برخورد با مجموعه داده های بسیار بزرگ مفید است.
روش آرنج – انتخاب بهترین تعداد گروه
تا اینجای کار خیلی خوبه! ما 10 فروشگاه را بر اساس خوشه بندی کرده ایم روی فاصله اقلیدسی بین نقاط و مرکز. اما در مورد آن دو نقطه در وسط نمودار که خوشهبندی آنها کمی سختتر است، چطور؟ آیا نمی توانستند یک گروه جداگانه هم تشکیل دهند؟ آیا واقعاً با انتخاب اشتباه کردیم؟ K=2 گروه ها؟ شاید واقعا داشتیم K=3 گروه ها؟ حتی می توانستیم بیش از سه گروه داشته باشیم و از آن آگاه نباشیم.
سوالی که در اینجا مطرح می شود این است روش تعیین تعداد گروه ها (K) در K-Means. برای پاسخ به این سوال، باید بدانیم که آیا خوشه “بهتر” برای مقدار متفاوت K وجود دارد یا خیر.
راه ساده برای یافتن آن، خوشهبندی نقاط با مقادیر مختلف است ک، بنابراین برای K=2، K=3، K=4، و غیره روی:
for number_of_clusters in range(1, 11):
kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
kmeans.fit(points)
اما، نقاط خوشه بندی برای مختلف Ks تنها کافی نخواهد بود برای درک اینکه آیا مقدار ایده آل را برای آن انتخاب کرده ایم یا خیر ک. ما به راهی برای ارزیابی کیفیت خوشه بندی برای هر یک نیاز داریم ک ما انتخاب کرده ایم
محاسبه دستی درون مجموع مربعها (WCSS)
در اینجا مکان ایده آلی برای معرفی میزان نزدیکی نقاط خوشه ای ما به یکدیگر است. اساساً توضیح می دهد که چقدر واریانس ما درون یک خوشه واحد داریم. این اندازه گیری نامیده می شود در مجموع مجذورات خوشه ای، یا WCSS به طور خلاصه هرچه WCSS کوچکتر باشد، نقاط ما به هم نزدیکتر هستند، بنابراین ما یک خوشه خوش فرم تر داریم. فرمول WCSS را می توان برای هر تعداد خوشه استفاده کرد:
$$
WCSS = \sum(Pi_1 – Centroid_1)^2 + \cdots + \sum(Pi_n – Centroid_n)^2
$$
توجه داشته باشید: در این راهنما، ما از فاصله اقلیدسی برای به دست آوردن مرکز، اما سایر معیارهای فاصله مانند منهتن نیز می توانند استفاده شوند.
اکنون میتوانیم فرض کنیم که دو کلاستر داشته باشیم و سعی کنیم WCSS را پیادهسازی کنیم تا بهتر بفهمیم WCSS چیست و چگونه از آن استفاده کنیم. همانطور که فرمول بیان می کند، ما باید مجذور اختلاف بین تمام نقاط خوشه و مرکز را جمع کنیم. بنابراین، اگر اولین امتیاز ما از گروه اول باشد (5, 3)
و آخرین مرکز ما (پس از همگرایی) از گروه اول است (16.8, 17.0)
، WCSS خواهد بود:
$$
WCSS = \sum((5،3) – (16.8، 17.0))^2
$$
$$
WCSS = \sum((5-16.8) + (3-17.0))^2
$$
$$
WCSS = \sum((-11.8) + (-14.0))^2
$$
$$
WCSS = \sum((-25.8))^2
$$
$$
WCSS = 335.24
$$
این مثال نشان می دهد که چگونه WCSS را برای یک نقطه از خوشه محاسبه می کنیم. اما خوشه معمولاً شامل بیش از یک نقطه است و ما باید همه آنها را هنگام محاسبه WCSS در نظر بگیریم. ما این کار را با تعریف تابعی انجام خواهیم داد که خوشه ای از نقاط و مرکزها را دریافت می کند و مجموع مربع ها را برمی گرداند:
def sum_of_squares(cluster, centroid):
squares = ()
for p in cluster:
squares.append((p - centroid)**2)
ss = np.array(squares).sum()
return ss
اکنون می توانیم مجموع مربع های هر خوشه را بدست آوریم:
g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)
و نتایج را جمع کنید تا مجموع را بدست آورید WCSS:
g1 + g2
این نتیجه در:
2964.3999999999996
بنابراین، در مورد ما، چه زمانی ک برابر 2، مجموع WCSS است 2964.39. اکنون میتوانیم Ks را تغییر دهیم و WCSS را برای همه آنها محاسبه کنیم. به این ترتیب، ما میتوانیم بینشی در مورد چه چیزی داشته باشیم ک ما باید انتخاب کنیم که خوشه بندی ما بهترین عملکرد را داشته باشد.
در حال محاسبه WCSS استفاده کردن Scikit-Learn
خوشبختانه، ما نیازی به محاسبه دستی WCSS برای هر یک نداریم ک. پس از انجام خوشه بندی K-Means برای تعداد خوشه های داده شده، می توانیم WCSS آن را با استفاده از inertia_
صفت. اکنون، میتوانیم به K-Means خود برگردیم for
حلقه، از آن برای تغییر تعداد خوشه ها استفاده کنید و مقادیر WCSS مربوطه را فهرست کنید:
wcss = ()
for number_of_clusters in range(1, 11):
kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
kmeans.fit(points)
wcss.append(kmeans.inertia_)
wcss
توجه داشته باشید که مقدار دوم در لیست دقیقاً همان است که قبلاً برای آن محاسبه کرده بودیم K=2:
(18272.9, # For k=1
2964.3999999999996, # For k=2
1198.75, # For k=3
861.75,
570.5,
337.5,
175.83333333333334,
79.5,
17.0,
0.0)
برای تجسم آن نتایج، بیایید خود را رسم کنیم Ks همراه با مقادیر WCSS:
ks = (1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10)
plt.plot(ks, wcss)
یک وقفه وجود دارد روی یک طرح زمانی که x = 2
، یک نقطه پایین در خط، و حتی پایین تر زمانی که x = 3
. توجه داشته باشید که آن را به ما یادآوری می کند شکل آرنج. با ترسیم Ks به همراه WCSS، ما از آن استفاده می کنیم روش آرنج برای انتخاب تعداد Ks. و K انتخاب شده دقیقاً پایین ترین نقطه آرنج است، بنابراین، می شود 3
بجای 2
، در مورد ما:
ks = (1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10)
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')
میتوانیم الگوریتم خوشهای K-Means را دوباره اجرا کنیم تا ببینیم دادههای ما چگونه به نظر میرسند سه خوشه:
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points(:,0), y = points(:,1), hue=kmeans.labels_)
ما قبلاً از دو خوشه راضی بودیم، اما طبق روش آرنج، سه خوشه برای دادههای ما مناسبتر بود. در این صورت به جای دو فروشگاه، سه نوع فروشگاه خواهیم داشت. قبل از استفاده از روش زانویی به خوشه های فروشگاه های جنوب غربی و شمال شرقی فکر می کردیم، اکنون در مرکز نیز فروشگاه هایی داریم. شاید این می تواند مکان خوبی برای افتتاح یک فروشگاه دیگر باشد زیرا رقابت کمتری در آن نزدیکی خواهد داشت.
معیارهای کیفی خوشه ای جایگزین
همچنین معیارهای دیگری وجود دارد که میتوان هنگام ارزیابی کیفیت خوشه استفاده کرد:
- امتیاز سیلوئت – نه تنها فاصله بین نقاط درون خوشه ای بلکه بین خود خوشه ها را نیز تجزیه و تحلیل می کند
- بین خوشه ها مجموع مربع ها (BCSS) – متریک مکمل WCSS
- خطای مجموع مربعات (SSE)
- حداکثر شعاع – بزرگترین فاصله از یک نقطه تا مرکز آن را اندازه گیری می کند
- شعاع متوسط – مجموع بزرگترین فاصله از یک نقطه تا مرکز آن تقسیم بر تعداد خوشه ها.
توصیه می شود آزمایش کنید و با هر یک از آنها آشنا شوید روی مشکل این است که برخی از گزینه ها می توانند کاربردی تر از پرکاربردترین معیارها باشند (نمره WCSS و Silhouette).
در پایان، مانند بسیاری از الگوریتمهای علم داده، میخواهیم واریانس درون هر خوشه را کاهش دهیم و واریانس بین خوشههای مختلف را به حداکثر برسانیم. بنابراین ما خوشه های تعریف شده و قابل تفکیک بیشتری داریم.
استفاده از K-Means روی یک مجموعه داده دیگر
بیایید از آموخته های خود استفاده کنیم روی مجموعه داده دیگری این بار سعی خواهیم کرد گروه هایی از شراب های مشابه را پیدا کنیم.
توجه داشته باشید: می توانید مجموعه داده را دانلود کنید اینجا.
ما با واردات شروع می کنیم pandas
برای خواندن wine-clustering
CSV (مقادیر جدا شده با کاما) فایل به a Dataframe
ساختار:
import pandas as pd
df = pd.read_csv('wine-clustering.csv')
پس از بارگذاری آن، بیایید نگاهی به پنج رکورد اول داده با آن بیاندازیم head()
روش:
df.head()
این نتیجه در:
Alcohol Malic_Acid Ash Ash_Alcanity Magnesium Total_Phenols Flavonoids Nonflavanoid_Phenols Proanthocyanidins Color_Intensity Hue OD280 Proline
0 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
2 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
3 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
4 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735
ما اندازه گیری های زیادی از مواد موجود در شراب ها داریم. در اینجا، ما همچنین نیازی به تبدیل ستون های دسته بندی نخواهیم داشت زیرا همه آنها عددی هستند. حال بیایید نگاهی به آمار توصیفی با describe()
روش:
df.describe().T
جدول توصیف:
count mean std min 25% 50% 75% max
Alcohol 178.0 13.000618 0.811827 11.03 12.3625 13.050 13.6775 14.83
Malic_Acid 178.0 2.336348 1.117146 0.74 1.6025 1.865 3.0825 5.80
Ash 178.0 2.366517 0.274344 1.36 2.2100 2.360 2.5575 3.23
Ash_Alcanity 178.0 19.494944 3.339564 10.60 17.2000 19.500 21.5000 30.00
Magnesium 178.0 99.741573 14.282484 70.00 88.0000 98.000 107.0000 162.00
Total_Phenols 178.0 2.295112 0.625851 0.98 1.7425 2.355 2.8000 3.88
Flavonoids 178.0 2.029270 0.998859 0.34 1.2050 2.135 2.8750 5.08
Nonflavanoid_Phenols 178.0 0.361854 0.124453 0.13 0.2700 0.340 0.4375 0.66
Proanthocyanidins 178.0 1.590899 0.572359 0.41 1.2500 1.555 1.9500 3.58
Color_Intensity 178.0 5.058090 2.318286 1.28 3.2200 4.690 6.2000 13.00
Hue 178.0 0.957449 0.228572 0.48 0.7825 0.965 1.1200 1.71
OD280 178.0 2.611685 0.709990 1.27 1.9375 2.780 3.1700 4.00
Proline 178.0 746.893258 314.907474 278.00 500.500 673.500 985.0000 1680.00
با نگاه کردن به جدول مشخص می شود که مقداری وجود دارد تنوع در داده ها – برای برخی از ستون ها مانند Alcohol
بیشتر وجود دارد، و برای دیگران، مانند Malic_Acid
، کمتر اکنون می توانیم بررسی کنیم که آیا وجود دارد یا خیر null
، یا NaN
مقادیر موجود در مجموعه داده ما:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Alcohol 178 non-null float64
1 Malic_Acid 178 non-null float64
2 Ash 178 non-null float64
3 Ash_Alcanity 178 non-null float64
4 Magnesium 178 non-null int64
5 Total_Phenols 178 non-null float64
6 Flavonoids 178 non-null float64
7 Nonflavanoid_Phenols 178 non-null float64
8 Proanthocyanidins 178 non-null float64
9 Color_Intensity 178 non-null float64
10 Hue 178 non-null float64
11 OD280 178 non-null float64
12 Proline 178 non-null int64
dtypes: float64(11), int64(2)
memory usage: 18.2 KB
با توجه به اینکه مقادیر خالی در مجموعه داده وجود ندارد، نیازی به حذف یا وارد کردن داده نیست. ما می توانیم از Seaborn استفاده کنیم pairplot()
برای مشاهده توزیع داده ها و بررسی اینکه آیا مجموعه داده جفت ستون هایی را تشکیل می دهد که می توانند برای خوشه بندی جالب باشند:
sns.pairplot(df)
با نگاه کردن به نمودار جفت، دو ستون برای اهداف خوشهبندی امیدوارکننده به نظر میرسند – Alcohol
و OD280
(که روشی برای تعیین غلظت پروتئین در شراب ها است). به نظر می رسد که 3 خوشه مجزا وجود دارد روی طرح هایی که دو تا از آنها را با هم ترکیب می کنند.
ستون های دیگری نیز وجود دارند که به نظر می رسد همبستگی دارند. قابل توجه ترین Alcohol
و Total_Phenols
، و Alcohol
و Flavonoids
. آنها روابط خطی بسیار خوبی دارند که می توان آنها را در نمودار جفت مشاهده کرد.
از آنجایی که تمرکز ما خوشهبندی با K-Means است، بیایید مثلاً یک جفت ستون را انتخاب کنیم Alcohol
و OD280
و روش elbow را برای این مجموعه داده آزمایش کنید.
توجه داشته باشید: هنگام استفاده از ستون های بیشتری از مجموعه داده، نیاز به ترسیم نمودار در 3 بعد یا کاهش داده ها به اجزای اصلی (استفاده از PCA) وجود خواهد داشت. این یک رویکرد معتبر و رایج تر است، فقط مطمئن شوید که اجزای اصلی را بر اساس انتخاب کنید روی چقدر آنها توضیح می دهند و در نظر دارند که هنگام کاهش ابعاد داده، مقداری اطلاعات از دست می رود – بنابراین طرح یک تقریب از داده های واقعی، نه اینکه واقعا چگونه است.
بیایید نمودار پراکندگی را با آن دو ستون که محور آن تنظیم شده است رسم کنیم تا نقاطی را که میخواهیم به گروهها تقسیم کنیم، نگاه دقیقتری بیندازیم:
sns.scatterplot(data=df, x='OD280', y='Alcohol')
حالا میتوانیم ستونهایمان را تعریف کنیم و از روش elbow برای تعیین تعداد خوشهها استفاده کنیم. ما همچنین الگوریتم را با شروع خواهیم کرد kmeans++
فقط برای اطمینان از همگرایی سریعتر:
values = df(('OD280', 'Alcohol'))
wcss_wine = ()
for i in range(1, 11):
kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
kmeans.fit(values)
wcss_wine.append(kmeans.inertia_)
ما WCSS را محاسبه کرده ایم، بنابراین می توانیم نتایج را رسم کنیم:
clusters_wine = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')
طبق روش آرنج باید 3 خوشه در اینجا داشته باشیم. برای مرحله آخر، اجازه دهید نقاط خود را به 3 خوشه خوشه بندی کنیم و آن دسته از خوشه های مشخص شده با رنگ ها را رسم کنیم:
kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values('OD280'), y = values('Alcohol'), hue=kmeans_wine.labels_)
ما می توانیم خوشه ها را ببینیم 0
، 1
، و 2
در نمودار مستقر روی تحلیل ما، گروه 0 دارای شراب هایی با محتوای پروتئین بالاتر و الکل کمتر، گروه 1 دارای شراب هایی با محتوای الکل بالاتر و پروتئین کم، و گروه 2 هم پروتئین بالا و هم الکل بالا در شراب های خود دارد.
این مجموعه داده بسیار جالبی است و من شما را تشویق میکنم تا با خوشهبندی دادهها پس از عادیسازی و PCA – همچنین با تفسیر نتایج و یافتن اتصالات جدید، به تجزیه و تحلیل بیشتر بروید.
نتیجه
K-Means خوشهبندی یک الگوریتم یادگیری ماشینی ساده و در عین حال بسیار مؤثر برای خوشهبندی داده است. بر اساس داده ها خوشه بندی می کند روی فاصله اقلیدسی بین نقاط داده الگوریتم خوشه بندی K-Means کاربردهای زیادی برای گروه بندی اسناد متنی، تصاویر، ویدئوها و موارد دیگر دارد.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-04 20:05:05