Napisałem własną procedurę klastrowania i chciałbym stworzyć dendrogram. Najłatwiej to zrobić, używając funkcji dendrogramu scipy. Wymaga to jednak, aby dane wejściowe były w tym samym formacie, co funkcja łączenia scipy. Nie mogę znaleźć przykładu, w jaki sposób dane wyjściowe są sformatowane. Zastanawiałem się, czy ktoś tam może mnie oświecić.scipy format linkowy
Odpowiedz
To z dokumentacji scipy.cluster.hierarchy.linkage() funkcji, to, że jest to całkiem jasne, opis formatu wyjściowego:
A ( n -1) przez 4 macierzy Z jest zwracany. W tej iteracji klastry z indeksami Z [i, 0] i Z [i, 1] są łączone w celu utworzenia klastra + n + n. Klaster o indeksie mniejszym niż n odpowiada jednej z pierwotnych obserwacji. Odległość między skupieniami Z [i, 0] i Z [i, 1] jest określona przez Z [i, 2]. Czwarta wartość Z [i, 3] reprezentuje liczbę oryginalnych obserwacji w nowo utworzonym skupieniu.
Potrzebujesz czegoś więcej?
Drobna korekcja: jest to (n-1) przez 4 macierzy. – HerrKaputt
Tak, więcej informacji byłoby niezwykle pomocne. Na przykład, gdybym miał wyliczyć wszystkie wskaźniki, jakie to jest przejście? Jak dokładnie są oznaczane węzły? Czy mógłbyś zadowalać się jasnym i dokładnym przykładem i krok po kroku, jak to jest sformatowane, wraz z drzewem i wszystkimi etykietami odpowiadającymi każdemu z węzłów. – mortonjt
Zgadzam się z https://stackoverflow.com/users/1167475/mortonjt, że dokumentacja nie wyjaśnia w pełni indeksowania klastrów pośrednich, podczas gdy ja zgadzam się z https://stackoverflow.com/users/1354844/dkar, że format jest inaczej dokładnie wyjaśniony.
na przykładzie danych z tego pytania: Tutorial for 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]])
Macierz podnośnik może być zbudowany za pomocą pojedynczego (tzn najbliższe punkty pasujące do całości):
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. ]])
Jako dokumentacja wyjaśnia klastry poniżej n (tutaj: 11) są po prostu punktami danych w oryginalnej macierzy A. Klastry pośrednie idą do przodu, są kolejno indeksowane.
W ten sposób klastry 7 i 9 (pierwsze scalenie) są scalane w skupienie 11, klastry 4 i 6 w 12. Następnie obserwuj linię trzecią, łącząc klastry 5 (od A) i 12 (od niepokazywanego klastra pośredniego 12) wynikający z odległości wewnątrz klastra (WCD) równej 0,5. Pojedyncza metoda zakłada, że nowe WCS wynosi 0,5, czyli odległość między A [5] a najbliższym punktem w grupie 12, A [4] i A [6]. Sprawdźmy:
In [198]: norm([a[5]-a[4]])
Out[198]: 0.70710678118654757
In [199]: norm([a[5]-a[6]])
Out[199]: 0.5
Ten klaster powinien być teraz klastrem pośrednim 13, który następnie jest połączony z A [2]. Tak więc nowa odległość powinna być najbliższa pomiędzy punktami A [2] i 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
Co, jak widać, sprawdza się i wyjaśnia format pośredni nowych klastrów.
Dokumentacja scipy jest dokładna, jak wskazał dkar ... ale trochę trudniej jest zamienić zwrócone dane w coś, co można wykorzystać do dalszej analizy.
Moim zdaniem powinny one zawierać możliwość zwracania danych w strukturze drzewa jak struktura danych.Poniższy kod będzie iterację matrycy i budowania drzewa:
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)
Zaznacz to: http://users.soe.ucsc.edu/~eads/iris.html może uda Ci pomóc! –