K-means - это стандартный алгоритм кластеризации без наблюдения, который, учитывая набор «точек» и количество кластеров K, назначит каждую «точку» одному из K кластеров.
Псевдокод К-средних
Обратите внимание, что существует много вариантов K-средних. Вы должны реализовать алгоритм, который я описываю ниже. Вы можете иметь некоторые вариации в алгоритме или использовать встроенные модули, если вы получите тот же результат, что и этот алгоритм, с теми же начальными точками.
В этой задаче все входные данные будут точками на 2D-плоскости (каждая точка представлена своими координатами в x и y).
Inputs: K, the number of clusters
P, the set of points
Choose K points of P uniformly at random
Each chosen point is the initial centroid of its cluster
Loop:
For each point in P:
Assign to the cluster whose centroid is the nearest (Euclidean distance)
In case of a tie, any of the tied cluster can be chosen
Recompute the centroid of each cluster:
Its x coordinate is the average of all x's of the points in the cluster
Its y coordinate is the average of all y's of the points in the cluster
Until the clusters don't change from one iteration to the next
Output: the set of clusters
Входы и выходы
- Вы можете использовать K и P
STDIN
как аргумент функции и т. Д. - P и точки в P могут быть представлены с использованием любой структуры, которая естественна для наборов / списков на выбранном вами языке.
- K - строго положительное целое число.
- Вы можете предположить, что входные данные действительны.
- Всегда будет хотя бы K очков в P.
- Вы можете выводить кластеры в
STDOUT
, возвращать их из функции и т. Д. - Порядок кластеров и порядок внутри кластеров не имеет значения. -Вы можете вернуть группы точек для представления кластеров, или каждая точка помечена идентификатором для кластера (например, целое число).
Контрольные примеры
Поскольку получающиеся кластеры зависят от того, какие точки были изначально выбраны, вы можете не все получить одинаковые результаты (или один и тот же результат каждый раз, когда запускаете свой код).
Следовательно, используйте выходные данные только в качестве примера.
Input:
K = 1
P = [[1,2.5]]
Output:
[[[1,2.5]]]
Input:
K = 3
P = [[4,8], [15,16], [23,42], [-13.37,-12.1], [666,-666]]
Output:
[[[666,-666]],[[-13.37,-12.1],[4,8]],[[15,16],[23,42]]]
Input:
K = 2
P = [[1,1], [1,1], [1,1]]
Output:
[[[1,1]],[[1,1],[1,1]]]
счет
Это код-гольф , поэтому выигрывает самый короткий ответ в байтах.
источник
1
, все точки второго кластера имеют метки и2
т. Д.)K=2, P = [[1,1], [1,1], [1,1]]
.Ответы:
Matlab, 25 байт
Для данной
n x 2
матрицы (например, по одной строке на точку[[4,8]; [15,16]; [23,42]; [-13.37,-12.1]; [666,-666]]
) эта функция возвращает список меток для каждой входной точки.источник
C ++,
479474 байтаВсего в 20 раз больше, чем Matlab!
Golfed
Вход / выход алгоритма представляет собой набор точек (
struct P
) сx
иy
; и выходные данные являются теми же самыми, с ихi
установленными, чтобы указать индекс выходного кластера, в котором заканчивается точка.Это дополнение
i
также используется для идентификации кластеров. В основном цикле ближайший центроид к каждой точке находится путем сортировки копии текущих центроидов по близости к этой точке.Это обрабатывает вырожденные случаи (пустые кластеры), сохраняя предыдущую позицию соответствующих центроидов (см. Определение
P::n
, которое также возвращает расстояние до предыдущего центроида). Несколько символов могут быть сохранены, если предположить, что они не возникнут.Неуправляемый, с основным
источник
#define R p){return
и изменить второй аргументl
на,p
чтобы вы могли использовать его трижды всего?J
6054 байтаОпределяет вспомогательный глагол,
p
который берет список точек и центроидов и классифицирует каждую точку по индексу ближайшего центроида. Затем он использует это, чтобы повторить процесс выбора нового центроида, беря средние значения точек в каждом кластере, пока он не сходится, а затем разделить точки для вывода.Применение
Значение k задается как целое число на LHS. Список точек представлен в виде двумерного массива на RHS. Здесь он указывается в виде списка точек, который преобразуется в двумерный массив 5 x 2. Выходными данными будет метка, для которой кластер каждой точке принадлежит в том же порядке, что и входные.
Если вы хотите использовать фиксированное начальное число для воспроизводимых результатов, замените его
?
на?.
at(?#)
.объяснение
источник
CJam (60 байт)
Это функция, которая принимает данные в виде
k p
стека. Предполагается, что точки представлены двойными, а не целыми числами. Он не подразумевает ничего явно относительно размерности точек, поэтому он будет группироваться так же хорошо в 6-мерном евклидовом пространстве, как и в указанном 2-мерном.Онлайн демо
источник
Mathematica
1412 байтПоскольку встроенные модули разрешены, это должно быть сделано.
пример
{{{4, 8}, {-13,37, -12,1}}, {{15, 16}, {23, 42}}, {{666, -666}}}
источник
f = FindClusters
,f[something]
.Желе , 24 байта
Попробуйте онлайн!
Использует функции, которые были реализованы после публикации этого вызова. Предположительно, это больше не конкурирует .
объяснение
источник
R , 273 байта
Попробуйте онлайн!
Принимает в
P
качестве матрицы, сx
иy
координатами в первом и втором столбце соответственно. ВозвращаетP
с добавлением первого столбца, который указывает индекс кластера (целое число).Мне пришлось переопределить
w
, скопировав источник,nnet::which.is.max
чтобы соответствовать требованию, что кластер выбирается случайным образом в случае связей. В противном случае я бы использовалwhich.min
отbase
в общей сложности 210 байтов. Есть все еще место для игры в гольф, но я не хотел запутывать это слишком много, чтобы дать другим возможность обнаружить возможные проблемы в моем коде.источник
Юлия 213 байт
Возвращает массив той же длины
p
, что и целые числа, указывающие, к какому кластеру принадлежит соответствующий элементp
.Я думаю, что есть еще много возможностей для оптимизации обратного отсчета символов.
(Конечно, я мог бы просто использовать пакет Clustering.jl, чтобы сделать это тривиально)
источник