K-means est un algorithme de clustering non supervisé standard qui, étant donné un ensemble de "points" et un certain nombre de clusters K, attribuera chaque "point" à l'un des K clusters.
Pseudo-code de K-means
Notez qu'il existe de nombreuses variantes de K-means. Vous devez implémenter l'algorithme que je décris ci-dessous. Vous pouvez avoir une certaine variation sur l'algorithme ou utiliser des intégrés tant que vous obtiendrez le même résultat que cet algorithme étant donné les mêmes points initiaux.
Dans ce défi, toutes les entrées seront des points sur le plan 2D (chaque point est représenté par ses coordonnées en x et 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
Entrées et sorties
- Vous pouvez faire passer K et P
STDIN
, ou comme argument de fonction, etc. - P et les points de P peuvent être représentés en utilisant n'importe quelle structure naturelle pour les ensembles / listes dans la langue de votre choix.
- K est un entier strictement positif.
- Vous pouvez supposer que les entrées sont valides.
- Il y aura toujours au moins K points en P.
- Vous pouvez sortir les clusters vers
STDOUT
, les renvoyer d'une fonction, etc. - L'ordre des clusters et l'ordre à l'intérieur des clusters sont sans importance. -Vous pouvez soit renvoyer des groupes de points pour représenter des grappes, soit chaque point étiqueté avec un identifiant pour la grappe (par exemple un entier).
Cas de test
Étant donné que les clusters résultants dépendent des points initialement choisis, vous n'obtiendrez peut-être pas tous les mêmes résultats (ou le même résultat à chaque fois que vous exécutez votre code).
Par conséquent, prenez uniquement la sortie comme exemple de sortie.
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]]]
Notation
Il s'agit de code-golf , donc la réponse la plus courte en octets l'emporte.
la source
1
, tous les points du second ont une étiquette,2
etc.)K=2, P = [[1,1], [1,1], [1,1]]
.Réponses:
Matlab, 25 octets
Étant donné une
n x 2
matrice (une ligne par point, par exemple[[4,8]; [15,16]; [23,42]; [-13.37,-12.1]; [666,-666]]
), cette fonction renvoie une liste d'étiquettes pour chaque point d'entrée.la source
C ++,
479474 octetsSeulement ~ 20x autant que Matlab!
Golfé
L'entrée / sortie de l'algorithme est un ensemble de points (
struct P
) avecx
ety
; et la sortie est le même ensemble, avec leuri
ensemble pour indiquer l'indice du cluster de sortie dans lequel se termine le point.Cet extra
i
est également utilisé pour identifier les clusters. Dans la boucle principale, le centroïde le plus proche de chaque point est trouvé en triant une copie des centroïdes actuels par proximité de ce point.Cela gère les cas dégénérés (grappes vides) en conservant la position précédente des centroïdes correspondants (voir la définition de
P::n
, qui renvoie également la distance au centroïde précédent). Quelques caractères pourraient être sauvés en supposant qu'ils ne se reproduiraient pas.Non golfé, avec main
la source
#define R p){return
et changer le deuxième argument del
lap
sorte que vous pouvez l' utiliser trois fois au total?J,
6054 octetsDéfinit un verbe auxiliaire
p
qui prend une liste de points et de centroïdes et classe chaque point par l'index du centroïde le plus proche. Ensuite, il l'utilise pour répéter le processus de choix d'un nouveau centroïde en prenant les moyennes des points dans chaque cluster jusqu'à ce qu'il converge, puis pour partitionner les points pour la sortie.Usage
La valeur de k est donnée sous forme d'entier sur le LHS. La liste des points est donnée sous forme d'un tableau 2D sur le RHS. Ici, il est spécifié comme une liste de points qui est remodelée en un tableau 2D de 5 x 2. La sortie sera l'étiquette pour laquelle le cluster appartient à chaque point dans le même ordre que l'entrée.
Si vous désirez utiliser une graine fixe pour des résultats reproductibles, remplacer
?
par un?.
à(?#)
.Explication
la source
CJam (60 octets)
Il s'agit d'une fonction qui prend son entrée sous la forme
k p
sur la pile. Il suppose que les points sont représentés par des doubles, pas des entiers. Il ne suppose implicitement rien de la dimension des points, il se regrouperait donc aussi bien dans l'espace euclidien 6-D que dans le 2-D spécifié.Démo en ligne
la source
Mathematica
1412 octetsÉtant donné que les intégrés sont autorisés, cela devrait le faire.
Exemple
{{{4, 8}, {-13.37, -12.1}}, {{15, 16}, {23, 42}}, {{666, -666}}}
la source
f = FindClusters
,f[something]
.Gelée , 24 octets
Essayez-le en ligne!
Utilise les fonctionnalités qui ont été implémentées après la publication de ce défi. Soi-disant, ce n'est plus non concurrentiel .
Explication
la source
R , 273 octets
Essayez-le en ligne!
Prend
P
comme matrice, avecx
ety
coordonne respectivement dans la première et la deuxième colonne. RenvoieP
avec une première colonne ajoutée qui indique l'index de cluster (entier).J'ai dû redéfinir
w
en copiant la source dennet::which.is.max
pour se conformer à l'exigence selon laquelle le cluster est choisi aléatoirement en cas d'égalité. Sinon, j'utiliseraiswhich.min
debase
pour un total de 210 octets. Il y a encore de la place pour le golf mais je ne voulais pas trop le masquer pour donner aux autres une chance de repérer les problèmes possibles dans mon code.la source
Julia 213 octets
Renvoie un tableau de la même longueur que
p
, avec des entiers indiquant à quel cluster l'élément correspondantp
appartient.Je pense qu'il y a encore pas mal de possibilités pour optimiser le décompte des personnages.
(Bien sûr, je pourrais simplement utiliser le package Clustering.jl pour le faire trivialement)
la source