2016-05-10 9 views
3

Ich habe eine numpy 2-d Heatmap und zwei überlappende Masken (mit verschiedenen Größen). Ich möchte die Elemente innerhalb dieser Masken mit einem eindeutigen numpy Array pro Maske multiplizieren. Zuerst entferne ich die überlappenden Koordinaten von einer der Masken. Dann möchte ich die Heatmap-Elemente pro Maske extrahieren, ohne Schleifen zu verwenden.Numpy 2-d Elemente pro Maske separat auswählen und multiplizieren (ohne Schleifen)

Der Grund dafür ist, dass ich in Wirklichkeit über 10000 Masken habe, aus denen sich eine variable Zahl überschneidet. Außerdem habe ich 25 Heatmaps mit einer Größe von 80000 * 80000. Die Herausforderung besteht darin, mit diesen Zahlen einen Alorithmus zu erstellen, der schnell und nicht zu speicherintensiv ist.

Beispiel Heatmap:

heatmap = array([[236, 235, 225, 226, 215], 
    [214, 217, 220, 215, 228], 
    [238, 227, 209, 210, 220], 
    [251, 224, 225, 220, 229], 
    [ 0, 226, 231, 233, 240]], dtype=uint64) 

Boolean Masken:

bool1=array([[ True, True, True, True, False], 
    [ True, True, True, True, False], 
    [ True, True, True, True, False], 
    [ True, True, True, False, False], 
    [False, False, False, False, False]], dtype=bool) 

bool2=array([[False, False, False, False, False], 
    [False, False, False, True, False], 
    [False, False, True, True, True], 
    [False, False, True, True, True], 
    [False, False, True, True, True]], dtype=bool) 

entfernen Koordinaten von der zweiten Maske überlappende:

bool2[bool1]=False 

Im Moment habe ich die Heatmap Elemente pro Maske wie folgt auswählen :

combined_bool=[bool1,bool2] 
multiply_array1=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]) 
multiply_array2=np.array([1,2,3,4,5,6]) #only 6 Trues in bool2 after duplicate cell removal 
combined_mult= [multiply_array1,multiply_array2] 

for i in range(0,len(combined_bool)): 
    mask=combined_bool[i] 
    heatmap[mask]=heatmap[mask]*combined_mult[i] 

#output 
array([[ 236, 470, 675, 904, 215], 
    [1070, 1302, 1540, 1720, 228], 
    [2142, 2270, 2299, 2520, 220], 
    [3263, 3136, 3375, 440, 687], 
    [ 0, 226, 924, 1165, 1440]], dtype=uint64) 

Wie kann ich diese Multiplikation pro Maske ohne die Verwendung einer For-Schleife machen?

+0

Wie viele überlappende Masken arbeiten Sie in Ihrem tatsächlichen Fall? – Divakar

+0

Dies ist eine variable Zahl, ich habe auch mehrere Heatmaps. –

+0

Ich meinte typisch. Weil das "len (combined_bool)" entscheiden würde und wenn das eine kleine Zahl ist, lohnt es sich nicht, die Vektorisierung zu machen. – Divakar

Antwort

2

Hier ist ein vektorisiert Ansatz NumPy broadcasting und einige andere Methoden -

# Concatenate all input multiply_arrays  
combined_mult_arr = np.hstack((multiply_array1,multiply_array2)) 

# Concatenate all input boolean arrays  
B = np.dstack((bool1,bool2)) 

# 3D mask with the uniqueness set 
unqmask = (B.argmax(2) == np.arange(B.shape[2])[:,None,None]) & B.any(2) 

# Get True indices in each 3D slice. Index into 1D version of heatmap & multiply 
R,C = np.where(unqmask.reshape(unqmask.shape[0],-1)) 
heatmap.ravel()[C] *= combined_mult_arr 

Nun, um den Code zu überprüfen, lassen Sie uns einen weiteren Eingang boolean und Multiplikation Array einzuführen. Also, lassen Sie uns eine zusätzliche bool3 wie bool2 und setzen (0,4) Element als True. Dementsprechend haben wir zusätzliche multiply_array3 als np.array([10]). Daher würde ein Beispiel, das mit solchen Modifikationen ausgeführt wird, wie folgt aussehen.

1) Eingänge:

In [126]: heatmap 
Out[126]: 
array([[ 236, 470, 675, 904, 2150], 
     [1070, 1302, 1540, 1720, 228], 
     [2142, 2270, 2299, 2520, 220], 
     [3263, 3136, 3375, 440, 687], 
     [ 0, 226, 924, 1165, 1440]]) 

In [127]: bool1 
Out[127]: 
array([[ True, True, True, True, False], 
     [ True, True, True, True, False], 
     [ True, True, True, True, False], 
     [ True, True, True, False, False], 
     [False, False, False, False, False]], dtype=bool) 

In [128]: bool2 
Out[128]: 
array([[False, False, False, False, False], 
     [False, False, False, True, False], 
     [False, False, True, True, True], 
     [False, False, True, True, True], 
     [False, False, True, True, True]], dtype=bool) 

In [129]: bool3 
Out[129]: 
array([[False, False, False, False, True], 
     [False, False, False, True, False], 
     [False, False, True, True, True], 
     [False, False, True, True, True], 
     [False, False, True, True, True]], dtype=bool) 

In [130]: multiply_array1=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]) 
    ...: multiply_array2=np.array([1,2,3,4,5,6]) 
    ...: multiply_array3=np.array([10]) 
    ...: 

2) Führen Sie den Code:

In [133]: combined_mult_arr = np.hstack((multiply_array1,\ 
    ...:      multiply_array2,multiply_array3)) 
    ...: B = np.dstack((bool1,bool2,bool3)) 
    ...: unqmask = (B.argmax(2) == np.arange(B.shape[2])[:,None,None]) & B.any(2) 
    ...: R,C = np.where(unqmask.reshape(unqmask.shape[0],-1)) 
    ...: heatmap.ravel()[C] *= combined_mult_arr 
    ...: 

3) prüfen die Ausgabe:

In [136]: heatmap 
Out[136]: 
array([[ 236, 470, 675, 904, 2150], 
     [1070, 1302, 1540, 1720, 228], 
     [2142, 2270, 2299, 2520, 220], 
     [3263, 3136, 3375, 440, 687], 
     [ 0, 226, 924, 1165, 1440]]) 

Wie man sehen kann, ist der einzige Unterschied in der Dieser Ausgang im Vergleich mit dem Ausgang mit zwei Eingängen ist 2150 bei (0,4) gegen 215 vorher. Dies liegt an dem dritten booleschen Array und dem dritten Multiplikations-Array mit dem Element 10, das für die Skalierung des Elements durch 10 verantwortlich ist.

+0

Vielen Dank, ich werde es in meinem Skript implementieren und Ihnen den Unterschied in der Berechnungszeit mitteilen, wenn ich fertig bin! –

+0

Leider wird die Rechenzeit mit ca. 15 Sekunden verlangsamt.Mit 426 Masken auf 15 Heatmaps mit der Form 1400 * 1035 –

+0

Zusätzlich bekomme ich einen Speicherfehler, der vorher nicht da war, wenn ich eine größere Heatmap verwende. Das liegt wahrscheinlich am dstack –