Доступен ли алгоритм Fuzzy C-Means для Python? - PullRequest
11 голосов
/ 18 июля 2011

У меня есть несколько точек в трехмерном пространстве, и я хотел бы сгруппировать их. Я знаю модуль Python "кластер", но он имеет только K-средства. Знаете ли вы модуль, который имеет FCM (Fuzzy C-Means)?

(Если вы знаете некоторые другие модули Python, которые связаны с кластеризацией, вы можете назвать их в качестве бонуса. Но важный вопрос - это вопрос для FCM-алгоритма в Python.)

Matlab

Кажется, довольно просто использовать FCM в Matlab ( пример ). Разве что-то подобное не доступно для Python?

NumPy, SciPy и Sage

Я не нашел FCM в NumPy , SciPy или Sage . Я скачал документацию и искал ее. Нет результатов

Python-кластер

Похоже, что модуль кластера добавит нечеткие C-Means в следующей версии (см. Roadmap ). Но мне это нужно сейчас

Ответы [ 3 ]

7 голосов
/ 17 мая 2015

Посмотрите на пакет scikit-fuzzy .Он обладает базовыми функциями нечеткой логики, включая кластеризацию нечетких c-средних.

7 голосов
/ 18 июля 2011

PEACH обеспечит некоторую функциональность Fuzzy C-Means: http://code.google.com/p/peach/

Однако, похоже, нет полезной документации, поскольку вики пуста пример использования FCM с PEACH можно найти на его веб-сайте.

1 голос
/ 11 июля 2018

Я сделал это с нуля, используя инициализацию K ++ (с фиксированными начальными числами и 5 центроидами. Не должно быть слишком сложно адаптировать его к желаемому числу центроидов):

# K++ initialization Algorithm:
import random
def initialize(X, K):
    C = [X[0]]
    for k in range(1, K):
        D2 = scipy.array([min([scipy.inner(c-x,c-x) for c in C]) for x in X])
        probs = D2/D2.sum()
        cumprobs = probs.cumsum()
        np.random.seed(20)            # fixxing seeds
        #random.seed(0)               # fixxing seeds
        r = scipy.rand()        
        for j,p in enumerate(cumprobs):
            if r < p:
                i = j
                break
        C.append(X[i])
    return C

a = initialize(data2,5)   # "a" is the centroids initial array... I used 5 centroids

# Now the Fuzzy c means algorithm:
m = 1.5     # Fuzzy parameter (it can be tuned)
r = (2/(m-1))

# Initial centroids:
c1,c2,c3,c4,c5 = a[0],a[1],a[2],a[3],a[4]

# prepare empty lists to add the final centroids:
cc1,cc2,cc3,cc4,cc5 = [],[],[],[],[]

n_iterations = 10000

for j in range(n_iterations):
    u1,u2,u3,u4,u5 = [],[],[],[],[]

    for i in range(len(data2)):
        # Distances (of every point to each centroid):
        a = LA.norm(data2[i]-c1)    
        b = LA.norm(data2[i]-c2)
        c = LA.norm(data2[i]-c3)
        d = LA.norm(data2[i]-c4)
        e = LA.norm(data2[i]-c5)

        # Pertenence matrix vectors:
        U1 = 1/(1 + (a/b)**r + (a/c)**r + (a/d)**r + (a/e)**r) 
        U2 = 1/((b/a)**r + 1 + (b/c)**r + (b/d)**r + (b/e)**r)
        U3 = 1/((c/a)**r + (c/b)**r + 1 + (c/d)**r + (c/e)**r)
        U4 = 1/((d/a)**r + (d/b)**r + (d/c)**r + 1 + (d/e)**r)
        U5 = 1/((e/a)**r + (e/b)**r + (e/c)**r + (e/d)**r + 1)

        # We will get an array of n row points x K centroids, with their degree of pertenence       
        u1.append(U1)
        u2.append(U2)
        u3.append(U3)
        u4.append(U4)
        u5.append(U5)        

    # now we calculate new centers:
    c1 = (np.array(u1)**2).dot(data2) / np.sum(np.array(u1)**2)
    c2 = (np.array(u2)**2).dot(data2) / np.sum(np.array(u2)**2)
    c3 = (np.array(u3)**2).dot(data2) / np.sum(np.array(u3)**2)
    c4 = (np.array(u4)**2).dot(data2) / np.sum(np.array(u4)**2)
    c5 = (np.array(u5)**2).dot(data2) / np.sum(np.array(u5)**2)

    cc1.append(c1)
    cc2.append(c2)
    cc3.append(c3)
    cc4.append(c4)
    cc5.append(c5) 

    if (j>5):  
        change_rate1 = np.sum(3*cc1[j] - cc1[j-1] - cc1[j-2] - cc1[j-3])/3
        change_rate2 = np.sum(3*cc2[j] - cc2[j-1] - cc2[j-2] - cc2[j-3])/3
        change_rate3 = np.sum(3*cc3[j] - cc3[j-1] - cc3[j-2] - cc3[j-3])/3
        change_rate4 = np.sum(3*cc4[j] - cc4[j-1] - cc4[j-2] - cc4[j-3])/3
        change_rate5 = np.sum(3*cc5[j] - cc5[j-1] - cc5[j-2] - cc5[j-3])/3        
        change_rate = np.array([change_rate1,change_rate2,change_rate3,change_rate4,change_rate5])
        changed = np.sum(change_rate>0.0000001)
        if changed == 0:
            break

print(c1)  # to check a centroid coordinates   c1 - c5 ... they are the last centroids calculated, so supposedly they converged.
print(U)  # this is the degree of pertenence to each centroid (so n row points x K centroids columns).

Я знаюэто не очень питонически, но я надеюсь, что это может быть отправной точкой для вашего полного алгоритма нечетких средних.Я думаю, что «мягкая кластеризация» - это путь, когда данные не легко разделить (например, когда «визуализация t-SNE» показывает все данные вместе, а не показывает четко разделенные группы. В этом случае принуждение данных строго относиться ктолько одна кластеризация может быть опасной).Я хотел бы попробовать m = 1.1, m = 2.0, чтобы вы могли видеть, как нечеткий параметр влияет на матрицу перентентности.

...