web-dev-qa-db-fra.com

Comment pourrait-on utiliser l'estimation de la densité du noyau comme méthode de clustering 1D dans Scikit Learn?

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
24
Alex Kinman

É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)

enter image description here

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')

enter image description here

Nous avons coupé aux marqueurs rouges. Les marqueurs verts sont nos meilleures estimations pour les centres de grappes.

44