3

Ich habe mit Hierarchical Clustering experimentiert und in R ist es so einfach hclust(as.dist(X),method="average"). Ich fand eine Methode in Python, die auch ziemlich einfach ist, außer dass ich etwas verwirrt bin, was mit meiner Eingabe-Distanzmatrix passiert.Dreieck vs. Quadrat Abstandsmatrix für hierarchisches Clustering Python?

Ich habe eine Ähnlichkeitsmatrix (DF_c93tom w/eine kleinere Testversion namens DF_sim), die ich in eine Unähnlichkeitsmatrix DF_dissm = 1 - DF_sim umwandeln.

Ich verwende dies als Eingabe in linkage von scipy, aber die Dokumentation sagt, dass es in einer quadratischen oder Dreiecksmatrix dauert. Ich bekomme einen anderen Cluster für die Eingabe eines lower triangle, upper triangle und square matrix. Warum ist das? Es möchte ein oberes Dreieck aus der Dokumentation, aber das untere Dreiecks-Cluster sieht WIRKLICH ähnlich aus.

Meine Frage, warum sind alle Cluster unterschiedlich? Welches ist korrekt?

Dies ist die Dokumentation für die Eingangsdistanzmatrix für linkage

y : ndarray 
A condensed or redundant distance matrix. A condensed distance matrix is a flat array containing the upper triangular of the distance matrix. 

ist hier mein Code:

import matplotlib.pyplot as plt 
import seaborn as sns 
import numpy as np 
import pandas as pd 
from scipy.cluster.hierarchy import dendrogram, linkage 

%matplotlib inline 

#Test Data 
DF_sim = DF_c93tom.iloc[:10,:10] #Similarity Matrix 
DF_sim.columns = DF_sim.index = range(10) 
#print(DF_test) 
#   0 1   2   3 4 5 6 7 8 9 
# 0 1.000000 0 0.395833 0.083333 0 0 0 0 0 0 
# 1 0.000000 1 0.000000 0.000000 0 0 0 0 0 0 
# 2 0.395833 0 1.000000 0.883792 0 0 0 0 0 0 
# 3 0.083333 0 0.883792 1.000000 0 0 0 0 0 0 
# 4 0.000000 0 0.000000 0.000000 1 0 0 0 0 0 
# 5 0.000000 0 0.000000 0.000000 0 1 0 0 0 0 
# 6 0.000000 0 0.000000 0.000000 0 0 1 0 0 0 
# 7 0.000000 0 0.000000 0.000000 0 0 0 1 0 0 
# 8 0.000000 0 0.000000 0.000000 0 0 0 0 1 0 
# 9 0.000000 0 0.000000 0.000000 0 0 0 0 0 1 

#Dissimilarity Matrix 
DF_dissm = 1 - DF_sim 

#Redundant Matrix 
#np.tril(DF_dissm).T == np.triu(DF_dissm) 
#True for all values 

#Hierarchical Clustering for square and triangle matrices 
fig_1 = plt.figure(1) 
plt.title("Square") 
Z_square = linkage((DF_dissm.values),method="average") 
dendrogram(Z_square) 

fig_2 = plt.figure(2) 
plt.title("Triangle Upper") 
Z_triu = linkage(np.triu(DF_dissm.values),method="average") 
dendrogram(Z_triu) 

fig_3 = plt.figure(3) 
plt.title("Triangle Lower") 
Z_tril = linkage(np.tril(DF_dissm.values),method="average") 
dendrogram(Z_tril) 

plt.show() 

enter image description here

Antwort

3

Wenn ein 2D-Array als erstes Argument übergeben wird Zu scipy.cluster.hierarchy.linkage, wird es als eine Folge der Beobachtung behandelt s und scipy.spatial.pdist is used, um es in eine Sequenz von paarweisen Abständen zwischen den Beobachtungen zu konvertieren.

Es ist ein github issue dieses Verhalten in Bezug auf, da es bedeutet, dass eine Weitergabe „distance matrix“ wie DF_dissm.values (stumm) erzeugt ein falsches Ergebnis .

So the upshot of this ist, dass keines dieser

Z_square = linkage((DF_dissm.values),method="average") 
Z_triu = linkage(np.triu(DF_dissm.values),method="average") 
Z_tril = linkage(np.tril(DF_dissm.values),method="average") 

das gewünschte Ergebnis.Stattdessen verwenden

  • np.triu_indices:

    h, w = arr.shape 
    Z = linkage(arr[np.triu_indices(h, 1)], method="average") 
    
  • oder spatial.distance.squareform:

    from scipy.spatial import distance as ssd 
    Z = linkage(ssd.squareform(arr), method="average") 
    
  • oder gelten spatial.distance.pdist auf die ursprünglichen Punkte:

    Z = hierarchy.linkage(ssd.pdist(points), method="average") 
    
  • oder vorbei an der 2D-Array points:

    Z = hierarchy.linkage(points, method="average") 
    

import matplotlib.pyplot as plt 
import numpy as np 
from scipy.cluster import hierarchy as hier 
from scipy.spatial import distance as ssd 
np.random.seed(2016) 

points = np.random.random((10, 2)) 
arr = ssd.cdist(points, points) 

fig, ax = plt.subplots(nrows=4) 

ax[0].set_title("condensed upper triangular") 
Z = hier.linkage(arr[np.triu_indices(arr.shape[0], 1)], method="average") 
hier.dendrogram(Z, ax=ax[0]) 

ax[1].set_title("squareform") 
Z = hier.linkage(ssd.squareform(arr), method="average") 
hier.dendrogram(Z, ax=ax[1]) 

ax[2].set_title("pdist") 
Z = hier.linkage(ssd.pdist(points), method="average") 
hier.dendrogram(Z, ax=ax[2]) 

ax[3].set_title("sequence of observations") 
Z = hier.linkage(points, method="average") 
hier.dendrogram(Z, ax=ax[3]) 

plt.show() 

enter image description here