Подтвердить что ты не робот

Формат scipy linkage

Я написал свою собственную процедуру кластеризации и хотел бы создать дендрограмму. Самый простой способ сделать это - использовать функцию scipy dendrogram. Однако для этого требуется, чтобы вход был в том же формате, что и функция scipy linkage. Я не могу найти пример того, как вывод этого форматируется. Мне было интересно, может ли кто-то там просветить меня.

4b9b3361

Ответ 1

Это из scipy.cluster.hierarchy.linkage(), я думаю, что это довольно четкое описание для выходного формата:

A (n-1) на 4 матрицы Z возвращается. На i-й итерации кластеры с индексами Z [i, 0] и Z [i, 1] объединяются для формирования кластера n + i. Кластер с индексом меньше n соответствует одному из первоначальных наблюдений. Расстояние между кластерами Z [i, 0] и Z [i, 1] задается Z [i, 2]. Четвертое значение Z [i, 3] представляет количество исходных наблюдений во вновь образованном кластере.

Вам нужно что-то еще?

Ответ 2

Я согласен с https://stackoverflow.com/users/1167475/mortonjt в том, что документация не полностью объясняет индексацию промежуточных кластеров, в то время как я согласен с https://stackoverflow.com/users/1354844/dkar, что формат в противном случае точно объясняется.

Используя данные примера из этого вопроса: Учебник для scipy.cluster.hierarchy

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

Матрица связей может быть построена с использованием единственной (то есть ближайших совпадающих точек):

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.        ]])

Поскольку в документации объясняются кластеры ниже n (здесь: 11), это просто точки данных в исходной матрице A. Промежуточные кластеры, идущие вперёд, индексируются последовательно.

Таким образом, кластеры 7 и 9 (первое слияние) объединяются в кластер 11, кластеры 4 и 6 в 12. Затем наблюдайте третью строку, объединяя кластеры 5 (из А) и 12 (из непроявленного промежуточного кластера 12), что приводит к расстоянию внутри кластера (WCD) 0,5. Единственный метод предполагает, что новый WCS равен 0,5, что является расстоянием между A [5] и ближайшей точкой в ​​кластере 12, A [4] и A [6]. Пусть проверьте:

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

Теперь этот кластер должен быть промежуточным кластером 13, который впоследствии сливается с A [2]. Таким образом, новое расстояние должно быть самым близким к точкам A [2] и 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

Что, как можно видеть, также проверяет и объясняет промежуточный формат новых кластеров.

Ответ 3

Скупичная документация точна, как указал dkar... но немного сложно превратить возвращенные данные в то, что можно использовать для дальнейшего анализа.

По моему мнению, они должны включать возможность возврата данных в дерево, например, в структуру данных. Следующий код будет проходить через матрицу и построить дерево:

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)