Efektivní numpy přiřazení hodnoty pomocí booleovské maska

0

Otázka

Mám boolean hodnota masky přiřazení problém vyžaduje efektivní boolean maska provoz.

Je to multi-rozměr masky a já jsem s použitím einsum k dosažení výsledku, ale operace není příliš efektivní, a zajímalo by mě, jestli můžu dostat nějakou pomoc s tím Tady je moje aktuální řešení: (jak mask, truth_value, false_value jsou dummy data s dtype a tvar odpovídá na můj problém.

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)

Existuje nějaký rychlejší způsob, jak se dostat objective vzhledem mask, truth_value, false_value ?

Zatímco jsem čekal, zjistil, rychlejší způsob

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

Ale je tam nějaký rychlejší alternativu ?

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

Nejlepší odpověď

0

Můžete použít Numba JIT dělat efektivněji.

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)

Výpočet objective je 4,8 krát rychleji na můj stroj.

Pokud to není dost rychle, můžete se pokusit paralelizovat kód pomocí parametru parallel=True a pomocí nb.prange místo range v i-založené smyčky. To nemusí být rychlejší vzhledem k režii vytváření nových vláken. Na mém stroji (6 jader), paralelní verze je 7,4 krát rychlejší (vytváření vláken je docela drahé ve srovnání s, čas spuštění).

Další možné optimalizace je napsat přímo výsledek do vyrovnávací paměti přidělené dopředu (je to jen lepší, pokud si tuto funkci volat vícekrát se stejnou velikosti pole).

Zde jsou celkové časování na můj stroj:

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

díky!!! to je skutečně rychlejší, než můj einsum řešení! trochu rychlejší než moje np.where +np.broadcast_to řešení na bázi.
yupbank

V jiných jazycích

Tato stránka je v jiných jazycích

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