2017-12-31 159 views
1

Ich habe ein Array von Integer-Labels und ich möchte bestimmen, wie viele von jedem Etikett vorhanden ist und diese Werte in einem Array mit der gleichen Größe wie die Eingabe speichern. Dies kann mit der folgenden Schleife durchgeführt werden:Rückgabe Array von Zählern für jedes Merkmal der Eingabe

def counter(labels): 
    sizes = numpy.zeros(labels.shape) 
    for num in numpy.unique(labels): 
     mask = labels == num 
     sizes[mask] = numpy.count_nonzero(mask) 
return sizes 

mit Eingang:

array = numpy.array([ 
     [0, 1, 2, 3], 
     [0, 1, 1, 3], 
     [3, 1, 3, 1]]) 

counter() Rückkehr:

array([[ 2., 5., 1., 4.], 
     [ 2., 5., 5., 4.], 
     [ 4., 5., 4., 5.]]) 

jedoch für großen Arrays mit vielen einzigartigen Etikett, 60.000 in Mein Fall, das kostet viel Zeit. Dies ist der erste Schritt in einem komplexen Algorithmus und ich kann es mir nicht leisten, mehr als 30 Sekunden für diesen Schritt zu verwenden. Gibt es eine Funktion, die bereits existiert, die dies erreichen kann? Wenn nicht, wie kann ich die bestehende Schleife beschleunigen?

+1

Können Sie eine [MCVE] mit einer Probe Eingang und Ausgang? Warum funktioniert 'np.unique' nicht für Sie? –

Antwort

4

Ansatz # 1

Hier ist ein np.unique mit -

_, tags, count = np.unique(labels, return_counts=1, return_inverse=1) 
sizes = count[tags] 

Ansatz # 2

mit positiven Zahlen in labels, einfacher und effizienter Weise mit np.bincount -


Runtime Test

Einrichtung mit 60,000 eindeutigen positiven Zahlen und zwei solche Sätzen von Längen 100,0001000,000 und sind zeitlich gesteuert.

Set # 1:

In [192]: np.random.seed(0) 
    ...: labels = np.random.randint(0,60000,(100000)) 

In [193]: %%timeit 
    ...: sizes = np.zeros(labels.shape) 
    ...: for num in np.unique(labels): 
    ...:  mask = labels == num 
    ...:  sizes[mask] = np.count_nonzero(mask) 
1 loop, best of 3: 2.32 s per loop 

In [194]: %timeit np.bincount(labels)[labels] 
1000 loops, best of 3: 376 µs per loop 

In [195]: 2320/0.376 # Speedup figure 
Out[195]: 6170.212765957447 

Set # 2:

In [196]: np.random.seed(0) 
    ...: labels = np.random.randint(0,60000,(1000000)) 

In [197]: %%timeit 
    ...: sizes = np.zeros(labels.shape) 
    ...: for num in np.unique(labels): 
    ...:  mask = labels == num 
    ...:  sizes[mask] = np.count_nonzero(mask) 
1 loop, best of 3: 43.6 s per loop 

In [198]: %timeit np.bincount(labels)[labels] 
100 loops, best of 3: 5.15 ms per loop 

In [199]: 43600/5.15 # Speedup figure 
Out[199]: 8466.019417475727 
+1

Frohes neues Jahr !! –

+1

@ cᴏʟᴅsᴘᴇᴇᴅ Auch du wirst bald hoffentlich bei dir sein! – Divakar

Verwandte Themen