Процедура кластеризації, коли кожен кластер має рівну кількість балів?


25

У мене є кілька точок в R pX={x1,...,xn}Rp , і я хочу об'єднати точки так, щоб:

  1. Кожен кластер містить рівну кількість елементів . (Припустимо, що кількість кластерів ділить nXn .)

  2. Кожен кластер є «просторово згуртованим» у певному сенсі, як кластери з значень.k

Легко придумати безліч процедур кластеризації, які задовольняють одну чи іншу з них, але хтось знає про спосіб отримати обидва відразу?


2
Чи вказаний також розмір кластера? Тоді, як було сказано, проблема здається мені нерозв’язною. Розглянемо наступний випадок з : X = { - 1 , 0,99 , 1 , 1,01 } . Якщо ви хочете 2 кластери, ви отримуєте або різні розміри, або не "просторово згуртовані". Або ви хочете чогось на кшталт "максимально просторової згуртованості" - мінімізуючи максимальну відстань у внутрішньому кластері чи так? Іншим рішенням було б дозволити будь-який дільник n на розмір кластера, але тоді завжди є тривіальне рішення n кластерів розміром 1н=4,p=1Х={-1,0,99,1,1.01}нн1 .
Ерік П.

1
Влучне зауваження. В ідеалі мені хотілося б чогось, що є "максимально просторовим згуртованим" при задоволенні рівних обмежень кардинальності. Але мені було б цікаво почути про будь-які процедури, які також роблять тут інші компроміси, оскільки, можливо, вони можуть бути адаптовані.
Не Дерретт

Чи вистачить розділення даних на квантові? Якщо значення не є монотонними відносно один одного, я не бачу, як ще вони могли бути «просторово згуртованими».
селеній

4
Було проведено кілька останніх досліджень щодо обмеженої кластеризації. Google google.com/search?q=constrained+k-means .
whuber

Просто одна не перевірена ідея. У кластеризації часто використовується так звана статистика силуетів. Він показує, наскільки об’єкт кластеризований і який найкращий, сусідський кластер, до якого можна було б записати. Отже, ви можете почати з K-MEANS або іншої класифікації з різними кластерними n . Потім перемістіть об'єкти, не дуже добре класифіковані (згідно зі статистикою), до їх кращих сусідських кластерів з меншим n, поки не отримаєте рівну n . Я очікую ітерацій: переміщення деяких об'єктів, перерахунок статистики, переміщення деяких об'єктів тощо. Це буде компромісний процес.
ttnphns

Відповіді:


6

Я пропоную двоступеневий підхід:

  1. отримати хороші початкові оцінки центрів кластерів, наприклад, використовуючи жорсткі або нечіткі K-засоби.

  2. Використовуйте глобальне призначення найближчого сусіда, щоб пов’язати точки з центрами кластерів: Обчисліть матрицю відстані між кожною точкою та кожним центром кластера (ви можете зробити проблему трохи меншою, обчисливши розумні відстані), повторіть кожен центр кластера X разів і вирішіть лінійну проблема завдання . Ви отримаєте для кожного центру кластерів рівно X, що відповідає точкам даних, так що в глобальному масштабі відстань між точками даних та центрами кластерів мінімізується.

Зауважте, що ви можете оновити центри кластерів після кроку 2 і повторити етап 2, щоб в основному запустити K-засоби з фіксованою кількістю точок на кластер. І все-таки буде хорошою ідеєю спочатку отримати хорошу початкову здогадку.


4

Спробуйте цей варіант k-означає:

Ініціалізація :

  • вибирайте kцентри з набору даних випадковим чином, а ще краще, використовуючи стратегію kmeans ++
  • для кожної точки обчисліть відстань до найближчого центру кластера та побудуйте для цього купу
  • намалюйте точки з купи та призначте їх до найближчого кластеру, якщо кластер вже не переповнюється. Якщо це так, обчисліть наступний найближчий центр кластера та знову вставіть у купу

