Efektívne numpy priradenie hodnoty cez boolean maska

0

Otázka

Mám boolean hodnotu masky priradenie problém si vyžaduje účinné boolean maska prevádzky.

Je to multi-rozmer masku a som pomocou einsum ak chcete dosiahnuť výsledok, ale prevádzka nie je veľmi efektívna, a ja som premýšľal, či môžem dostať nejakú pomoc s ním Tu je môj súčasný riešenie: (oboch mask, truth_value, false_value sú fiktívne údaje s dtype a tvar zápasy 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)

Je nejaký rýchlejší spôsob, ako získať objective uvedené mask, truth_value, false_value ?

Kým som čakal, prišiel na rýchlejší spô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 nejaké rýchlejšie alternatíva ?

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

Najlepšiu odpoveď

0

Môžete použiť Numba JIT k tomu, že efektívnejšie.

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čtu objective je 4.8 krát rýchlejšie na môj stroj.

Ak to nie je dostatočne rýchly, môžete sa pokúsiť parallelize kód pomocou parametra parallel=True a pomocou nb.prange namiesto range v i-založené slučky. To môže byť rýchlejšie, v dôsledku réžiu vytvárať nové témy. Na môj stroj (s 6 jadrá), paralelné verzie je 7.4 krát rýchlejšie (vytvorenie vlákna je dosť drahé v porovnaní s výkonom čase).

Ďalším možným optimalizácia je napísať priamo výsledok vo vyrovnávacej pridelené dopredu (to je len lepšie, ak budete volať túto funkciu viackrát s rovnakým pole veľkosti).

Tu sú celkovo časovanie na mojom stroji:

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

vďaka! to je naozaj rýchlejší ako môj einsum riešenie! trochu rýchlejší ako môj np.where +np.broadcast_to based riešenie.
yupbank

V iných jazykoch

Táto stránka je v iných jazykoch

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