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

۱۸۸ بازدید
آخرین به‌روزرسانی: ۲۴ دی ۱۳۹۷
زمان مطالعه: ۷ دقیقه
الگوریتم فازی 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.')

خوشه‌بندی F-Cmeans

الگوریتم فازی 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()

خوشه‌بندی فازی C-Means

ضریب تقسیم فازی (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")

Fuzzy-Cmeans

همانطور که مشهود است، تعداد ایده‌آل مرکزها برابر با ۳ است. در این مثال کشف این موضوع خبر جدیدی نبود چون همانطور که پیش‌تر بیان شد، از قبل این آگاهی وجود داشت که تعداد خوشه‌ها سه تا است. اما در حالت کلی، استفاده از 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()

خوشه‌بندی فازی C-Means

کد کامل این کار را می‌توان از زیر کپی و در فایل با فرمت 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

"""

اگر نوشته بالا برای شما مفید بوده، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۵ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
pythonhosted

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *