formato de enlace scipy


He escrito mi propia rutina de clustering y me gustaría producir un dendrograma. La forma más fácil de hacer esto sería usar la función dendrogram de scipy. Sin embargo, esto requiere que la entrada esté en el mismo formato que produce la función de enlace scipy. No puedo encontrar un ejemplo de cómo se formatea la salida de esto. Me preguntaba si alguien puede iluminarme.

Author: Jason Sundram, 2012-03-23

3 answers

Esto es del scipy.Cluster.jerarquía.documentación de la función linkage () , creo que es una descripción bastante clara para el formato de salida:

A ( n -1) por 4 matriz Z se devuelve. En el i-ésima iteración, los grupos con índices de Z[i, 0] y Z[i, 1], se combinan para formar clúster n + i. Un grupo con un índice inferior a n corresponde a una de las observaciones originales. La distancia entre los grupos Z[i, 0] y Z [i, 1] es a cargo de Z [i, 2]. El cuarto valor Z [i, 3] representa el número de observaciones originales en el grupo recién formado.

¿necesitas algo más?

 25
Author: dkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-12 14:11:23

Estoy de acuerdo con https://stackoverflow.com/users/1167475/mortonjt que la documentación no explica completamente la indexación de clústeres intermedios, mientras que estoy de acuerdo con el https://stackoverflow.com/users/1354844/dkar que el formato se explica con precisión.

Usando los datos de ejemplo de esta pregunta: Tutorial para scipy.Cluster.jerarquía

A = np.array([[0.1,   2.5],
              [1.5,   .4 ],
              [0.3,   1  ],
              [1  ,   .8 ],
              [0.5,   0  ],
              [0  ,   0.5],
              [0.5,   0.5],
              [2.7,   2  ],
              [2.2,   3.1],
              [3  ,   2  ],
              [3.2,   1.3]])

Se puede construir una matriz de enlace usando el single (es decir, la coincidencia más cercana puntos):

z = hac.linkage(a, method="single")

 array([[  7.        ,   9.        ,   0.3       ,   2.        ],
        [  4.        ,   6.        ,   0.5       ,   2.        ],
        [  5.        ,  12.        ,   0.5       ,   3.        ],
        [  2.        ,  13.        ,   0.53851648,   4.        ],
        [  3.        ,  14.        ,   0.58309519,   5.        ],
        [  1.        ,  15.        ,   0.64031242,   6.        ],
        [ 10.        ,  11.        ,   0.72801099,   3.        ],
        [  8.        ,  17.        ,   1.2083046 ,   4.        ],
        [  0.        ,  16.        ,   1.5132746 ,   7.        ],
        [ 18.        ,  19.        ,   1.92353841,  11.        ]])

Como explica la documentación, los clústeres debajo de n (aquí: 11) son simplemente los puntos de datos en la matriz original A. Los clústeres intermedios en el futuro, se indexan sucesivamente.

Así, los grupos 7 y 9 (la primera fusión) se fusionan en el grupo 11, los grupos 4 y 6 en 12. Luego observe la línea tres, fusionando los clústeres 5 (de A) y 12 (del cluster intermedio no mostrado 12) resultando con una Distancia Dentro del Cluster (WCD) de 0.5. El método único implica que el nuevo WCS es 0.5, que es la distancia entre A [5] y el punto más cercano en el clúster 12, A[4] y A[6]. Vamos a comprobar:

 In [198]: norm([a[5]-a[4]])
 Out[198]: 0.70710678118654757
 In [199]: norm([a[5]-a[6]])
 Out[199]: 0.5

Este grupo debería ser ahora el grupo intermedio 13, que posteriormente se fusiona con un[2]. Por lo tanto, la nueva distancia debe ser la más cercana entre los puntos A[2] y A[4,5,6].

 In [200]: norm([a[2]-a[4]])
 Out[200]: 1.019803902718557
 In [201]: norm([a[2]-a[5]])
 Out[201]: 0.58309518948452999
 In [202]: norm([a[2]-a[6]])
 Out[202]: 0.53851648071345048

Que, como se puede ver también comprueba, y explica el formato intermedio de los nuevos clústeres.

 14
Author: user1603472,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:24

La documentación de scipy es precisa como dkar señaló ... pero es un poco difícil convertir los datos devueltos en algo que se pueda utilizar para un análisis posterior.

En mi opinión deberían incluir la capacidad de devolver los datos en un árbol como estructura de datos. El siguiente código iterará a través de la matriz y construirá un árbol:

from scipy.cluster.hierarchy import linkage
import numpy as np

a = np.random.multivariate_normal([10, 0], [[3, 1], [1, 4]], size=[100,])
b = np.random.multivariate_normal([0, 20], [[3, 1], [1, 4]], size=[50,])
centers = np.concatenate((a, b),)

def create_tree(centers):
    clusters = {}
    to_merge = linkage(centers, method='single')
    for i, merge in enumerate(to_merge):
        if merge[0] <= len(to_merge):
            # if it is an original point read it from the centers array
            a = centers[int(merge[0]) - 1]
        else:
            # other wise read the cluster that has been created
            a = clusters[int(merge[0])]

        if merge[1] <= len(to_merge):
            b = centers[int(merge[1]) - 1]
        else:
            b = clusters[int(merge[1])]
        # the clusters are 1-indexed by scipy
        clusters[1 + i + len(to_merge)] = {
            'children' : [a, b]
        }
        # ^ you could optionally store other info here (e.g distances)
    return clusters

print create_tree(centers)
 7
Author: Salik Syed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-20 06:25:03