2016-07-15 2 views
0

Je fais maintenant le clustering sur python en utilisant from scipy.cluster.hierarchy import linkage Du manuel, je sais qu'il donne résultat dans cette forme -> [A, B, longueur, #] dont A et B sont les indices des éléments qui vont pour fusionner dans cette ... étape (?), mais puis-je obtenir des informations sur les clusters qui sont déjà fusionnés mais ne vont pas participer à cette étape?Comment puis-je lister tous les clusters actuels lorsque j'utilise un seul algorithme de liaison?

Par exemple, mon jeu de données est

A=[[1,1],[1,2],[1,3],[1,4],[1,5], [10,1],[10,2],[10,3],[10,4],[10,5], [15,1],[15,2],[15,3],[15,4],[15,5], [30,1],[30,2],[30,3],[30,4],[30,5]]

et appliquer l'algorithme de liaison unique sur elle

Z = linkage(A, 'single') 

Z=[[ 0. 4. 1. 2.] 
    [ 1. 20. 1. 3.] 
    [ 2. 21. 1. 4.] 
    [ 3. 22. 1. 5.] 
    [ 17. 19. 1. 2.] 
    [ 5. 9. 1. 2.] 
    [ 6. 25. 1. 3.] 
    [ 7. 26. 1. 4.] 
    [ 8. 27. 1. 5.] 
    [ 18. 24. 1. 3.] 
    [ 10. 14. 1. 2.] 
    [ 11. 30. 1. 3.] 
    [ 12. 31. 1. 4.] 
    [ 13. 32. 1. 5.] 
    [ 16. 29. 1. 4.] 
    [ 15. 34. 1. 5.] 
    [ 28. 33. 5. 10.] 
    [ 23. 36. 9. 15.] 
    [ 35. 37. 15. 20.]] 

ici, je choisis 5 comme la limitation de distance en cluster, si je reçois

[ 28. 33. 5. 10.]

je retracée 28 et 33 Retour aux indices originaux

cut = 5 
temp1 = [] 
temp2 = [] 
for i in range(len(Z)): 
if Z[i][2] >= cut: 
    temp1.append(Z[i]) 
for i in range(2): 
    temp2[i].append(int(temp1[0][i])) 
for j in range(0, len(temp2)): 
try: 
    g = max(temp2[j]) 
except: 
    continue 
G = int(g - len(A)) 
while g >= len(A): 
    ind = temp2[j].index(g) 
    temp2[j].append(int(Z[G][0])) 
    temp2[j].append(int(Z[G][1])) 
    del temp2[j][ind] 
    g = max(temp2[j]) 
    G = int(g - len(A)) 

et a constaté que

temp2 = [[8, 7, 6, 5, 9], [13, 12, 11, 10, 14]] 

qui signifie '28' est synonyme de points de [10,1],[10,2],[10,3],[10,4],[10,5] et '33' représente des points [15,1],[15,2],[15,3],[15,4],[15,5], ce qui signifie clairement que le cluster est constitué de [10, x] et que le cluster constitué de [15, x] va fusionner à ce stade.

Mais il est évident [1,1],[1,2],[1,3],[1,4],[1,5] et [30,1],[30,2],[30,3],[30,4],[30,5] devaient former deux autres groupes au stade plus tôt, donc au moment avant [10, x] et [15, x] fusionner, actuellement il y a 4 groupes

donc le résultat que je veut est comme

temp2 = [[8, 7, 6, 5, 9], [13, 12, 11, 10, 14], [0, 1, 2, 3, 4], [15, 16, 17, 18, 19]] 

Que dois-je faire pour obtenir les deux dernières grappes T^T ?? Merci à QQ avancé

Répondre

1

Comme décrit dans the documentation, linkage vous donne la distance entre les clusters, qui est la même que la distance entre les éléments cophénétique dans ces groupes. Comme décrit dans other documentation, fcluster vous donnera des agrégats plats, et si vous spécifiez 'distance' comme critère, coupez le dendrogramme en fonction de la distance cophénétique.

Vous pouvez donc obtenir ce que vous voulez en utilisant fcluster pour définir le seuil des grappes à la distance choisie. Cependant, une légère ride est que fcluster traite le seuil comme la plus grande distance à la masse, pas la plus basse distance à diviser, donc si vous utilisez 5 comme seuil, il rejoindra les deux groupes auxquels vous faites référence et vous donnera seulement trois groupes . Vous devrez choisir un seuil légèrement inférieur à 5 pour obtenir ce que vous voulez. Par exemple:

from scipy.cluster import hierarchy as clust 
>>> clust.fcluster(Z, 4.99999, criterion='distance') 
array([2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1]) 

Ceci vous indique le cluster dans lequel se trouve chaque élément.Pour traduire de nouveau dans les listes des indices dans chaque groupe, vous pouvez utiliser np.where:

>>> clusters = clust.fcluster(Z, 4.99999, criterion='distance') 
>>> [np.where(clusters==k)[0].tolist() for k in np.unique(clusters)] 
[[15L, 16L, 17L, 18L, 19L], 
[0L, 1L, 2L, 3L, 4L], 
[5L, 6L, 7L, 8L, 9L], 
[10L, 11L, 12L, 13L, 14L]] 

En somme, l'idée est de regarder ce que vous appelez la « limitation de distance » et utiliser fclust pour obtenir des grappes plates avec cette distance (ou plutôt, une distance légèrement inférieure) comme seuil. Cela vous donnera le numéro de cluster de chaque index, puis vous pouvez utiliser np.where pour obtenir une liste pour chaque cluster.

+0

Merci beaucoup !!!!!! C'est exactement ce que je cherche T^T BTW, ce n'est pas une question juste que je suis curieux, à quoi servent ces L dans votre dernière sortie? Je n'ai pas obtenu ces L dans mon résultat (et c'est bien quand même) – Chu

+0

@Xiadan: Ceux-ci indiquent un "entier long". C'est juste une ordure qui est jetée quand je convertis le tableau numpy en liste. Il n'apparaîtra probablement pas pour vous si vous êtes sur Python 3, et pourrait également ne pas apparaître en fonction des autres détails de la plate-forme (comme 64 vs 32 bits). Comme vous avez trouvé, cependant, cela n'a aucun impact sur le résultat; ça a l'air bizarre. – BrenBarn

+0

Et aussi merci pour la partie np.where T^T je savais qu'il doit y avoir une façon plus intelligente de traduire cela en listes d'indices. – Chu