Горящий куст двойного отрицания
Горящий куст двойного отрицания

Времена когда горящий куст мог принести озарение давно прошли. Примитивный опыт уже не может стать источником открытий. А всё потому, что он обобщён и впитан в культуру человечества. И чтобы подключиться к мудрости предков нужно опереться на философию. В этой статье мы познакомимся с новым алгоритмом кластеризации и поверхностно затронем некоторые философские категории. Перевернём объективность в субъектность и обратно.

Инструменты кластеризации

Кластеризация — это поиск групп о которых ничего не известно (не путать с классификацией, т. е. с назначением класса элементам). Неизвестность разрешается перебором параметров.

Если известно k количество искомых групп, то можно применить метод k-средних (k-means). Такой алгоритм подбирает центры. Работает для сферических групп.

Если перед вами вытянулись колбаски, то можно применить плотностный алгоритм DBSCAN(ε, k) — задать размер области ε и сколько точек k должна содержать область. Если две точки касаются друг друга такими областями, тогда эти точки принадлежат одному кластеру.

В обоих случаях приходится перебирать параметры. Перезапуск затратен, и выбор варианта человеком субъективен. Вот было бы здорово исключить эту меру мер и собрать решение за один прогон.

К-means не нашёл сфер. DBSCAN не нашёл переходов колбасок. Друг справился.
К-means не нашёл сфер. DBSCAN не нашёл переходов колбасок. Друг справился.

В поисках универсалий

Поступай с другими так, как хочешь, чтобы поступали с тобой.

И если другой ответит взаимностью, то вы притянитесь. Подобное соединяется с подобным, а неравноправным отношениям стыд, срам и конец очереди.

Но позвольте! У нас же данные, а не человеки! Поэтому нам предстоит очеловечить точки, закрыть их от окружающего мира и тем самым превратить в субъектов.

Если из точки распространить шар, то можно будет посчитать сколько точек попало в шар и какой радиус этого шара. А если остановить рост этого шара на конкретной точке, то определится отношение к этой точке-соседу. У этого отношения будет две стороны, количественный ранг и качественное расстояние.

Шары отношений между A и B. 2 точки внутри белого шара (A, B) и 4 точки внутри синего (A, B, C, D).
Шары отношений между A и B. 2 точки внутри белого шара (A, B) и 4 точки внутри синего (A, B, C, D).

Рассмотрим отношение между A и B:

• Для A: A, B, C, E. Ранг AB = 2.
Расстояние d.

• Для B: B, C, D, A. Ранг BA = 4. Расстояние d.

Оба шара имеют одинаковый радиус d = d(AB) = d(BA), но ранги отличаются. В жизни так же, вы стоите напротив человека, а он напротив вас. Объективно между вами равное расстояние, мерь хоть от него, хоть от вас, но есть маленький субъектный нюанс. Два нюанса, его и ваш. Учтём их. Сотворим из точек субъектов и оценим чужое качество.

Итак, у нас две независимые точки A и B. И явная разница в окружении: у А 2 точки, а у B 4 точки. Из "глаз" A оценим чужое отношение так, как будто у B столько же точек. То есть посчитаем BA в единицах A: поделим d на 4 и умножим на 2. И наоборот, из "глаз" B — оценка AB = 4/2·d.

Субъект А с двумя шарами на 2 и 4 точки. Субъект B — шары пунктиром.
Субъект А с двумя шарами на 2 и 4 точки. Субъект B — шары пунктиром.

Второй способ оценки — через перенос и натягивание чужого шара.

Перенесём голубой шар в систему координат A, сохраняя количественные свойства шара (внутри должно быть 4 точки). Тогда шар увеличится, чтобы вместить A, B, C, E!

Для B тоже всё поменяется — только наоборот шар уменьшится до точек B, C (белым пунктиром).

Итого получены по две оценки чужого отношения каждым субъектом. Сравним эти оценки с изначальным радиусом AB=d.

  • Для A: количественная оценка уменьшилась до 2/4·d; качественная оценка увеличилась до AE, т. е. до четвёртого ранга d(A₄);

  • Для B наоборот: количественная оценка увеличилась до 4/2·d; качественная оценка уменьшилась до второго ранга d(B₂).

Каждая точка стала субъектом, у неё нет доступа к чужим радиусам, к качественным сторонам отношений других. Но при этом у них появились две оценки происходящего r/R·d(r) и d(R). Заметим, что если бы ранги совпадали r=R, то обе оценки были бы равны d. Выбрав наибольшую оценку, станет возможным отделить подобные от неподобных

\max{( \frac{r}{R} d(r); d(R))}.

Самое близкое из таких отношений и кристаллизуется в ребро. Образуется деревце, и поиск наиближайшего запустится снова. Так будет продолжаться до тех пор, пока все точки не соединятся.

