Efficace numpy affectation de la valeur via boolean masque

0

La question

J'ai un boolean valeur du masque de l'attribution problème l'exige efficace boolean masque de fonctionnement.

C'est un multi-dimension de masque et je suis en utilisant einsum pour atteindre le résultat, mais l'opération n'est pas très efficace, et je me demandais, si je peux obtenir un peu d'aide avec elle Voici ma solution actuelle: (les deux mask, truth_value, false_value sont des données factices avec dtype et la forme correspond à mon problème.

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)

Est-il un moyen plus rapide pour obtenir objective compte tenu de mask, truth_value, false_value ?

Pendant que j'attendais, trouvé un moyen plus rapide

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

Mais est-il une alternative plus rapide ?

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

La meilleure réponse

0

Vous pouvez utiliser le Numba JIT pour le faire plus efficacement.

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)

Le calcul de objective est 4,8 fois plus vite sur ma machine.

Si ce n'est pas assez rapide, vous pouvez essayer de paralléliser le code à l'aide du paramètre parallel=True et à l'aide de nb.prange au lieu de range dans le i de boucles. Cela ne peut pas être plus rapide en raison de la surcharge de créer de nouveaux threads. Sur ma machine (avec 6 cœurs), la version parallèle est de 7,4 fois plus rapide (la création de threads est assez cher par rapport au temps d'exécution).

Une autre optimisation possible est d'écrire directement le résultat dans une mémoire tampon allouée à l'avance (ce n'est que mieux si vous appelez cette fonction plusieurs fois avec la même taille de la matrice).

Voici l'ensemble des timings sur ma machine:

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

merci! c'est en effet plus vite que mon einsum solution! un peu plus vite que mon np.where +np.broadcast_to en fonction de la solution.
yupbank

Dans d'autres langues

Cette page est dans d'autres langues

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