Eficiente numpy asignación de valor a través de la máscara booleano

0

Pregunta

Tengo un booleano valor de la máscara de la asignación de problema requiere el uso eficiente booleano máscara de operación.

Es un multi-dimensión de la máscara y la estoy usando einsum para conseguir el resultado, pero la operación no es muy eficiente, y yo me pregunto, si puedo conseguir un poco de ayuda con esto Aquí está mi solución actual: (ambos mask, truth_value, false_value son datos ficticios con dtype y la forma de las coincidencias con mi 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)

¿Hay alguna manera más rápida de llegar objective dado mask, truth_value, false_value ?

Mientras estaba esperando, descubrió una manera más rápida

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

Pero, ¿hay alguna alternativa más rápida ?

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

Mejor respuesta

0

Usted puede utilizar el Numba JIT para hacerlo de manera más eficiente.

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)

El cálculo de objective es 4,8 veces más rápido que en mi máquina.

Si este no es lo suficientemente rápido, puede intentar paralelizar el código mediante el parámetro parallel=True y el uso de nb.prange en lugar de range en el i-basado en bucle. Esto no puede ser más rápido debido a la sobrecarga de crear nuevos hilos. En mi máquina (con 6 núcleos), la versión paralela es de 7,4 veces más rápido (la creación de hilos, es bastante caro en comparación con el tiempo de ejecución).

Otra posible la optimización es escribir directamente el resultado en un búfer asignado antes de tiempo (este es sólo mejor si se llama a esta función varias veces con el mismo tamaño de la matriz).

Aquí son los tiempos en mi máquina:

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

gracias! este es de hecho más rápido que mi einsum la solución! un poco más rápido de lo que mi np.where +np.broadcast_to basado en la solución.
yupbank

En otros idiomas

Esta página está en otros idiomas

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