Без всяких зацепок-параметров нам удалось создать формулу диалектического расстояния, отражающую суть отношений точек в пространстве. Объективность пространства перешла в субъектность точек и вывернулась обратно в объект-ребро. Пройдя двойное отрицание, абстрактное стало конкретным.

ДРУГ (druhg)

Взаимное опосредование точек друг другом снял вопрос параметров и их подбора. Получился детерминированный алгоритм. Вначале собираются двухточечные деревья рангом 2. Потом сгустки точек растут, соединяя соседей, пока всё не превратится в единое дерево. При этом выбросы (ранги 2) будут иметь последнюю очередь соединений.

Алгоритм идеален для первичного исследования данных (EDA) и для поиска глобальных выбросов.

Шары A и B более схожи (ранги 4 и 5), чем шар C (ранг 2). Выброс С проигрывает A, B в приоритете.
Шары A и B более схожи (ранги 4 и 5), чем шар C (ранг 2). Выброс С проигрывает A, B в приоритете.

Глобальный порядок, локальный расчёт

Ребро с создаётся позже а и b. Но a и b независимы.
Ребро с создаётся позже а и b. Но a и b независимы.

Создаётся видимость глобального порядка соединений. Но это не так.

Ребро a значительно меньше ребра b, но они не влияют друг друга. Главное чтобы они случились до ребра c.

Частичный порядок позволяет познавать мир локально и не требует знаний обо всех точках света. Что открывает возможность параллельных вычислений на ячейках сетки пространства.

Сложность вычислений

Может также показаться, что сравнение всех точек со всеми — это вычислительно затратная задача с квадратичной сложностью O(n²). А повторный запуск процесса поиска ближайшего соединения усложняет вычисление до O(n³). Но это не так.

Поиск глобального ближайшего заменяется на поиск субъектных ближайших и хранение этих оптимумов. Структура данных k-ближайших соседей упрощает алгоритмическую сложность до O(n logn).

У всех алгоритмов заранее подогнаны параметры, кроме Друга (последняя колонка).
У всех алгоритмов заранее подогнаны параметры, кроме Друга (последняя колонка).

Точность vs производительность

В настоящей реализации можно ускорить алгоритм, ограничив количество соседей max_ranking. Но тогда есть вероятность, что в соседи не попадут точки другого кластера. (На предыдущей картинке пятый тест был перезапущен по этой причине).

Чтобы точки одного полумесяца, увидели другой, требуется 64+ соседей
Чтобы точки одного полумесяца, увидели другой, требуется 64+ соседей

При ограничении от 6 до 63 ближайших соседей достигается хороший результат. После 64 соседей результат сходится и впустую тратится время обработки (возможно алгоритмически решится через поиск лучшего для дерева, а не точки).

Результат быстро сходится. Но реализацию ещё нужно оптимизировать.
Результат быстро сходится. Но реализацию ещё нужно оптимизировать.

Запуск и исследование вложенности

Жми сюда. Пример и код

Нажал сюда, нажми и на звёздочку с лайком.

https://github.com/artamono1/druhg/

# pip install druhg

from druhg import DRUHG
import matplotlib.pyplot as plt
import pandas as pd, numpy as np

XX = pd.read_csv('chameleon.csv', sep='\t', header=None)
XX = np.array(XX)
clusterer = DRUHG(max_ranking=200, do_edges=True)
clusterer.fit(XX)

# research tool with silders
clusterer.plot()

# manual labels 
labels = clusterer.relabel(exclude=[], 
                           size_range=[0.2, 2242], 
                           fix_outliers=1)

Первоначальный запуск дороговат. Но исследование вложенной структуры практически бесплатно. Можно экспериментировать:

  • Разбить кластер по его лейблу. exclude=[7749] разобьёт красный огурец

  • Не выводить слишком маленькие или слишком большие кластеры. size_range=[0.2,2242] от 20% размера выборки до конкретных 2242. Слайдер Qty справа.

  • Покрасить выбросы по соединённости. fix_outliers=1.

Или запустить clusterer.plot():

Инструмент по разбивке кластеров по размеру и значению. Не требует перезапуска алгоритма.
Инструмент по разбивке кластеров по размеру и значению. Не требует перезапуска алгоритма.

Инструмент позволяет выбрать нужную разбивку по размеру кластеров — почему-то такой инструмент не предоставляется в стандартных инструментах. Позволяет выявлять глобальные выбросы. Получать общую информацию по кластеру. Наигравшись, можно сохранить результат через relabel().

P.S. о секретном соусе, превращающем деревья в кластеры, и о диалектике целостности расскажу в следующей статье.