2013-08-21 8 views
9

Ho un algoritmo in esecuzione su un set di oggetti. Questo algoritmo produce un punteggio che determina le differenze tra gli elementi nel set.Valori di raggruppamento in base alla loro vicinanza in python (apprendimento macchina?)

L'output ordinato è qualcosa di simile:

[1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230]

Se si stabiliscono questi valori in giù su un foglio di calcolo si vede che essi costituiscono gruppi

[1,1,5,6,1,5] [10,22,23,23] [50,51, 51,52] [100,112,130] [500,512,600] [12000,12230]

C'è un modo per ottenere questi raggruppamenti in modo programmatico?

Forse un algoritmo di clustering che utilizza una libreria di apprendimento automatico? O sto pensando troppo a questo?

Ho guardato scikit ma i loro esempi sono troppo avanzate per il mio problema ...

risposta

2

È possibile utilizzare il clustering per raggruppare questi. Il trucco è capire che ci sono due dimensioni per i tuoi dati: la dimensione che puoi vedere e la dimensione "spaziale" che assomiglia a [1, 2, 3 ... 22]. È possibile creare questa matrice in numpy in questo modo:

import numpy as np 

y = [1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230] 
x = range(len(y)) 
m = np.matrix([x, y]).transpose() 

Quindi è possibile eseguire il clustering sulla matrice, con:

uscita
from scipy.cluster.vq import kmeans 
kclust = kmeans(m, 5) 

di kclust sarà simile a questa:

(array([[ 11, 51], 
     [ 15, 114], 
     [ 20, 12115], 
     [ 4,  9], 
     [ 18, 537]]), 21.545126372346271) 

Per tu, la parte più interessante è la prima colonna della matrice, che dice quali sono i centri lungo quella dimensione x:

kclust[0][:, 0] 
# [20 18 15 4 11] 

È possibile assegnare i punti a un cluster in base al quale dei cinque centri che sono più vicini al:

assigned_clusters = [abs(cluster_indices - e).argmin() for e in x] 
# [3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 0, 0, 0] 
+0

una funzione kmeans2 aggiornata (in scipy.cluster.vq) emette ora sia centroide ed etichetta, ad esempio 'kclust, label = kmeans (m, 5)' – Sean

+0

Ciao, Il codice non funziona. Errore in prima linea per ovvi motivi. Anche l'ultima riga produce un errore, 'cluster_indices' non definito. Puoi aiutarci per far funzionare questo codice? – gprakhar

+0

@gprakhar Usa 'cluster_indices = kclust [0] [:, 0]'. – joost

17

una buona opzione se non si conosce il numero di cluster è MeanShift:

import numpy as np 
from sklearn.cluster import MeanShift, estimate_bandwidth 

x = [1,1,5,6,1,5,10,22,23,23,50,51,51,52,100,112,130,500,512,600,12000,12230] 

X = np.array(zip(x,np.zeros(len(x))), dtype=np.int) 
bandwidth = estimate_bandwidth(X, quantile=0.1) 
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True) 
ms.fit(X) 
labels = ms.labels_ 
cluster_centers = ms.cluster_centers_ 

labels_unique = np.unique(labels) 
n_clusters_ = len(labels_unique) 

for k in range(n_clusters_): 
    my_members = labels == k 
    print "cluster {0}: {1}".format(k, X[my_members, 0]) 

uscita per questo algoritmo:

cluster 0: [ 1 1 5 6 1 5 10 22 23 23 50 51 51 52] 
cluster 1: [100 112 130] 
cluster 2: [500 512] 
cluster 3: [12000] 
cluster 4: [12230] 
cluster 5: [600] 

Modi fying quantile variabile è possibile cambiare il numero di clustering criteri di selezione

+2

Il primo argomento di 'np.array' deve essere' list (zip (x, np.zeros (len (x)))) '. Altrimenti, Python genera un errore: _TypeError: l'argomento int() deve essere una stringa, un oggetto simile a un byte o un numero, non 'zip'_ – Logan

+0

Questo approccio potrebbe non funzionare molto bene per alcuni input che non sono facilmente "clusterable" ", per esempio 'x = [90, 100, 110]'. Fallirà quindi con 'ValueError: Expected n_neighbors> 0. Ottenuto 0' (che può essere evitato con l'ottimizzazione dei parametri). Per tali input, https://stackoverflow.com/a/18385795/942774 è probabilmente la risposta più semplice e migliore. – hendrik

8

Non utilizzare il clustering per i dati 1-dimensionali

algoritmi di clustering sono progettati per i dati multivariati. Quando si dispone di dati 1-dimensionale, ordinarlo e cercare le maggiori lacune . Questo è banale e veloce in 1d, e non possibile in 2d. Se vuoi qualcosa di più avanzato, usa Kernel Density Estimation (KDE) e cerca i minimi locali per dividere il set di dati.

Ci sono un certo numero di duplicati di questa domanda:

+0

Questo approccio potrebbe essere sensibile al rumore. – jhegedus

+0

Al contrario. KDE è fluido e quindi non troppo sensibile al rumore. Molto meno di k-significa che è noto per essere molto sensibile a causa di termini di errore al quadrato. –

+0

Interessante, grazie per averlo indicato. – jhegedus