الگوریتم فازی C-Means در پایتون — راهنمای کاربردی

از اصول «منطق فازی» (Fuzzy Logic)، میتوان برای خوشهبندی دادههای چندبُعدی استفاده کرد. با استفاده از منطق فازی در دادهکاوی، به هر نمونه داده یک «عضویت» (Membership) برای هر «مرکز خوشه» (Cluster Center) تخصیص داده میشود که مقداری بین ۰ الی ۱۰۰ درصد دارد. این روش میتواند نسبت به خوشهبندیهای دارای «آستانه سخت» (Hard-Thresholded) سنتی که در آن هر نمونه یک برچسب مشخص دارد بسیار قدرتمندتر واقع شود. خوشهبندی با الگوریتم فازی C-Means که به آن فازی K-Means نیز گفته میشود، در پایتون با بهرهگیری از تابع skfuzzy.cmeans انجام میشود. خروجی این تابع میتواند برای دستهبندی دادههای جدید، مطابق با خوشههای محاسبه شده (که به آنها پیشبینی نیز گفته میشود)، با بهرهگیری از skfuzzy.cmeans_predict هدفگذاری مجدد شود و در واقع قابل استفاده برای دادههای جدید باشد.
تولید داده و راهاندازی
در این مثال، ابتدا ورودیهای لازم دریافت و سپس، «دادههای آزمون» (Test Data) برای کار تعریف میشوند.
from __future__ import division, print_function import numpy as np import matplotlib.pyplot as plt import skfuzzy as fuzz colors = ['b', 'orange', 'g', 'r', 'c', 'm', 'y', 'k', 'Brown', 'ForestGreen'] # Define three cluster centers centers = [[4, 2], [1, 7], [5, 6]] # Define three cluster sigmas in x and y, respectively sigmas = [[0.8, 0.3], [0.3, 0.5], [1.1, 0.7]] # Generate test data np.random.seed(42) # Set seed for reproducibility xpts = np.zeros(1) ypts = np.zeros(1) labels = np.zeros(1) for i, ((xmu, ymu), (xsigma, ysigma)) in enumerate(zip(centers, sigmas)): xpts = np.hstack((xpts, np.random.standard_normal(200) * xsigma + xmu)) ypts = np.hstack((ypts, np.random.standard_normal(200) * ysigma + ymu)) labels = np.hstack((labels, np.ones(200) * i)) # Visualize the test data fig0, ax0 = plt.subplots() for label in range(3): ax0.plot(xpts[labels == label], ypts[labels == label], '.', color=colors[label]) ax0.set_title('Test data: 200 points x3 clusters.')
الگوریتم فازی C-Means برای خوشهبندی
در بالا، دادههای تست مشاهده میشوند. به طور مشخص، سه ناحیه متمایز از هم وجود دارند. اما، اگر مشخص نباشد که چه تعداد خوشه باید وجود داشته باشد چه اقدامی باید انجام داد؟ اگر دادهها خیلی شفاف خوشهبندی نشوند (مرزهای دستهها مشخص نباشد) چه کار باید کرد؟ در ادامه، خوشهبندی چندین بار با تعداد خوشههای بین ۲ و ۹ تکرار میشود.
# Set up the loop and plot fig1, axes1 = plt.subplots(3, 3, figsize=(8, 8)) alldata = np.vstack((xpts, ypts)) fpcs = [] for ncenters, ax in enumerate(axes1.reshape(-1), 2): cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans( alldata, ncenters, 2, error=0.005, maxiter=1000, init=None) # Store fpc values for later fpcs.append(fpc) # Plot assigned clusters, for each data point in training set cluster_membership = np.argmax(u, axis=0) for j in range(ncenters): ax.plot(xpts[cluster_membership == j], ypts[cluster_membership == j], '.', color=colors[j]) # Mark the center of each fuzzy cluster for pt in cntr: ax.plot(pt[0], pt[1], 'rs') ax.set_title('Centers = {0}; FPC = {1:.2f}'.format(ncenters, fpc)) ax.axis('off') fig1.tight_layout()
ضریب تقسیم فازی (FPC)
«ضریب تقسیم فازی» (Fuzzy Partition Coefficient)، در طیفی بین 0 و ۱ قرار میگیرد که در آن ۱ بهترین است. این سنجه به کاربر میگوید که دادهها به وسیله یک مدل چقدر شفاف توصیف شدهاند. سپس، مجموعه دادهها چندین بار با تعداد خوشههای بین ۲ تا ۹ خوشهبندی میشوند (در اینجا این آگاهی از پیش وجود داشت که تعداد خوشهها سه تا است). سپس، نتایج خوشهبندی نمایش داده میشود و نمودار ضریب تقسیم فازی رسم میشود. هنگامی که مقدار FPC بیشینه شد، دادهها به بهترین شکل توصیف میشوند.
fig2, ax2 = plt.subplots() ax2.plot(np.r_[2:11], fpcs) ax2.set_xlabel("Number of centers") ax2.set_ylabel("Fuzzy partition coefficient")
همانطور که مشهود است، تعداد ایدهآل مرکزها برابر با ۳ است. در این مثال کشف این موضوع خبر جدیدی نبود چون همانطور که پیشتر بیان شد، از قبل این آگاهی وجود داشت که تعداد خوشهها سه تا است. اما در حالت کلی، استفاده از FPC هنگامی که ساختار دادهها شفاف نیست، بسیار مفید محسوب میشود. توجه به این نکته لازم است که کار با دو مرکز خوشه آغاز میشود. خوشهبندی مجموعه داده با تنها یک مرکز خوشه یک راهکار بدیهی است و بر اساس تعریف FPC == 1 را باز میگرداند (در واقع تنها یک خوشه وجود دارد که همه دادهها به آن تعلق دارند).
دستهبندی دادههای جدید
اکنون که میتوان دادهها را خوشهبندی کرد، گام بعدی معمولا برازش نمونه دادههای جدید در مدل موجود است. به این کار پیشبینی گفته میشود و به مدل موجود و دادههای جدید برای دستهبندی نیاز دارد. برای دستهبندی دادههای جدید، نیاز به مدل موجود و دادههای جدید برای انجام دستهبندی است.
ساخت مدل
همانطور که پیشتر بیان شد، بهترین مدل دارای سه خوشه خروجی است. در ادامه، مدل سه خوشهای برای استفاده به منظور انجام خوشهبندی مجددا ساخته میشود، دادههای یونیفرم جدید تولید میشوند و پیشبینی میشود که هر نمونه داده جدید به کدام خوشه تعلق دارد.
# Regenerate fuzzy model with 3 cluster centers - note that center ordering # is random in this clustering algorithm, so the centers may change places cntr, u_orig, _, _, _, _, _ = fuzz.cluster.cmeans( alldata, 3, 2, error=0.005, maxiter=1000) # Show 3-cluster model fig2, ax2 = plt.subplots() ax2.set_title('Trained model') for j in range(3): ax2.plot(alldata[0, u_orig.argmax(axis=0) == j], alldata[1, u_orig.argmax(axis=0) == j], 'o', label='series ' + str(j)) ax2.legend()
پیشبینی
در نهایت، دادههایی که به صورت یکنواخت نمونهبرداری شدهاند تولید میشوند و خوشهبندی آنها با بهرهگیری از cmeans_predict انجام میشود. cmeans_predict در واقع آن را در یک مدل از پیش موجود ترکیب میکند.
# Generate uniformly sampled data spread across the range [0, 10] in x and y newdata = np.random.uniform(0, 1, (1100, 2)) * 10 # Predict new cluster membership with `cmeans_predict` as well as # `cntr` from the 3-cluster model u, u0, d, jm, p, fpc = fuzz.cluster.cmeans_predict( newdata.T, cntr, 2, error=0.005, maxiter=1000) # Plot the classified uniform data. Note for visualization the maximum # membership value has been taken at each point (i.e. these are hardened, # not fuzzy results visualized) but the full fuzzy result is the output # from cmeans_predict. cluster_membership = np.argmax(u, axis=0) # Hardening for visualization fig3, ax3 = plt.subplots() ax3.set_title('Random points classifed according to known centers') for j in range(3): ax3.plot(newdata[cluster_membership == j, 0], newdata[cluster_membership == j, 1], 'o', label='series ' + str(j)) ax3.legend() plt.show()
کد کامل این کار را میتوان از زیر کپی و در فایل با فرمت py. ذخیرهسازی کرد.
""" ======================== Fuzzy c-means clustering ======================== Fuzzy logic principles can be used to cluster multidimensional data, assigning each point a *membership* in each cluster center from 0 to 100 percent. This can be very powerful compared to traditional hard-thresholded clustering where every point is assigned a crisp, exact label. Fuzzy c-means clustering is accomplished via ``skfuzzy.cmeans``, and the output from this function can be repurposed to classify new data according to the calculated clusters (also known as *prediction*) via ``skfuzzy.cmeans_predict`` Data generation and setup ------------------------- In this example we will first undertake necessary imports, then define some test data to work with. """ from __future__ import division, print_function import numpy as np import matplotlib.pyplot as plt import skfuzzy as fuzz colors = ['b', 'orange', 'g', 'r', 'c', 'm', 'y', 'k', 'Brown', 'ForestGreen'] # Define three cluster centers centers = [[4, 2], [1, 7], [5, 6]] # Define three cluster sigmas in x and y, respectively sigmas = [[0.8, 0.3], [0.3, 0.5], [1.1, 0.7]] # Generate test data np.random.seed(42) # Set seed for reproducibility xpts = np.zeros(1) ypts = np.zeros(1) labels = np.zeros(1) for i, ((xmu, ymu), (xsigma, ysigma)) in enumerate(zip(centers, sigmas)): xpts = np.hstack((xpts, np.random.standard_normal(200) * xsigma + xmu)) ypts = np.hstack((ypts, np.random.standard_normal(200) * ysigma + ymu)) labels = np.hstack((labels, np.ones(200) * i)) # Visualize the test data fig0, ax0 = plt.subplots() for label in range(3): ax0.plot(xpts[labels == label], ypts[labels == label], '.', color=colors[label]) ax0.set_title('Test data: 200 points x3 clusters.') """ .. image:: PLOT2RST.current_figure Clustering ---------- Above is our test data. We see three distinct blobs. However, what would happen if we didn't know how many clusters we should expect? Perhaps if the data were not so clearly clustered? Let's try clustering our data several times, with between 2 and 9 clusters. """ # Set up the loop and plot fig1, axes1 = plt.subplots(3, 3, figsize=(8, 8)) alldata = np.vstack((xpts, ypts)) fpcs = [] for ncenters, ax in enumerate(axes1.reshape(-1), 2): cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans( alldata, ncenters, 2, error=0.005, maxiter=1000, init=None) # Store fpc values for later fpcs.append(fpc) # Plot assigned clusters, for each data point in training set cluster_membership = np.argmax(u, axis=0) for j in range(ncenters): ax.plot(xpts[cluster_membership == j], ypts[cluster_membership == j], '.', color=colors[j]) # Mark the center of each fuzzy cluster for pt in cntr: ax.plot(pt[0], pt[1], 'rs') ax.set_title('Centers = {0}; FPC = {1:.2f}'.format(ncenters, fpc)) ax.axis('off') fig1.tight_layout() """ .. image:: PLOT2RST.current_figure The fuzzy partition coefficient (FPC) ------------------------------------- The FPC is defined on the range from 0 to 1, with 1 being best. It is a metric which tells us how cleanly our data is described by a certain model. Next we will cluster our set of data - which we know has three clusters - several times, with between 2 and 9 clusters. We will then show the results of the clustering, and plot the fuzzy partition coefficient. When the FPC is maximized, our data is described best. """ fig2, ax2 = plt.subplots() ax2.plot(np.r_[2:11], fpcs) ax2.set_xlabel("Number of centers") ax2.set_ylabel("Fuzzy partition coefficient") """ .. image:: PLOT2RST.current_figure As we can see, the ideal number of centers is 3. This isn't news for our contrived example, but having the FPC available can be very useful when the structure of your data is unclear. Note that we started with *two* centers, not one; clustering a dataset with only one cluster center is the trivial solution and will by definition return FPC == 1. ==================== Classifying New Data ==================== Now that we can cluster data, the next step is often fitting new points into an existing model. This is known as prediction. It requires both an existing model and new data to be classified. Building the model ------------------ We know our best model has three cluster centers. We'll rebuild a 3-cluster model for use in prediction, generate new uniform data, and predict which cluster to which each new data point belongs. """ # Regenerate fuzzy model with 3 cluster centers - note that center ordering # is random in this clustering algorithm, so the centers may change places cntr, u_orig, _, _, _, _, _ = fuzz.cluster.cmeans( alldata, 3, 2, error=0.005, maxiter=1000) # Show 3-cluster model fig2, ax2 = plt.subplots() ax2.set_title('Trained model') for j in range(3): ax2.plot(alldata[0, u_orig.argmax(axis=0) == j], alldata[1, u_orig.argmax(axis=0) == j], 'o', label='series ' + str(j)) ax2.legend() """ .. image:: PLOT2RST.current_figure Prediction ---------- Finally, we generate uniformly sampled data over this field and classify it via ``cmeans_predict``, incorporating it into the pre-existing model. """ # Generate uniformly sampled data spread across the range [0, 10] in x and y newdata = np.random.uniform(0, 1, (1100, 2)) * 10 # Predict new cluster membership with `cmeans_predict` as well as # `cntr` from the 3-cluster model u, u0, d, jm, p, fpc = fuzz.cluster.cmeans_predict( newdata.T, cntr, 2, error=0.005, maxiter=1000) # Plot the classified uniform data. Note for visualization the maximum # membership value has been taken at each point (i.e. these are hardened, # not fuzzy results visualized) but the full fuzzy result is the output # from cmeans_predict. cluster_membership = np.argmax(u, axis=0) # Hardening for visualization fig3, ax3 = plt.subplots() ax3.set_title('Random points classifed according to known centers') for j in range(3): ax3.plot(newdata[cluster_membership == j, 0], newdata[cluster_membership == j, 1], 'o', label='series ' + str(j)) ax3.legend() plt.show() """ .. image:: PLOT2RST.current_figure """
اگر نوشته بالا برای شما مفید بوده، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای آمار، احتمالات و دادهکاوی
- آموزش طراحی سیستمهای فازی عصبی یا ANFIS با استفاده از الگوریتمهای فرا ابتکاری و تکاملی
- مجموعه آموزشهای سیستمها و منطق فازی
- داده کاوی (Data Mining) — از صفر تا صد
- داده کاوی فازی چیست؟ — به زبان ساده
- یادگیری علم داده (Data Science) با پایتون — از صفر تا صد
^^