2016-06-05 5 views
-1

Stelle möchte ich Clustering DBSCAN Algorithmus mit einer Datenmenge zu tun, die 3 Punkte enthält. Dies ist der Datensatz:ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist mehrdeutig. Verwenden a.any() oder a.All() Python DBSCAN 3 Dimensionen

1 5 7 
12 8 9 
2 4 10 
6 3 21 
11 13 0 
6 3 21 
11 13 0 
3 7 1 
1 9 2 
1 5 7 

ich Clustering mit diesem Code:

from math import sqrt, pow 

def __init__(eps=0.1, min_points=2): 
    eps = 10 
    min_points = 2 
    visited = [] 
    noise = [] 
    clusters = [] 
    dp = [] 

def cluster(data_points): 
    visited = [] 
    dp = data_points 
    c = 0 

    for point in data_points: 
     if point not in visited: 
      visited.append(point) 
      print point 
      neighbours = region_query(point) 
      #print neighbours 
      if len(neighbours) < min_points: 
       noise.append(point) 

      else: 
       c += 1 
       expand_cluster(c, neighbours) 

#cluster(data_points) 

def expand_cluster(cluster_number, p_neighbours): 
    cluster = ("Cluster: %d" % cluster_number, []) 
    clusters.append(cluster) 
    new_points = p_neighbours 
    while new_points: 
     new_points = pool(cluster, new_points) 


def region_query(p): 
    result = [] 
    for d in dp: 
     distance = (((d[0] - p[0])**2 + (d[1] - p[1])**2 + (d[2] - p[2])**2)**0.5) 
     print distance 
     if distance <= eps: 
      result.append(d) 
    return result 

#p_neighbours = region_query(p=pcsv) 

def pool(cluster, p_neighbours): 
    new_neighbours = [] 
    for n in p_neighbours: 
     if n not in visited: 
      visited.append(n) 
      n_neighbours = region_query(n) 
      if len(n_neighbours) >= min_points: 
       new_neighbours = unexplored(p_neighbours, n_neighbours) 
     for c in clusters: 
      if n not in c[1] and n not in cluster[1]: 
       cluster[1].append(n) 
    return new_neighbours 

@staticmethod 
def unexplored(x, y): 
    z = [] 
    for p in y: 
     if p not in x: 
      z.append(p) 
    return z 

in diesem Code gibt es point und n Variablen, die mit data_points gleichen sind, die den Datensatz enthält. Wenn ich manuell lese denke ich, dass dieser Code tatsächlich funktionieren kann, aber wenn ich cluster() Funktion ausführen, gibt es einen Fehler.

Traceback (most recent call last): 

    File "<ipython-input-39-77eb6be20d82>", line 2, in <module> 
    if n not in visited: 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

Ich weiß nicht, warum dieser Code noch diesen Fehler erhalten, während ich n oder point Variable mit Indexdaten ändern. Hast du eine Idee was mit diesem Code nicht stimmt? Wie kann ich es zum Laufen bringen?

danken Ihnen für Ihre Hilfe ..

+1

Sie haben ernsthafte Probleme mit lokalen und globalen Variablen in Ihrem Code. – Daniel

Antwort

0

Wenn Sie numpy verwenden, sollten Sie Masken statt Listen verwenden:

def cluster(data_points, eps=0.1, min_points=3): 
    cluster_numbers = numpy.zeros(len(data_points), dtype=int) 
    c = 0 
    for idx, point in enumerate(data_points): 
     if cluster_numbers[idx] == 0: 
      print point 
      neighbours = region_query(data_points, point, eps) 
      #print neighbours 
      if sum(neighbours) < min_points: 
       # noise 
       cluster_numbers[idx] = -1 
      else: 
       c += 1 
       expand_cluster(c, data_points, cluster_numbers, neighbours, eps) 
    return cluster_numbers 

def region_query(points, point, eps=0.1): 
    distance = ((points-point)**2).sum(axis=1) ** 0.5 
    return distance <= eps 

def expand_cluster(cluster_number, points, cluster_numbers, new_points, eps=0.1): 
    while True: 
     indices = numpy.where(new_points & (cluster_numbers==0))[0] 
     if not len(indices): 
      break 
     new_points = False 
     for idx in indices: 
      cluster_numbers[idx] = cluster_number 
      new_points = new_points | region_query(points, points[idx], eps) 

Was man bekommt, ist ein Array mit Integer-Zahlen, eine für jeden Eingabepunkt. Positionen mit -1 als Wert sind Rauschpunkte, 1 .. n sind die verschiedenen Cluster.

So können Sie die Punkte für einen Cluster erhalten:

cluster_numbers = cluster(data_points) 
noise_points = data_points[cluster_numbers == -1] 
print "Total Clusters:", cluster_numbers.max() 
for idx in range(1, cluster_numbers.max() + 1): 
    cluster_points = data_points[cluster_numbers == idx] 
    print "Cluster %d as %d points" % (idx, len(cluster_points)) 
+0

vielen Dank für die Antworten, Entschuldigung, möchten Sie zeigen, wie bekomme ich den Cluster und die Anzahl der Cluster? – estu

+0

@estu: Antwort aktualisiert. – Daniel

1

Der Fehler aus diesen Linien ergibt:

if point not in visited: 
     visited.append(point) 

Der in Operator ruft list.__contains__, die Iteration über die Elemente in der Liste visited wenn einer von ihnen zu sehen sind gleich point. Gleichheitsprüfungen zwischen numpigen Arrays ergeben jedoch keinen einzelnen booleschen Wert, sondern ein Array von bools, die die elementweisen Vergleiche der Elemente in den Arrays darstellen. Zum Beispiel ist das Ergebnis von array([1, 2]) == array([1, 3])array([True, False]), nicht nur False.

, die so weit in Ordnung ist. Vergleiche in Python erlauben es, jedes gewünschte Objekt zurückzugeben. Wenn Gleichheit jedoch von in getestet wird, benötigt es am Ende ein boolesches Ergebnis, so dass bool auf das Ergebnis des Vergleichs aufgerufen wird. Die Ausnahme, die Sie erhalten haben, kommt von bool(array([...])), die, wie die Nachricht sagt, mehrdeutig ist. Sollte bool(array([True, False]))True oder False sein? Die Bibliothek weigert sich, für Sie zu raten.

Leider, ich glaube nicht, dass es eine wirklich gute Möglichkeit ist, dies zu umgehen. Vielleicht könnten Sie Ihre Punkte in Tupel konvertieren, bevor Sie sie in visited speichern? Als einen netten Nebeneffekt würde dies eine set anstelle einer Liste verwenden (da Tupel hashbar sind).

Ein weiteres Problem, das Sie haben, ist, dass die Gleichstellung Prüfung zwischen Schwimmern zu einer Ungenauigkeit von Natur aus anfällig ist. Zwei Zahlen, die sollten gleich sein, können tatsächlich nicht gleich sein, wenn sie mit Floats durch verschiedene Berechnungen berechnet verglichen. Zum Beispiel ist 0.1 + 0.2 == 0.3False, weil die Rundung auf beiden Seiten des Gleichheitszeichens nicht auf die gleiche Weise funktioniert. Auch wenn Sie zwei Punkte haben, die gleich sein sollten, können Sie sie möglicherweise nicht in Ihren Daten nur mit Gleichheitstests ermitteln. Sie müssten ihre Differenz berechnen und sie mit einem kleinen Wert von espilon vergleichen, um den maximalen Fehler abzuschätzen, der sich aus Ihren Berechnungen ergeben hätte.

Verwandte Themen