Зрештою, у вас повинен бути розподіл, який відповідає вашим вимогам + -1 однакова кількість об'єктів на кластер (переконайтеся, що останні кілька кластерів також мають правильне число. Перші mкластери повинні мати ceilоб'єкти, а решта точно floorоб'єкти.)

Крок ітерації :

Реквізити: список для кожного кластеру з "підмінами пропозицій" (об'єкти, які вважають за краще бути в іншому кластері).

Е крок: обчислити оновлені центри кластерів , як і в звичайних до- засобів

М крок: Ітерація через всі крапки (або тільки один, або все в одному пакеті)

Обчисліть найближчий центр кластера для об'єкта / всіх центрів кластерів, які ближче, ніж поточні кластери. Якщо це інший кластер:

  • Якщо інший кластер менший, ніж поточний кластер, просто перемістіть його до нового кластеру
  • Якщо є пропозиція swap з іншого кластеру (або будь-якого кластера з меншою відстані), поміняйте місцями два кластерні завдання (якщо пропозицій більше, виберіть той, який має найбільше вдосконалення)
  • в іншому випадку вкажіть пропозицію про своп для іншого кластеру

Розміри кластерів залишаються інваріантними (+ - різниця стелі / підлоги), об'єкти переміщуються лише з одного кластеру в інший до тих пір, поки це призведе до покращення оцінки. Тому воно повинно сходитися в певний момент, як k-засоби. Це може бути трохи повільніше (тобто більше ітерацій).

Я не знаю, чи було це опубліковано чи впроваджено раніше. Це саме те, що я б спробував (якби я спробував k-засоби. Є набагато кращі алгоритми кластеризації.)

Хорошим місцем для початку може стати реалізація k-засобів в ELKI , яка, здається, підтримує три різні ініціалізації (включаючи k-засоби ++), і автори заявили, що вони також хочуть мати різні стратегії ітерації, щоб охопити всі різні поширені варіанти модульної форми (наприклад, Lloyd, MacQueen, ...).


2
Аналогічний підхід включений у ELKI як навчальний посібник та модуль "розширення" підручника: elki.dbs.ifi.lmu.de/wiki/Tutorial/SameSizeKMeans
Еріх Шуберт

3

Це проблема оптимізації. У нас є бібліотека Java з відкритим кодом, яка вирішує цю проблему (кластеризація, коли кількість на кластер має бути між встановленими діапазонами). Потрібно, щоб ваша загальна кількість балів була не більше кількох тисяч, але не більше 5000, а може і 10000.

Бібліотека тут:

https://github.com/PGWelch/territorium/tree/master/territorium.core

Сама бібліотека налаштована на проблеми географічного типу / ГІС - тому ви побачите посилання на X і Ys, широти і довготи, клієнтів, відстань і час тощо. Ви можете просто проігнорувати "географічні" елементи, хоча і використовувати їх як чистий кластер.

Ви надаєте набір спочатку порожніх вхідних кластерів, кожний з мінімальною та максимальною цільовою кількістю. Кластерист присвоює точки вхідним кластерам, використовуючи евристичний алгоритм оптимізації (підміни, переміщення тощо). При оптимізації він, по-перше, визначає пріоритетність утримання кожного кластеру в межах його мінімального та максимального діапазону, а потім, по-друге, мінімізує відстані між усіма точками кластеру та центральною точкою кластера, тому кластер є просторово згуртованим.

Ви надаєте розв'язувачу метричну функцію (тобто функцію відстані) між точками за допомогою цього інтерфейсу:

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/TravelMatrix.java

Метод фактично побудований для повернення як відстані, так і «часу», оскільки він розроблений для географічних проблем, заснованих на подорожах, але для задач довільної кластеризації просто встановив, що «час» дорівнює нулю, а відстань буде вашою фактичною метрикою, яку ви використовуєте між бали.

Ви встановите свою проблему в цьому класі:

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Problem.java

Ваші бали будуть "Клієнти", а їх кількість буде 1. У класі клієнта переконайтеся, що ви встановили costPerUnitTime = 0 та costPerUnitDistance = 1, якщо ви повернете свою метричну відстань у поле "відстань", повернене TravelMatrix.

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Customer.java

Дивіться тут приклад запуску розв'язувача:

https://github.com/PGWelch/territorium/blob/master/territorium.core/src/test/java/com/opendoorlogistics/territorium/TestSolver.java



2

Нещодавно мені це було потрібно для не дуже великого набору даних. Моя відповідь, хоча має відносно тривалий час роботи, гарантовано збігається з локальним оптимумом.

def eqsc(X, K=None, G=None):
    "equal-size clustering based on data exchanges between pairs of clusters"
    from scipy.spatial.distance import pdist, squareform
    from matplotlib import pyplot as plt
    from matplotlib import animation as ani    
    from matplotlib.patches import Polygon   
    from matplotlib.collections import PatchCollection
    def error(K, m, D):
        """return average distances between data in one cluster, averaged over all clusters"""
        E = 0
        for k in range(K):
            i = numpy.where(m == k)[0] # indeces of datapoints belonging to class k
            E += numpy.mean(D[numpy.meshgrid(i,i)])
        return E / K
    numpy.random.seed(0) # repeatability
    N, n = X.shape
    if G is None and K is not None:
        G = N // K # group size
    elif K is None and G is not None:
        K = N // G # number of clusters
    else:
        raise Exception('must specify either K or G')
    D = squareform(pdist(X)) # distance matrix
    m = numpy.random.permutation(N) % K # initial membership
    E = error(K, m, D)
    # visualization
    #FFMpegWriter = ani.writers['ffmpeg']
    #writer = FFMpegWriter(fps=15)
    #fig = plt.figure()
    #with writer.saving(fig, "ec.mp4", 100):
    t = 1
    while True:
        E_p = E
        for a in range(N): # systematically
            for b in range(a):
                m[a], m[b] = m[b], m[a] # exchange membership
                E_t = error(K, m, D)
                if E_t < E:
                    E = E_t
                    print("{}: {}<->{} E={}".format(t, a, b, E))
                    #plt.clf()
                    #for i in range(N):
                        #plt.text(X[i,0], X[i,1], m[i])
                    #writer.grab_frame()
                else:
                    m[a], m[b] = m[b], m[a] # put them back
        if E_p == E:
            break
        t += 1           
    fig, ax = plt.subplots()
    patches = []
    for k in range(K):
        i = numpy.where(m == k)[0] # indeces of datapoints belonging to class k
        x = X[i]        
        patches.append(Polygon(x[:,:2], True)) # how to draw this clock-wise?
        u = numpy.mean(x, 0)
        plt.text(u[0], u[1], k)
    p = PatchCollection(patches, alpha=0.5)        
    ax.add_collection(p)
    plt.show()

if __name__ == "__main__":
    N, n = 100, 2    
    X = numpy.random.rand(N, n)
    eqsc(X, G=3)

1
Дякуємо за цей внесок, @ user2341646. Ви не хотіли б додати деяку експозицію, яка пояснює, що таке рішення, як воно працює, і чому це рішення?
gung - Відновіть Моніку

ДОБРЕ. В основному алгоритм починається з присвоєнь членства, які є випадковими, але в кластері є близькі до членів G, а загалом є K кластери. Ми визначаємо функцію помилок, яка вимірює середні відстані між даними в одному кластері, усереднені по всіх кластерах. Систематично переглядаючи всі пари даних, ми бачимо, якщо обмін членством цих двох даних призводить до меншої помилки. Якщо це так, ми оновлюємо найменшу можливу помилку, інакше відміняємо перемикач членства. Ми робимо це, поки не залишиться більше рухів за один цілий прохід.
Олександр Каїн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.