Efficiente numpy valore di assegnazione di via booleano maschera

0

Domanda

Ho un booleano valore di maschera di assegnazione problema richiede un efficiente boolean maschera di funzionamento.

Si tratta di un multi-dimensione maschera e sto usando einsum per raggiungere il risultato, ma l'operazione non è molto efficiente, e mi chiedo, se non è possibile ottenere qualche aiuto con esso Ecco la mia attuale soluzione: (sia mask, truth_value, false_value sono dati fittizi con tipo dimensione e forma corrisponde al mio problema.

mask = np.random.randn(1000, 50)> 0.5
truth_value = np.random.randn(50, 10)
false_value = np.random.randn(10)
objective = np.einsum('ij,jk->ijk', mask, truth_value) + np.einsum('ij,k->ijk', ~mask, false_value)

C'è qualche modo più veloce per arrivare objective dato mask, truth_value, false_value ?

Mentre ero in attesa, ho scoperto un modo più veloce

objective = np.where(mask[...,np.newaxis], np.broadcast_to(truth_value, (1000, 50, 10)), np.broadcast_to(false_value,  (1000, 50, 10)))

Ma c'è qualche alternativa più veloce ?

mask numpy python
2021-11-21 23:00:26
1

Migliore risposta

0

È possibile utilizzare il Numba JIT per farlo in modo più efficiente.

import numpy as np
import numba as nb

@nb.njit('float64[:,:,::1](bool_[:,::1], float64[:,::1], float64[::1])')
def blend(mask, truth_value, false_value):
    n, m = mask.shape
    l = false_value.shape[0]
    assert truth_value.shape == (m, l)
    result = np.empty((n, m, l), dtype=np.float64)
    for i in range(n):
        for j in range(m):
            if mask[i, j]:
                result[i, j, :] = truth_value[j, :]
            else:
                result[i, j, :] = false_value[:]
    return result

mask = np.random.randn(1000, 50) > 0.5
truth_value = np.random.randn(50, 10)
false_value = np.random.randn(10)
objective = blend(mask, truth_value, false_value)

Il calcolo di objective è di 4,8 volte più veloce sulla mia macchina.

Se questo non è abbastanza veloce, si può provare a parallelizzare il codice utilizzando il parametro parallel=True e l'utilizzo di nb.prange invece di range l'ho basato su loop. Questo non può essere più veloce a causa del sovraccarico di creazione di un nuovo thread. Sulla mia macchina (con 6 core), la versione parallela è di 7,4 volte più veloce (la creazione del thread è abbastanza costoso rispetto al tempo di esecuzione).

Un altro possibile ottimizzazione è quello di scrivere direttamente il risultato in un buffer allocato in anticipo (questo è solo meglio se si chiama questa funzione più volte con la stessa dimensione della matrice).

Ecco la complessiva tempi sulla mia macchina:

np.einsum:         4.32 ms
np.where:          1.72 ms
numba sequential:  0.89 ms
numba parallel:    0.58 ms
2021-11-21 23:52:43

grazie! questa, infatti, è più veloce rispetto al mio einsum soluzione! un po ' più veloce rispetto al mio np.where +np.broadcast_to soluzione a base di.
yupbank

In altre lingue

Questa pagina è in altre lingue

Русский
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................