J'ai besoin de regrouper un ensemble de données univarié simple en un nombre prédéfini de clusters. Techniquement, il serait plus proche de regrouper ou de trier les données car il ne s'agit que de 1D, mais mon patron l'appelle clustering, donc je vais m'en tenir à ce nom. La méthode actuellement utilisée par le système sur lequel je suis est K-means, mais cela semble exagéré.
Existe-t-il une meilleure façon d'effectuer cette tâche?
Les réponses à certains autres articles mentionnent KDE (Kernel Density Estimation), mais c'est une méthode d'estimation de la densité, comment cela fonctionnerait-il?
Je vois comment KDE renvoie une densité, mais comment lui dire de diviser les données en bacs?
Comment puis-je avoir un nombre fixe de bacs indépendamment des données (c'est une de mes exigences)?
Plus précisément, comment pourrait-on y parvenir en utilisant scikit learn?
Mon fichier d'entrée ressemble à:
str ID sls
1 10
2 11
3 9
4 23
5 21
6 11
7 45
8 20
9 11
10 12
Je veux regrouper le nombre sls en clusters ou bacs, de telle sorte que:
Cluster 1: [10 11 9 11 11 12]
Cluster 2: [23 21 20]
Cluster 3: [45]
Et mon fichier de sortie ressemblera à:
str ID sls Cluster ID Cluster centroid
1 10 1 10.66
2 11 1 10.66
3 9 1 10.66
4 23 2 21.33
5 21 2 21.33
6 11 1 10.66
7 45 3 45
8 20 2 21.33
9 11 1 10.66
10 12 1 10.66
Écrivez le code vous-même. Ensuite, cela correspond le mieux à votre problème!
Boilerplate: Ne présumez jamais que le code que vous téléchargez sur le net est correct ou optimal ... assurez-vous de bien le comprendre avant de l'utiliser.
%matplotlib inline
from numpy import array, linspace
from sklearn.neighbors.kde import KernelDensity
from matplotlib.pyplot import plot
a = array([10,11,9,23,21,11,45,20,11,12]).reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(a)
s = linspace(0,50)
e = kde.score_samples(s.reshape(-1,1))
plot(s, e)
from scipy.signal import argrelextrema
mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print "Minima:", s[mi]
print "Maxima:", s[ma]
> Minima: [ 17.34693878 33.67346939]
> Maxima: [ 10.20408163 21.42857143 44.89795918]
Vos clusters sont donc
print a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]]
> [10 11 9 11 11 12] [23 21 20] [45]
et visuellement, nous avons fait cette division:
plot(s[:mi[0]+1], e[:mi[0]+1], 'r',
s[mi[0]:mi[1]+1], e[mi[0]:mi[1]+1], 'g',
s[mi[1]:], e[mi[1]:], 'b',
s[ma], e[ma], 'go',
s[mi], e[mi], 'ro')
Nous avons coupé aux marqueurs rouges. Les marqueurs verts sont nos meilleures estimations pour les centres de grappes.